diff --git a/index.html b/index.html index 94efc7c9b153..f69f83579fdf 100755 --- a/index.html +++ b/index.html @@ -351,7 +351,7 @@
-
+

Celo's optimism

@@ -369,18 +369,18 @@
-
+24006
-
-165
+
+60593
+
-11981
-
+594
-
-624
+
+1139
+
-1060
-
+

This is an overview of the changes in Celo’s optimism implementation, a fork of Optimism’s optimism.

@@ -393,7 +393,7 @@
-
+
+ + +
+ +
+
+
+ + +
+
+ +
+
+
+ + +
+ +
+
+
+ + +
+
+ +
+
+
+ + +
+ +
+
+
+ + +
+
+ +
+
+
+ + +
+
+
+ + +
+ +
+
+
+ + +
+
+ +
+
+
+ + +
+ +
+
+
+ + +
+
+ +
+
+
+ + +
+ +
+
+
+ + +
+
+ +
+
+
+ + +
+ +
+
+
+ +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+1
+
-0
+ +
+ +
+
+
diff --git OP/op-chain-ops/.gitignore CELO/op-chain-ops/.gitignore +index ba077a4031add5b3a04384f8b9cfc414efbf47dd..2d94eb56a7db0e847b3ebd82bd6f03f325993ec6 100644 +--- OP/op-chain-ops/.gitignore ++++ CELO/op-chain-ops/.gitignore +@@ -1 +1,3 @@ + bin ++intent.toml ++state.json +\ No newline at end of file
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+29
+
-0
+ +
+ +
+
+
diff --git OP/op-chain-ops/Dockerfile CELO/op-chain-ops/Dockerfile +new file mode 100644 +index 0000000000000000000000000000000000000000..5aa278ed6b27e78ab6648f3064a3fcce17a06476 +--- /dev/null ++++ CELO/op-chain-ops/Dockerfile +@@ -0,0 +1,29 @@ ++FROM golang:1.21.1-alpine3.18 AS builder ++ ++RUN apk --no-cache add make ++ ++COPY ./go.mod /app/go.mod ++COPY ./go.sum /app/go.sum ++ ++WORKDIR /app ++ ++RUN go mod download ++ ++COPY ./op-service /app/op-service ++COPY ./op-node /app/op-node ++COPY ./op-alt-da /app/op-alt-da ++COPY ./op-chain-ops /app/op-chain-ops ++WORKDIR /app/op-chain-ops ++RUN make celo-migrate ++ ++FROM alpine:3.18 ++RUN apk --no-cache add ca-certificates bash rsync ++ ++# RUN addgroup -S app && adduser -S app -G app ++# USER app ++WORKDIR /app ++ ++COPY --from=builder /app/op-chain-ops/bin/celo-migrate /app ++ENV PATH="/app:${PATH}" ++ ++ENTRYPOINT ["/app/celo-migrate"]
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+33
+
-1
+ +
+ +
+
+
diff --git OP/op-chain-ops/Makefile CELO/op-chain-ops/Makefile +index 1f119a95f62dc584cf834de1c33c48e3c1c639ad..6a173c05103120b58c159c8c8418ae9c9b31bcda 100644 +--- OP/op-chain-ops/Makefile ++++ CELO/op-chain-ops/Makefile +@@ -1,3 +1,26 @@ ++GITCOMMIT ?= $(shell git rev-parse HEAD) ++GITDATE ?= $(shell git show -s --format='%ct') ++ ++# Find the github tag that points to this commit. If none are found, set the version string to "untagged" ++# Prioritizes release tag, if one exists, over tags suffixed with "-rc" ++VERSION ?= $(shell tags=$$(git tag --points-at $(GITCOMMIT) | grep '^op-deployer/' | sed 's/op-deployer\///' | sort -V); \ ++ preferred_tag=$$(echo "$$tags" | grep -v -- '-rc' | tail -n 1); \ ++ if [ -z "$$preferred_tag" ]; then \ ++ if [ -z "$$tags" ]; then \ ++ echo "untagged"; \ ++ else \ ++ echo "$$tags" | tail -n 1; \ ++ fi \ ++ else \ ++ echo $$preferred_tag; \ ++ fi) ++ ++LDFLAGSSTRING +=-X main.GitCommit=$(GITCOMMIT) ++LDFLAGSSTRING +=-X main.GitDate=$(GITDATE) ++LDFLAGSSTRING +=-X github.com/ethereum-optimism/optimism/op-chain-ops/deployer/version.Version=$(VERSION) ++LDFLAGSSTRING +=-X github.com/ethereum-optimism/optimism/op-chain-ops/deployer/version.Meta=$(VERSION_META) ++LDFLAGS := -ldflags "$(LDFLAGSSTRING)" ++ + # Use the old Apple linker to workaround broken xcode - https://github.com/golang/go/issues/65169 + ifeq ($(shell uname),Darwin) + FUZZLDFLAGS := -ldflags=-extldflags=-Wl,-ld_classic +@@ -9,13 +32,23 @@ + receipt-reference-builder: + go build -o ./bin/receipt-reference-builder ./cmd/receipt-reference-builder/*.go +  ++celo-migrate: ++ go build -o ./bin/celo-migrate ./cmd/celo-migrate/*.go ++ + test: + go test ./... +  ++op-deployer: ++ GOOS=$(TARGETOS) GOARCH=$(TARGETARCH) CGO_ENABLED=0 go build -v $(LDFLAGS) -o ./bin/op-deployer ./cmd/op-deployer/main.go ++ + fuzz: + go test $(FUZZLDFLAGS) -run NOTAREALTEST -v -fuzztime 10s -fuzz=FuzzEncodeDecodeWithdrawal ./crossdomain + go test $(FUZZLDFLAGS) -run NOTAREALTEST -v -fuzztime 10s -fuzz=FuzzEncodeDecodeLegacyWithdrawal ./crossdomain + go test $(FUZZLDFLAGS) -run NOTAREALTEST -v -fuzztime 10s -fuzz=FuzzAliasing ./crossdomain + go test $(FUZZLDFLAGS) -run NOTAREALTEST -v -fuzztime 10s -fuzz=FuzzVersionedNonce ./crossdomain +  +-.PHONY: test fuzz ++ ++sync-standard-version: ++ curl -Lo ./deployer/opcm/standard-versions.toml https://raw.githubusercontent.com/ethereum-optimism/superchain-registry/refs/heads/main/validation/standard/standard-versions.toml ++ ++.PHONY: test fuzz op-deployer sync-standard-version +\ No newline at end of file
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+136
+
-0
+ +
+ +
+
+
diff --git OP/op-chain-ops/cmd/celo-migrate/README.md CELO/op-chain-ops/cmd/celo-migrate/README.md +new file mode 100644 +index 0000000000000000000000000000000000000000..807a4f0b1606b12810bbd95ccc593f3f22794b31 +--- /dev/null ++++ CELO/op-chain-ops/cmd/celo-migrate/README.md +@@ -0,0 +1,136 @@ ++# Celo L2 Migration Script ++ ++## Overview ++ ++This script migrates a Celo L1 database (old datadir) into a new database compatible with Celo L2 (new datadir). It consists of 3 main processes that respectively migrate ancient blocks, non-ancient blocks and state. Migrated data is copied into a new datadir, leaving the old datadir unchanged. ++ ++To minimize migration downtime, the script is designed to run in two stages: ++1. The `pre migration` stage can be run ahead of the `full migration` and will process as much of the migration as possible up to that point. ++2. The `full migration` can then be run to finish migrating new blocks that were created after the `pre migration` and apply necessary state changes on top of the migration block. ++ ++### Pre migration ++ ++The `pre migration` consists of two parts that are run in parallel: ++- Copy and transform the ancient / frozen blocks (i.e. all blocks before the last 90000). ++- Copy over the rest of the database using `rsync`. ++ ++The ancients db is migrated sequentially because it is append-only, while the rest of the database is copied and then transformed in-place. We use `rsync` because it has flags for ignoring the ancients directory, skipping any already copied files and deleting any extra files in the new db, ensuring that we can run the script multiple times and only copy over actual updates. ++ ++The `pre migration` step is still run during a `full migration` but it will be much quicker as only newly frozen blocks and recent file changes need to be migrated. ++ ++### Full migration ++ ++During the `full migration`, we re-run the `pre migration` step to capture any updates since the last `pre migration` and then apply in-place changes to non-ancient blocks and state. While this is happening, the script also checks for any stray ancient blocks that have remained in leveldb despite being frozen and removes them from the new db. Non-ancient blocks are then transformed to ensure compatibility with the L2 codebase. ++ ++Finally after all blocks have been migrated, the script performs a series of modifications to the state db: ++1. First, it deploys the L2 smart contracts by iterating through the genesis allocs passed to the script and setting the nonce, balance, code and storage for each address accordingly, overwritting existing data if necessary. ++2. Finally, these changes are committed to the state db to produce a new state root and create the first Celo L2 block. ++ ++### Notes ++ ++> [!TIP] ++> See `--help` for how to run each portion of the script individually, along with other configuration options. ++ ++The longest running section of the script is the ancients migration, followed by the `rsync` command. By running these together in a `pre migration` we greatly reduce how long they will take during the `full migration`. Changes made to non-ancient blocks and state during a `full migration` are erased by the next `rsync` command. ++ ++The script outputs a `rollup-config.json` file that is passed to the sequencer in order to start the L2 network. ++ ++### Running the script ++ ++> [!NOTE] ++> You will need `rsync` to run this script if it's not already installed. ++ ++From the `op-chain-ops` directory, first build the script by running: ++ ++```bash ++make celo-migrate ++``` ++ ++You can then run the script as follows: ++ ++```bash ++go run ./cmd/celo-migrate --help ++``` ++ ++#### Running with local test setup (Alfajores / Holesky) ++ ++To test the script locally, we can migrate an Alfajores database and use Holesky as our L1. The input files needed for this can be found in `./testdata`. The necessary smart contracts have already been deployed on Holesky. ++ ++##### Pull down the latest Alfajores database snapshot ++ ++```bash ++gcloud alpha storage cp gs://celo-chain-backup/alfajores/chaindata-latest.tar.zst alfajores.tar.zst ++``` ++ ++Unzip and rename ++ ++```bash ++tar --use-compress-program=unzstd -xvf alfajores.tar.zst ++mv chaindata ./data/alfajores_old ++``` ++ ++##### Generate test allocs file ++ ++The state migration takes in an allocs file that specifies the l2 state changes to be made during the migration. This file can be generated from the deploy config and l1 contract addresses by running the following from the `contracts-bedrock` directory. ++ ++```bash ++CONTRACT_ADDRESSES_PATH=../../op-chain-ops/cmd/celo-migrate/testdata/deployment-l1-dango.json \ ++DEPLOY_CONFIG_PATH=../../op-chain-ops/cmd/celo-migrate/testdata/deploy-config-dango.json \ ++STATE_DUMP_PATH=../../op-chain-ops/cmd/celo-migrate/testdata/l2-allocs-dango.json \ ++forge script ./scripts/L2Genesis.s.sol:L2Genesis \ ++--sig 'runWithStateDump()' ++``` ++ ++This should output the allocs file to `./testdata/l2-allocs-dango.json`. If you encounter difficulties with this and want to just continue testing the script, you can alternatively find the allocs file [here](https://storage.googleapis.com/cel2-rollup-files/alfajores-mvp/l2-allocs.json). ++ ++##### Run script with test configuration ++ ++```bash ++go run ./cmd/celo-migrate pre \ ++--old-db ./data/alfajores_old \ ++--new-db ./data/alfajores_new ++``` ++ ++Running the pre-migration script should take ~5 minutes. This script copies and transforms ancient blocks and, in parallel, copies over all other chaindata without transforming it. This can be re-run mutliple times leading up to the full migration, and should only migrate updates to the old db between re-runs. ++ ++```bash ++go run ./cmd/celo-migrate full \ ++--deploy-config ./cmd/celo-migrate/testdata/deploy-config-dango.json \ ++--l1-deployments ./cmd/celo-migrate/testdata/deployment-l1-dango.json \ ++--l1-rpc https://ethereum-holesky-rpc.publicnode.com \ ++--l2-allocs ./cmd/celo-migrate/testdata/l2-allocs-dango.json \ ++--outfile.rollup-config ./cmd/celo-migrate/testdata/rollup-config-dango.json \ ++--old-db ./data/alfajores_old \ ++--new-db ./data/alfajores_new ++``` ++ ++Running the full migration script re-runs the pre-migration script once to migrate any new changes to the old db that have occurred since the last pre-migration. It then performs in-place transformations on the non-ancient blocks and performs the state migration as well. ++ ++#### Running for Cel2 migration ++ ++##### Generate allocs file ++ ++You can generate the allocs file needed to run the migration with the following script in `contracts-bedrock` ++ ++```bash ++CONTRACT_ADDRESSES_PATH=<PATH_TO_CONTRACT_ADDRESSES> \ ++DEPLOY_CONFIG_PATH=<PATH_TO_MY_DEPLOY_CONFIG> \ ++STATE_DUMP_PATH=<PATH_TO_WRITE_L2_ALLOCS> \ ++forge script scripts/L2Genesis.s.sol:L2Genesis \ ++--sig 'runWithStateDump()' ++``` ++ ++##### Dry-run / pre-migration ++ ++To minimize downtime caused by the migration, node operators can prepare their Cel2 databases by running the pre-migration command a day ahead of the actual migration. This will pre-populate the new database with most of the ancient blocks needed for the final migration and copy over other chaindata without transforming it. ++ ++If node operators would like to practice a `full migration` they can do so and reset their databases to the correct state by running another `pre migration` afterward. ++ ++> [!IMPORTANT] ++> The pre-migration should be run using a chaindata snapshot, rather than a db that is being used by a node. To avoid network downtime, we recommend that node operators do not stop any nodes in order to perform the pre-migration. ++ ++Node operators should inspect their migration logs after the dry-run to ensure the migration completed succesfully and direct any questions to the Celo developer community on Discord before the actual migration. ++ ++##### Final migration ++ ++On the day of the actual Cel2 migration, the `full migration` script can be run using the datadir of a Celo L1 node that has halted on the migration block. Far in advance of the migration, a version of `celo-blockchain` will be distributed where a flag can specify a block to halt on. When the Celo community aligns on a migration block, node operators will start / restart their nodes with this flag specifying the migration block. Their nodes will halt when this block is reached, at which point they will be able to run `full migration` and begin syncing with the Celo L2 network.
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+232
+
-0
+ +
+ +
+
+
diff --git OP/op-chain-ops/cmd/celo-migrate/ancients.go CELO/op-chain-ops/cmd/celo-migrate/ancients.go +new file mode 100644 +index 0000000000000000000000000000000000000000..183c81ed50deecc5506c72193a2d2a2cdf366633 +--- /dev/null ++++ CELO/op-chain-ops/cmd/celo-migrate/ancients.go +@@ -0,0 +1,232 @@ ++package main ++ ++import ( ++ "context" ++ "fmt" ++ "path/filepath" ++ ++ "github.com/ethereum/go-ethereum/common" ++ "github.com/ethereum/go-ethereum/core/rawdb" ++ "github.com/ethereum/go-ethereum/ethdb" ++ "github.com/ethereum/go-ethereum/log" ++ "golang.org/x/sync/errgroup" ++) ++ ++// RLPBlockRange is a range of blocks in RLP format ++type RLPBlockRange struct { ++ start uint64 ++ hashes [][]byte ++ headers [][]byte ++ bodies [][]byte ++ receipts [][]byte ++ tds [][]byte ++} ++ ++// NewChainFreezer is a small utility method around NewFreezer that sets the ++// default parameters for the chain storage. ++func NewChainFreezer(datadir string, namespace string, readonly bool) (*rawdb.Freezer, error) { ++ const freezerTableSize = 2 * 1000 * 1000 * 1000 ++ // chainFreezerNoSnappy configures whether compression is disabled for the ancient-tables. ++ // Hashes and difficulties don't compress well. ++ var chainFreezerNoSnappy = map[string]bool{ ++ rawdb.ChainFreezerHeaderTable: false, ++ rawdb.ChainFreezerHashTable: true, ++ rawdb.ChainFreezerBodiesTable: false, ++ rawdb.ChainFreezerReceiptTable: false, ++ rawdb.ChainFreezerDifficultyTable: true, ++ } ++ return rawdb.NewFreezer(datadir, namespace, readonly, freezerTableSize, chainFreezerNoSnappy) ++} ++ ++func migrateAncientsDb(ctx context.Context, oldDBPath, newDBPath string, batchSize, bufferSize uint64) (uint64, uint64, error) { ++ defer timer("ancients")() ++ ++ oldFreezer, err := NewChainFreezer(filepath.Join(oldDBPath, "ancient"), "", false) // Can't be readonly because we need the .meta files to be created ++ if err != nil { ++ return 0, 0, fmt.Errorf("failed to open old freezer: %w", err) ++ } ++ defer oldFreezer.Close() ++ ++ newFreezer, err := NewChainFreezer(filepath.Join(newDBPath, "ancient"), "", false) ++ if err != nil { ++ return 0, 0, fmt.Errorf("failed to open new freezer: %w", err) ++ } ++ defer newFreezer.Close() ++ ++ numAncientsOld, err := oldFreezer.Ancients() ++ if err != nil { ++ return 0, 0, fmt.Errorf("failed to get number of ancients in old freezer: %w", err) ++ } ++ ++ numAncientsNewBefore, err := newFreezer.Ancients() ++ if err != nil { ++ return 0, 0, fmt.Errorf("failed to get number of ancients in new freezer: %w", err) ++ } ++ ++ if numAncientsNewBefore >= numAncientsOld { ++ log.Info("Ancient Block Migration Skipped", "process", "ancients", "ancientsInOldDB", numAncientsOld, "ancientsInNewDB", numAncientsNewBefore) ++ return numAncientsNewBefore, numAncientsNewBefore, nil ++ } ++ ++ log.Info("Ancient Block Migration Started", "process", "ancients", "startBlock", numAncientsNewBefore, "endBlock", numAncientsOld-1, "count", numAncientsOld-numAncientsNewBefore, "step", batchSize) ++ ++ g, ctx := errgroup.WithContext(ctx) ++ readChan := make(chan RLPBlockRange, bufferSize) ++ transformChan := make(chan RLPBlockRange, bufferSize) ++ ++ g.Go(func() error { ++ return readAncientBlocks(ctx, oldFreezer, numAncientsNewBefore, numAncientsOld, batchSize, readChan) ++ }) ++ g.Go(func() error { return transformBlocks(ctx, readChan, transformChan) }) ++ g.Go(func() error { return writeAncientBlocks(ctx, newFreezer, transformChan, numAncientsOld) }) ++ ++ if err = g.Wait(); err != nil { ++ return 0, 0, fmt.Errorf("failed to migrate ancients: %w", err) ++ } ++ ++ numAncientsNewAfter, err := newFreezer.Ancients() ++ if err != nil { ++ return 0, 0, fmt.Errorf("failed to get number of ancients in new freezer: %w", err) ++ } ++ ++ log.Info("Ancient Block Migration Ended", "process", "ancients", "ancientsInOldDB", numAncientsOld, "ancientsInNewDB", numAncientsNewAfter, "migrated", numAncientsNewAfter-numAncientsNewBefore) ++ return numAncientsNewBefore, numAncientsNewAfter, nil ++} ++ ++func readAncientBlocks(ctx context.Context, freezer *rawdb.Freezer, startBlock, endBlock, batchSize uint64, out chan<- RLPBlockRange) error { ++ defer close(out) ++ ++ for i := startBlock; i < endBlock; i += batchSize { ++ select { ++ case <-ctx.Done(): ++ return ctx.Err() ++ default: ++ count := min(batchSize, endBlock-i+1) ++ start := i ++ ++ blockRange := RLPBlockRange{ ++ start: start, ++ hashes: make([][]byte, count), ++ headers: make([][]byte, count), ++ bodies: make([][]byte, count), ++ receipts: make([][]byte, count), ++ tds: make([][]byte, count), ++ } ++ var err error ++ ++ blockRange.hashes, err = freezer.AncientRange(rawdb.ChainFreezerHashTable, start, count, 0) ++ if err != nil { ++ return fmt.Errorf("failed to read hashes from old freezer: %w", err) ++ } ++ blockRange.headers, err = freezer.AncientRange(rawdb.ChainFreezerHeaderTable, start, count, 0) ++ if err != nil { ++ return fmt.Errorf("failed to read headers from old freezer: %w", err) ++ } ++ blockRange.bodies, err = freezer.AncientRange(rawdb.ChainFreezerBodiesTable, start, count, 0) ++ if err != nil { ++ return fmt.Errorf("failed to read bodies from old freezer: %w", err) ++ } ++ blockRange.receipts, err = freezer.AncientRange(rawdb.ChainFreezerReceiptTable, start, count, 0) ++ if err != nil { ++ return fmt.Errorf("failed to read receipts from old freezer: %w", err) ++ } ++ blockRange.tds, err = freezer.AncientRange(rawdb.ChainFreezerDifficultyTable, start, count, 0) ++ if err != nil { ++ return fmt.Errorf("failed to read tds from old freezer: %w", err) ++ } ++ ++ out <- blockRange ++ } ++ } ++ return nil ++} ++ ++func transformBlocks(ctx context.Context, in <-chan RLPBlockRange, out chan<- RLPBlockRange) error { ++ // Transform blocks from the in channel and send them to the out channel ++ defer close(out) ++ for blockRange := range in { ++ select { ++ case <-ctx.Done(): ++ return ctx.Err() ++ default: ++ for i := range blockRange.hashes { ++ blockNumber := blockRange.start + uint64(i) ++ ++ newHeader, err := transformHeader(blockRange.headers[i]) ++ if err != nil { ++ return fmt.Errorf("can't transform header: %w", err) ++ } ++ newBody, err := transformBlockBody(blockRange.bodies[i]) ++ if err != nil { ++ return fmt.Errorf("can't transform body: %w", err) ++ } ++ ++ if yes, newHash := hasSameHash(newHeader, blockRange.hashes[i]); !yes { ++ log.Error("Hash mismatch", "block", blockNumber, "oldHash", common.BytesToHash(blockRange.hashes[i]), "newHash", newHash) ++ return fmt.Errorf("hash mismatch at block %d", blockNumber) ++ } ++ ++ blockRange.headers[i] = newHeader ++ blockRange.bodies[i] = newBody ++ } ++ out <- blockRange ++ } ++ } ++ return nil ++} ++ ++func writeAncientBlocks(ctx context.Context, freezer *rawdb.Freezer, in <-chan RLPBlockRange, totalAncientBlocks uint64) error { ++ // Write blocks from the in channel to the newDb ++ for blockRange := range in { ++ select { ++ case <-ctx.Done(): ++ return ctx.Err() ++ default: ++ _, err := freezer.ModifyAncients(func(aWriter ethdb.AncientWriteOp) error { ++ for i := range blockRange.hashes { ++ blockNumber := blockRange.start + uint64(i) ++ if err := aWriter.AppendRaw(rawdb.ChainFreezerHashTable, blockNumber, blockRange.hashes[i]); err != nil { ++ return fmt.Errorf("can't write hash to Freezer: %w", err) ++ } ++ if err := aWriter.AppendRaw(rawdb.ChainFreezerHeaderTable, blockNumber, blockRange.headers[i]); err != nil { ++ return fmt.Errorf("can't write header to Freezer: %w", err) ++ } ++ if err := aWriter.AppendRaw(rawdb.ChainFreezerBodiesTable, blockNumber, blockRange.bodies[i]); err != nil { ++ return fmt.Errorf("can't write body to Freezer: %w", err) ++ } ++ if err := aWriter.AppendRaw(rawdb.ChainFreezerReceiptTable, blockNumber, blockRange.receipts[i]); err != nil { ++ return fmt.Errorf("can't write receipts to Freezer: %w", err) ++ } ++ if err := aWriter.AppendRaw(rawdb.ChainFreezerDifficultyTable, blockNumber, blockRange.tds[i]); err != nil { ++ return fmt.Errorf("can't write td to Freezer: %w", err) ++ } ++ } ++ return nil ++ }) ++ if err != nil { ++ return fmt.Errorf("failed to write block range: %w", err) ++ } ++ blockRangeEnd := blockRange.start + uint64(len(blockRange.hashes)) - 1 ++ log.Info("Wrote ancient blocks", "start", blockRange.start, "end", blockRangeEnd, "count", len(blockRange.hashes), "remaining", totalAncientBlocks-blockRangeEnd) ++ } ++ } ++ return nil ++} ++ ++// getStrayAncientBlocks returns a list of ancient block numbers / hashes that somehow were not removed from leveldb ++func getStrayAncientBlocks(dbPath string) ([]*rawdb.NumberHash, error) { ++ defer timer("getStrayAncientBlocks")() ++ ++ db, err := openDB(dbPath, true) ++ if err != nil { ++ return nil, fmt.Errorf("failed to open database: %w", err) ++ } ++ defer db.Close() ++ ++ numAncients, err := db.Ancients() ++ if err != nil { ++ return nil, fmt.Errorf("failed to get number of ancients in database: %w", err) ++ } ++ ++ return rawdb.ReadAllHashesInRange(db, 1, numAncients-1), nil ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+133
+
-0
+ +
+ +
+
+
diff --git OP/op-chain-ops/cmd/celo-migrate/db.go CELO/op-chain-ops/cmd/celo-migrate/db.go +new file mode 100644 +index 0000000000000000000000000000000000000000..180b9e541dd07bd730f3799b076b713a169268a1 +--- /dev/null ++++ CELO/op-chain-ops/cmd/celo-migrate/db.go +@@ -0,0 +1,133 @@ ++package main ++ ++import ( ++ "encoding/binary" ++ "errors" ++ "fmt" ++ "os" ++ "path/filepath" ++ ++ "github.com/ethereum/go-ethereum/common" ++ "github.com/ethereum/go-ethereum/core/rawdb" ++ "github.com/ethereum/go-ethereum/core/types" ++ "github.com/ethereum/go-ethereum/ethdb" ++ "github.com/ethereum/go-ethereum/log" ++) ++ ++// Constants for the database ++const ( ++ DBCache = 1024 // size of the cache in MB ++ DBHandles = 60 // number of handles ++) ++ ++var ( ++ headerPrefix = []byte("h") // headerPrefix + num (uint64 big endian) + hash -> header ++) ++ ++// encodeBlockNumber encodes a block number as big endian uint64 ++func encodeBlockNumber(number uint64) []byte { ++ enc := make([]byte, 8) ++ binary.BigEndian.PutUint64(enc, number) ++ return enc ++} ++ ++// headerKey = headerPrefix + num (uint64 big endian) + hash ++func headerKey(number uint64, hash common.Hash) []byte { ++ return append(append(headerPrefix, encodeBlockNumber(number)...), hash.Bytes()...) ++} ++ ++// Opens a database with access to AncientsDb ++func openDB(chaindataPath string, readOnly bool) (ethdb.Database, error) { ++ if _, err := os.Stat(chaindataPath); errors.Is(err, os.ErrNotExist) { ++ return nil, err ++ } ++ ++ db, err := rawdb.Open(rawdb.OpenOptions{ ++ Type: "leveldb", ++ Directory: chaindataPath, ++ AncientsDirectory: filepath.Join(chaindataPath, "ancient"), ++ Namespace: "", ++ Cache: DBCache, ++ Handles: DBHandles, ++ ReadOnly: readOnly, ++ }) ++ if err != nil { ++ return nil, err ++ } ++ ++ return db, nil ++} ++ ++// Opens a database without access to AncientsDb ++func openDBWithoutFreezer(chaindataPath string, readOnly bool) (ethdb.Database, error) { ++ if _, err := os.Stat(chaindataPath); errors.Is(err, os.ErrNotExist) { ++ return nil, err ++ } ++ ++ newDB, err := rawdb.NewLevelDBDatabase(chaindataPath, DBCache, DBHandles, "", readOnly) ++ if err != nil { ++ return nil, err ++ } ++ ++ return newDB, nil ++} ++ ++func createNewDbPathIfNotExists(newDBPath string) error { ++ if err := os.MkdirAll(newDBPath, 0755); err != nil { ++ return fmt.Errorf("failed to create new database directory: %w", err) ++ } ++ return nil ++} ++ ++func removeBlocks(ldb ethdb.Database, numberHashes []*rawdb.NumberHash) error { ++ defer timer("removeBlocks")() ++ ++ if len(numberHashes) == 0 { ++ return nil ++ } ++ ++ batch := ldb.NewBatch() ++ ++ for _, numberHash := range numberHashes { ++ log.Debug("Removing block", "block", numberHash.Number) ++ rawdb.DeleteBlockWithoutNumber(batch, numberHash.Hash, numberHash.Number) ++ rawdb.DeleteCanonicalHash(batch, numberHash.Number) ++ } ++ if err := batch.Write(); err != nil { ++ log.Error("Failed to write batch", "error", err) ++ } ++ ++ return nil ++} ++ ++func getHeadHeader(dbpath string) (*types.Header, error) { ++ db, err := openDBWithoutFreezer(dbpath, true) ++ if err != nil { ++ return nil, fmt.Errorf("failed to open database at %q err: %w", dbpath, err) ++ } ++ defer db.Close() ++ ++ headHeader := rawdb.ReadHeadHeader(db) ++ if headHeader == nil { ++ return nil, fmt.Errorf("head header not in database at: %s", dbpath) ++ } ++ return headHeader, nil ++} ++ ++func cleanupNonAncientDb(dir string) error { ++ log.Info("Cleaning up non-ancient data in new db") ++ ++ files, err := os.ReadDir(dir) ++ if err != nil { ++ return fmt.Errorf("failed to read directory: %w", err) ++ } ++ for _, file := range files { ++ if file.Name() != "ancient" { ++ err := os.RemoveAll(filepath.Join(dir, file.Name())) ++ if err != nil { ++ return fmt.Errorf("failed to remove file: %w", err) ++ } ++ } ++ } ++ return nil ++}
+
+ + +
@@ -7899,510 +47606,2261 @@
-
+480
+
+649
-0
-
diff --git OP/packages/contracts-bedrock/snapshots/abi/UniswapFeeHandlerSeller.json CELO/packages/contracts-bedrock/snapshots/abi/UniswapFeeHandlerSeller.json +
diff --git OP/op-chain-ops/cmd/celo-migrate/genesis.go CELO/op-chain-ops/cmd/celo-migrate/genesis.go new file mode 100644 -index 0000000000000000000000000000000000000000..19c31c979af28ecd9ffcfcda9095f993e30b3ed1 +index 0000000000000000000000000000000000000000..b646b4c73ea532318a5e31ac66965b7db823b6ce --- /dev/null -+++ CELO/packages/contracts-bedrock/snapshots/abi/UniswapFeeHandlerSeller.json -@@ -0,0 +1,481 @@ -+[ -+ { -+ "inputs": [ -+ { -+ "internalType": "bool", -+ "name": "test", -+ "type": "bool" -+ } -+ ], -+ "stateMutability": "nonpayable", -+ "type": "constructor" ++++ CELO/op-chain-ops/cmd/celo-migrate/genesis.go +@@ -0,0 +1,649 @@ ++package main ++ ++import ( ++ "fmt" ++ ++ "github.com/ethereum/go-ethereum/core" ++ "github.com/ethereum/go-ethereum/core/types" ++ "github.com/ethereum/go-ethereum/params" ++) ++ ++// Constants containing the genesis allocation of built-in genesis blocks. ++// Copied from https://github.com/celo-org/celo-blockchain/blob/d4ac28c04d5b94855e1e72c9b4436fa3c73e16ad/core/genesis_alloc.go#L19 ++ ++const baklavaAllocJSON = `{ ++ "fCf982bb4015852e706100B14E21f947a5Bb718E": { ++ "balance": "200000000000000000000000000" ++ }, ++ "0xd71fea6b92d3f21f659152589223385a7329bb11": { ++ "balance": "1000000000000000000000" ++ }, ++ "0x1e477fc9b6a49a561343cd16b2c541930f5da7d2": { ++ "balance": "1000000000000000000000" ++ }, ++ "0x460b3f8d3c203363bb65b1a18d89d4ffb6b0c981": { ++ "balance": "1000000000000000000000" ++ }, ++ "0x3b522230c454ca9720665d66e6335a72327291e8": { ++ "balance": "1000000000000000000000" ++ }, ++ "0x0AFe167600a5542d10912f4A07DFc4EEe0769672": { ++ "balance": "1000000000000000000000" ++ }, ++ "0x412ebe7859e9aa71ff5ce4038596f6878c359c96": { ++ "balance": "1000000000000000000000" ++ }, ++ "0xbbfe73df8b346b3261b19ac91235888aba36d68c": { ++ "balance": "1000000000000000000000" ++ }, ++ "0x02b1d1bea682fcab4448c0820f5db409cce4f702": { ++ "balance": "1000000000000000000000" ++ }, ++ "0xe90f891710f625f18ecbf1e02efb4fd1ab236a10": { ++ "balance": "1000000000000000000000" ++ }, ++ "0x28c52c722df87ed11c5d7665e585e84aa93d7964": { ++ "balance": "1000000000000000000000" ++ }, ++ "0Cc59Ed03B3e763c02d54D695FFE353055f1502D": { ++ "balance": "103010030000000000000000000" ++ }, ++ "3F5084d3D4692cf19b0C98A9b22De614e49e1470": { ++ "balance": "10011000000000000000000" ++ }, ++ "EF0186B8eDA17BE7D1230eeB8389fA85e157E1fb": { ++ "balance": "10011000000000000000000" ++ }, ++ "edDdb60EF5E90Fb09707246DF193a55Df3564c9d": { ++ "balance": "10011000000000000000000" ++ }, ++ "d5e454462b3Fd98b85640977D7a5C783CA162228": { ++ "balance": "10011000000000000000000" ++ }, ++ "a4f1bad7996f346c3E90b90b60a1Ca8B67B51E4B": { ++ "balance": "10011000000000000000000" ++ }, ++ "5B991Cc1Da0b6D54F8befa9De701d8BC85C92324": { ++ "balance": "10011000000000000000000" ++ }, ++ "6dfdAa51D146eCff3B97614EF05629EA83F4997E": { ++ "balance": "10011000000000000000000" ++ }, ++ "D2b16050810600296c9580D947E9D919D0c332ed": { ++ "balance": "10011000000000000000000" ++ }, ++ "Fe144D67068737628efFb701207B3eB30eF93C69": { ++ "balance": "10011000000000000000000" ++ }, ++ "82E64996B355625efeAaD12120710706275b5b9A": { ++ "balance": "10011000000000000000000" ++ }, ++ "241752a3f65890F4AC3eAeC518fF94567954e7b5": { ++ "balance": "10011000000000000000000" ++ }, ++ "1bdDeaF571d5da96ce6a127fEb3CADaDB531f433": { ++ "balance": "10011000000000000000000" ++ }, ++ "F86345e9c9b39aB1cbE82d7aD35854f905B8B835": { ++ "balance": "10011000000000000000000" ++ }, ++ "5c3512b1697302c497B861CBfDA158f8a3c5122C": { ++ "balance": "10011000000000000000000" ++ }, ++ "a02A692d70Fd9A5269397C044aEBDf1085ba090f": { ++ "balance": "10011000000000000000000" ++ }, ++ "aC91f591F12a8B6531Be43E0ccF21cd5fA0E80b0": { ++ "balance": "10011000000000000000000" ++ }, ++ "718A8AC0943a6D3FFa3Ec670086bfB03817ed540": { ++ "balance": "10011000000000000000000" ++ }, ++ "b30980cE21679314E240DE5Cbf437C15ad459EB8": { ++ "balance": "10011000000000000000000" ++ }, ++ "99eCa23623E59C795EceB0edB666eca9eC272339": { ++ "balance": "10011000000000000000000" ++ }, ++ "c030e92d19229c3EfD708cf4B85876543ee1A3F7": { ++ "balance": "10011000000000000000000" ++ }, ++ "5c98A3414Cb6Ff5c24d145F952Cd19F5f1f56643": { ++ "balance": "10011000000000000000000" ++ }, ++ "1979b042Ae2272197f0b74170B3a6F44C3cC5c05": { ++ "balance": "10011000000000000000000" ++ }, ++ "Db871070334b961804A15f3606fBB4fAc7C7f932": { ++ "balance": "10011000000000000000000" ++ }, ++ "C656C97b765D61E0fbCb1197dC1F3a91CC80C2a4": { ++ "balance": "10011000000000000000000" ++ }, ++ "aD95a2f518c197dc9b12eE6381D88bba11F2E0E5": { ++ "balance": "10011000000000000000000" ++ }, ++ "4D4B5bF033E4A7359146C9ddb13B1C821FE1D0d3": { ++ "balance": "10011000000000000000000" ++ }, ++ "9C64dA169d71C57f85B3d7A17DB27C1ce94FBDE4": { ++ "balance": "10011000000000000000000" ++ }, ++ "B5f32e89ccaD3D396f50da32E0a599E43CE87dd7": { ++ "balance": "10011000000000000000000" ++ }, ++ "Ba40Db8ab5325494C9E7e07A4c4720990A39305c": { ++ "balance": "10011000000000000000000" ++ }, ++ "8B7852DA535df3D06D6ADc1906778afd9481588a": { ++ "balance": "10011000000000000000000" ++ }, ++ "a8F41EA062C22dAFFc61e47cF15fc898517b86B1": { ++ "balance": "10011000000000000000000" ++ }, ++ "66a3Fc7E8fd6932568cDB6610F5a67BeD9F5beF8": { ++ "balance": "10011000000000000000000" ++ }, ++ "10301d9389653497F62876f450332467E07eEe1F": { ++ "balance": "10011000000000000000000" ++ }, ++ "6c3ac5fcb13E8DCd908C405Ec6DAcF0EF575D8FC": { ++ "balance": "10011000000000000000000" ++ }, ++ "85226637919D3d47E1A37b3AF989E9aE1a1C4790": { ++ "balance": "10011000000000000000000" ++ }, ++ "43BCa16603c56cb681d1da3636B7a1A225598bfc": { ++ "balance": "10011000000000000000000" ++ }, ++ "E55d8Bc08025BDDF8Da02eEB54882d0586f90700": { ++ "balance": "10011000000000000000000" ++ }, ++ "40E1C73f6228a2c15e10aF2F3e890098b777ED15": { ++ "balance": "10011000000000000000000" ++ }, ++ "DbbF476089a186a406EA13a4c46813f4BccC3660": { ++ "balance": "10011000000000000000000" ++ }, ++ "7baCEA66a75dD974Ad549987768bF8d8908b4917": { ++ "balance": "10011000000000000000000" ++ }, ++ "fbF4C2362a9EB672BAC39A46AFd919B3c12Ce44c": { ++ "balance": "10011000000000000000000" ++ }, ++ "A8dB96136990be5B3d3bfe592e5A5a5223350A7A": { ++ "balance": "10011000000000000000000" ++ }, ++ "1Dd21ED691195EBA816d59B3De7Fab8b3470Ae4B": { ++ "balance": "10011000000000000000000" ++ }, ++ "058A778A6aeEfacc013afba92578A43e38cc012D": { ++ "balance": "10011000000000000000000" ++ }, ++ "13f52Ab66871880DC8F2179d705281a4cf6a15fB": { ++ "balance": "10011000000000000000000" ++ }, ++ "eD1Ed9a71E313d1BCe14aB998E0646F212230a33": { ++ "balance": "10011000000000000000000" ++ }, ++ "c563F264f98e34A409C6a085da7510De8B6FE90B": { ++ "balance": "10011000000000000000000" ++ }, ++ "c6D678fC6Cc1dA9D5eD1c0075cF7c679e7138e02": { ++ "balance": "10011000000000000000000" ++ }, ++ "5179fc80CaB9BB20d5405a50ec0Fb9a36c1B367a": { ++ "balance": "10011000000000000000000" ++ }, ++ "0d473f73AAf1C2bf7EBd2be7196C71dBa6C1724b": { ++ "balance": "100110000000000000000" ++ }, ++ "6958c5b7E3D94B041d0d76Cac2e09378d31201bd": { ++ "balance": "10011000000000000000000" ++ }, ++ "628d4A734d1a2647c67D254209e7B6471a11a5cb": { ++ "balance": "10011000000000000000000" ++ }, ++ "E1601e3172F0ef0100e363B639Bd44420B7E5490": { ++ "balance": "10011000000000000000000" ++ }, ++ "3337F2Cd103976F044b55D3E69aB06d1ebB142Db": { ++ "balance": "10011000000000000000000" ++ }, ++ "8D0D5c57dC232Be15Df4A1a048EF36162C853b94": { ++ "balance": "10011000000000000000000" ++ }, ++ "14800c28F3cF1Dd17AaC55263ef4e173b0e8e3Ef": { ++ "balance": "10011000000000000000000" ++ }, ++ "f3996A0f0f593BfD5E39780059C5430fab7359FD": { ++ "balance": "10011000000000000000000" ++ }, ++ "2217FeBe31Aea6C771AF163dCc453F9f060a4a00": { ++ "balance": "10011000000000000000000" ++ }, ++ "f426CC817400766cd6b44F13Cb63Ca648e323484": { ++ "balance": "10011000000000000000000" ++ }, ++ "B2C4913e257a34445Ec31685E625bb4060FB8e1f": { ++ "balance": "10011000000000000000000" ++ }, ++ "9438dbD05dfC19F049a469185c7599daa82646e8": { ++ "balance": "10011000000000000000000" ++ }, ++ "4BeD66Bf507f3CF524704267908Ea4ee3cDe3053": { ++ "balance": "10011000000000000000000" ++ }, ++ "9a850fe8105e9CCfBD9d1D06D535BB4948f3f6Cf": { ++ "balance": "10011000000000000000000" ++ }, ++ "1277eE554565542A8d0553E1e54006d006db75bd": { ++ "balance": "10011000000000000000000" ++ }, ++ "D7e829bE8E374D3fBbd2F68D9A916cB2f769BA89": { ++ "balance": "10011000000000000000000" ++ }, ++ "3691b847eD14E296afC90Ff3E37D21e518306170": { ++ "balance": "10011000000000000000000" ++ }, ++ "c4C703357B01672cF95bFa0450a5717812Bc7ffb": { ++ "balance": "10011000000000000000000" ++ }, ++ "0c9369077836353A8D92aeD29C72A7DfD300B354": { ++ "balance": "10011000000000000000000" ++ }, ++ "856DF2A3bdBb8086cE406C469dDE94d12C1E3176": { ++ "balance": "10011000000000000000000" ++ }, ++ "E40B3e5c59e2157037b699895329DBe4aA33C039": { ++ "balance": "10011000000000000000000" ++ }, ++ "edb47aF3aC2325735722450D1E7DA082bDDad58c": { ++ "balance": "10011000000000000000000" ++ }, ++ "315D669866E13fA302B76c85481F9181e06304Ce": { ++ "balance": "10011000000000000000000" ++ }, ++ "A5185E3328592428d5989422e0339247dD77e10D": { ++ "balance": "10011000000000000000000" ++ }, ++ "85Fd1d1Cd6655EbB89db7D6cA0a5C9c62F7a4CFf": { ++ "balance": "10011000000000000000000" ++ }, ++ "ACC9E4430EC1011673547395A191C6b152763EA4": { ++ "balance": "10011000000000000000000" ++ }, ++ "3824967C172D52128522dD257FE8f58C9099166B": { ++ "balance": "10011000000000000000000" ++ }, ++ "5542aDEA3092da5541250d70a3Db28Ad9BE7Cfc7": { ++ "balance": "10011000000000000000000" ++ }, ++ "c61Cd4477f0A98BfC97744481181730f7af7c14f": { ++ "balance": "10011000000000000000000" ++ }, ++ "5D7Ffd0fC6DAA67AbF7d48ae69f09dbe53d86983": { ++ "balance": "10011000000000000000000" ++ }, ++ "350914ABD4F095534823C1e8fA1cfD7EF79e7E4c": { ++ "balance": "10011000000000000000000" ++ }, ++ "ECa6f058B718E320c1D45f5D1fb07947367C3D4B": { ++ "balance": "10011000000000000000000" ++ }, ++ "9C577D0795Ed0cA88814d149c2DC61E8Fc48Ad81": { ++ "balance": "10011000000000000000000" ++ }, ++ "72fE8bC8E3Ff1e56543c9c1F9834D6dfC31BEDDC": { ++ "balance": "10011000000000000000000" ++ }, ++ "6Ff2CFa7899073CD029267fd821C9497811b5f7E": { ++ "balance": "10011000000000000000000" ++ }, ++ "4685D123aE928a7912646681ba32035ad6F010a6": { ++ "balance": "10011000000000000000000" ++ }, ++ "4799946c8B21fF5E58A225AeCB6F54ec17a94566": { ++ "balance": "10011000000000000000000" ++ }, ++ "1D7dA5a23a99Fc33e2e94d502E4Fdb564eA0B24C": { ++ "balance": "10011000000000000000000" ++ }, ++ "DFc9719cD9c7982e4A1FFB4B87cC3b861C40E367": { ++ "balance": "10011000000000000000000" ++ }, ++ "0c1F0457ce3e87f5eA8F2C3A007dfe963A6Ff9a7": { ++ "balance": "10011000000000000000000" ++ }, ++ "7dC23b30dFDc326B9a694c6f9723DC889fe16b7d": { ++ "balance": "10011000000000000000000" ++ }, ++ "3F0c4cFDD40D16B7C15878AcCdc91Be9ca4DeE79": { ++ "balance": "10011000000000000000000" ++ }, ++ "B984a83416F560437C7866e26CdDb94bDB821594": { ++ "balance": "10011000000000000000000" ++ }, ++ "138EA4C57F5b3984EFacd944b3b85dfDd5A78Dcc": { ++ "balance": "10011000000000000000000" ++ }, ++ "AD4f16F3435E849505C643714C9E5f40f73c4a5a": { ++ "balance": "10011000000000000000000" ++ }, ++ "6b38E861ec0b65fd288d96d5630711C576362152": { ++ "balance": "10011000000000000000000" ++ }, ++ "AE15D05100CE807d0aC93119f4ada8fa21441Fd2": { ++ "balance": "10011000000000000000000" ++ }, ++ "e0e25c5734bef8b2Add633eAa2518B207DAa0D66": { ++ "balance": "10011000000000000000000" ++ }, ++ "9039Ce107A9cD36Ed116958E50f8BDe090e2406f": { ++ "balance": "10011000000000000000000" ++ }, ++ "089bE2dD42096ebA1d94aad20228b75df2BeeBC7": { ++ "balance": "10011000000000000000000" ++ }, ++ "E3a79AEee437532313015892B52b65f52794F8a2": { ++ "balance": "10011000000000000000000" ++ }, ++ "Cc38EE244819649C9DaB02e268306cED09B20672": { ++ "balance": "10011000000000000000000" ++ }, ++ "eb0357140a1a0A6c1cB9c93Bf9354ef7365C97d9": { ++ "balance": "10011000000000000000000" ++ }, ++ "44370D6b2d010C9eBFa280b6C00010AC99a45660": { ++ "balance": "10011000000000000000000" ++ }, ++ "762438915209d038340C3Af9f8aAb8F93aDc8A9A": { ++ "balance": "10011000000000000000000" ++ }, ++ "9CBa7aD50fa366Ff6fC2CAe468929eC9AD23Ea2B": { ++ "balance": "10011000000000000000000" ++ }, ++ "4f4F159826b2B1eE903A811fCd86E450c9954396": { ++ "balance": "10011000000000000000000" ++ }, ++ "3C132B8465e2D172BB7bab6654D85E398ee7c8AD": { ++ "balance": "10011000000000000000000" ++ }, ++ "0582426C929B7e525c22201Bd4c143E45189C589": { ++ "balance": "10011000000000000000000" ++ }, ++ "fb542740B34dDC0ADE383F2907a1e1E175E0BF5a": { ++ "balance": "10011000000000000000000" ++ }, ++ "184Ca91AfE8F36bC5772b29cE2A76c90fCef34D0": { ++ "balance": "10011000000000000000000" ++ }, ++ "0C6f48B50B166ddcE52CEE051acCAfFB8ecB4976": { ++ "balance": "10011000000000000000000" ++ }, ++ "3aD2bE38fA3DFa7969E79B4053868FD1C368eAb2": { ++ "balance": "10011000000000000000000" ++ }, ++ "a6A690637b088E9A1A89c44c9dC5e14eD4825053": { ++ "balance": "10011000000000000000000" ++ }, ++ "C224B131Ea71e11E7DF38de3774AAAAe7E197BA4": { ++ "balance": "10011000000000000000000" ++ }, ++ "d3C18531f0879B9FB8Ed45830C4ce6b54dC57128": { ++ "balance": "10011000000000000000000" ++ }, ++ "02a272d17E1308beF21E783A93D1658f84F2D414": { ++ "balance": "10011000000000000000000" ++ }, ++ "57A1aC8167d94b899b32C38Ff9D2B2bD0e55C10d": { ++ "balance": "10011000000000000000000" ++ }, ++ "F8fc7D740929E5DD4eBA8fd5a6873Be6a4151087": { ++ "balance": "10011000000000000000000" ++ }, ++ "B2AfC45838b364240dE17D3143AA6096d3340A91": { ++ "balance": "10011000000000000000000" ++ }, ++ "eAf133d1e0Dd325721665B19f67C9b914EE2469F": { ++ "balance": "10011000000000000000000" ++ }, ++ "B7660F1B075e56780e7E026ff66995765f5f1f7F": { ++ "balance": "10011000000000000000000" ++ }, ++ "F25087E27B7a59003bb08d2cAc7A69E7c15a4be8": { ++ "balance": "10011000000000000000000" ++ }, ++ "E65054681206658A845140331459A057C4EB3CA7": { ++ "balance": "10011000000000000000000" ++ }, ++ "e7569A0F93E832a6633d133d23503B5175bEa5Db": { ++ "balance": "10011000000000000000000" ++ }, ++ "a9f6102BCf5351dFdC7fA0CA4Fa0A711e16605c3": { ++ "balance": "10011000000000000000000" ++ }, ++ "1AB9aA0E855DF953CF8d9cC166172799afD12a68": { ++ "balance": "10011000000000000000000" ++ }, ++ "6C04aA35c377E65658EC3600Cab5E8FFa95567D9": { ++ "balance": "10011000000000000000000" ++ }, ++ "6b82AD37e64c91c628305813B2DA82F18f8e2a2B": { ++ "balance": "10011000000000000000000" ++ }, ++ "AD5D1DeD72F0e70a0a5500B26b82B1A2e8A63471": { ++ "balance": "10011000000000000000000" ++ }, ++ "72B3589771Ec8e189a5d9Fe7a214e44085e89054": { ++ "balance": "10011000000000000000000" ++ }, ++ "74F57dA8be3E9AB4463DD70319A06Fb5E3168211": { ++ "balance": "10011000000000000000000" ++ }, ++ "b6f7F57b99DB21027875BEa3b8531d5925c346cE": { ++ "balance": "10011000000000000000000" ++ }, ++ "279d05241d33Dc422d5AEcAc0e089B7f50f879c3": { ++ "balance": "10011000000000000000000" ++ }, ++ "d57FEfe1B634ab451a6815Cd6769182EABA62779": { ++ "balance": "10011000000000000000000" ++ }, ++ "e86C8538Bdfb253E8D6cC29ee24A330905324849": { ++ "balance": "10011000000000000000000" ++ }, ++ "2C58D7f7f9CDF79CF3Cd5F4247761b93428A4E9e": { ++ "balance": "10011000000000000000000" ++ }, ++ "37326cEfAFB1676f7Af1CcDcCD37A846Ec64F19d": { ++ "balance": "10011000000000000000000" ++ }, ++ "f01DCf91d5f74BDB161F520e800c64F686Eb253F": { ++ "balance": "10011000000000000000000" ++ }, ++ "Ba85246bc2A4fdaC1cB2e3C68383Fe79A6466fd9": { ++ "balance": "10011000000000000000000" ++ }, ++ "4A76f81eA26381981a3B740975fb4F605989b585": { ++ "balance": "10011000000000000000000" ++ }, ++ "00ee7168618BaE4F4d2900D5063c62948c6F0566": { ++ "balance": "10011000000000000000000" ++ }, ++ "E1aD0B232B4262E4A279C91070417DAAF202623F": { ++ "balance": "10011000000000000000000" ++ }, ++ "f611173319b22080E0F02eE724781d85f4b39Ae6": { ++ "balance": "10011000000000000000000" ++ }, ++ "158659458dff3a9E5182cA0e8Ba08F53463FA5e7": { ++ "balance": "10011000000000000000000" ++ }, ++ "FEB11610ad367b0c994274A8153E50F4557e473F": { ++ "balance": "10011000000000000000000" ++ }, ++ "e1eB2279f45760Ab9D734782B1a0A8FD3d47D807": { ++ "balance": "10011000000000000000000" ++ }, ++ "8667d005eCF50Eb247890a11FCdCfC321DC1Da9f": { ++ "balance": "10011000000000000000000" ++ }, ++ "5Ce612A664C2f35558Dcab7edb999619e155CD07": { ++ "balance": "10011000000000000000000" ++ }, ++ "aD95f88cCd3aBC12ddd6cD0b9a777B95339b747b": { ++ "balance": "10011000000000000000000" ++ }, ++ "6E5a5A2963F6d0C2EA26682a152fE3ac7CBC1227": { ++ "balance": "10011000000000000000000" ++ }, ++ "000000000000000000000000000000000000ce10": { ++ "code": "0x60806040526004361061004a5760003560e01c806303386ba3146101e757806342404e0714610280578063bb913f41146102d7578063d29d44ee14610328578063f7e6af8014610379575b6000600160405180807f656970313936372e70726f78792e696d706c656d656e746174696f6e00000000815250601c019050604051809103902060001c0360001b9050600081549050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610136576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f4e6f20496d706c656d656e746174696f6e20736574000000000000000000000081525060200191505060405180910390fd5b61013f816103d0565b6101b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f496e76616c696420636f6e74726163742061646472657373000000000000000081525060200191505060405180910390fd5b60405136810160405236600082376000803683855af43d604051818101604052816000823e82600081146101e3578282f35b8282fd5b61027e600480360360408110156101fd57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019064010000000081111561023a57600080fd5b82018360208201111561024c57600080fd5b8035906020019184600183028401116401000000008311171561026e57600080fd5b909192939192939050505061041b565b005b34801561028c57600080fd5b506102956105c1565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156102e357600080fd5b50610326600480360360208110156102fa57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061060d565b005b34801561033457600080fd5b506103776004803603602081101561034b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506107bd565b005b34801561038557600080fd5b5061038e610871565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b60008060007fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47060001b9050833f915080821415801561041257506000801b8214155b92505050919050565b610423610871565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146104c3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f73656e64657220776173206e6f74206f776e657200000000000000000000000081525060200191505060405180910390fd5b6104cc8361060d565b600060608473ffffffffffffffffffffffffffffffffffffffff168484604051808383808284378083019250505092505050600060405180830381855af49150503d8060008114610539576040519150601f19603f3d011682016040523d82523d6000602084013e61053e565b606091505b508092508193505050816105ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f696e697469616c697a6174696f6e2063616c6c6261636b206661696c6564000081525060200191505060405180910390fd5b5050505050565b600080600160405180807f656970313936372e70726f78792e696d706c656d656e746174696f6e00000000815250601c019050604051809103902060001c0360001b9050805491505090565b610615610871565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146106b5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f73656e64657220776173206e6f74206f776e657200000000000000000000000081525060200191505060405180910390fd5b6000600160405180807f656970313936372e70726f78792e696d706c656d656e746174696f6e00000000815250601c019050604051809103902060001c0360001b9050610701826103d0565b610773576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f496e76616c696420636f6e74726163742061646472657373000000000000000081525060200191505060405180910390fd5b8181558173ffffffffffffffffffffffffffffffffffffffff167fab64f92ab780ecbf4f3866f57cee465ff36c89450dcce20237ca7a8d81fb7d1360405160405180910390a25050565b6107c5610871565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610865576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f73656e64657220776173206e6f74206f776e657200000000000000000000000081525060200191505060405180910390fd5b61086e816108bd565b50565b600080600160405180807f656970313936372e70726f78792e61646d696e000000000000000000000000008152506013019050604051809103902060001c0360001b9050805491505090565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610960576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f6f776e65722063616e6e6f74206265203000000000000000000000000000000081525060200191505060405180910390fd5b6000600160405180807f656970313936372e70726f78792e61646d696e000000000000000000000000008152506013019050604051809103902060001c0360001b90508181558173ffffffffffffffffffffffffffffffffffffffff167f50146d0e3c60aa1d17a70635b05494f864e86144a2201275021014fbf08bafe260405160405180910390a2505056fea165627a7a72305820959a50d5df76f90bc1825042f47788ee27f1b4725f7ed5d37c5c05c0732ef44f0029", ++ "storage": { ++ "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x0Cc59Ed03B3e763c02d54D695FFE353055f1502D" ++ }, ++ "balance": "0" ++ } ++}` ++ ++const alfajoresAllocJSON = `{ ++ "456f41406B32c45D59E539e4BBA3D7898c3584dA": { ++ "balance": "103010030000000000000000000" + }, -+ { -+ "stateMutability": "payable", -+ "type": "receive" ++ "DD1F519F63423045F526b8c83edC0eB4BA6434a4": { ++ "balance": "10011000000000000000000" + }, -+ { -+ "inputs": [ -+ { -+ "internalType": "uint256", -+ "name": "midPriceNumerator", -+ "type": "uint256" -+ }, -+ { -+ "internalType": "uint256", -+ "name": "midPriceDenominator", -+ "type": "uint256" -+ }, -+ { -+ "internalType": "uint256", -+ "name": "amount", -+ "type": "uint256" -+ }, -+ { -+ "internalType": "uint256", -+ "name": "maxSlippage", -+ "type": "uint256" -+ } -+ ], -+ "name": "calculateMinAmount", -+ "outputs": [ -+ { -+ "internalType": "uint256", -+ "name": "", -+ "type": "uint256" -+ } -+ ], -+ "stateMutability": "pure", -+ "type": "function" ++ "050f34537F5b2a00B9B9C752Cb8500a3fcE3DA7d": { ++ "balance": "10011000000000000000000" + }, -+ { -+ "inputs": [ -+ { -+ "internalType": "address", -+ "name": "token", -+ "type": "address" -+ } -+ ], -+ "name": "getRoutersForToken", -+ "outputs": [ -+ { -+ "internalType": "address[]", -+ "name": "", -+ "type": "address[]" -+ } -+ ], -+ "stateMutability": "view", -+ "type": "function" ++ "Cda518F6b5a797C3EC45D37c65b83e0b0748eDca": { ++ "balance": "10011000000000000000000" + }, -+ { -+ "inputs": [], -+ "name": "getVersionNumber", -+ "outputs": [ -+ { -+ "internalType": "uint256", -+ "name": "", -+ "type": "uint256" -+ }, -+ { -+ "internalType": "uint256", -+ "name": "", -+ "type": "uint256" -+ }, -+ { -+ "internalType": "uint256", -+ "name": "", -+ "type": "uint256" -+ }, -+ { -+ "internalType": "uint256", -+ "name": "", -+ "type": "uint256" -+ } -+ ], -+ "stateMutability": "pure", -+ "type": "function" ++ "b4e92c94A2712e98c020A81868264bdE52C188Cb": { ++ "balance": "10011000000000000000000" + }, -+ { -+ "inputs": [ -+ { -+ "internalType": "address", -+ "name": "_registryAddress", -+ "type": "address" -+ }, -+ { -+ "internalType": "address[]", -+ "name": "tokenAddresses", -+ "type": "address[]" -+ }, -+ { -+ "internalType": "uint256[]", -+ "name": "newMininumReports", -+ "type": "uint256[]" -+ } -+ ], -+ "name": "initialize", -+ "outputs": [], -+ "stateMutability": "nonpayable", -+ "type": "function" ++ "Ae1ec841923811219b98ACeB1db297AADE2F46F3": { ++ "balance": "10011000000000000000000" + }, -+ { -+ "inputs": [], -+ "name": "initialized", -+ "outputs": [ -+ { -+ "internalType": "bool", -+ "name": "", -+ "type": "bool" -+ } -+ ], -+ "stateMutability": "view", -+ "type": "function" ++ "621843731fe33418007C06ee48CfD71e0ea828d9": { ++ "balance": "10011000000000000000000" + }, -+ { -+ "inputs": [ -+ { -+ "internalType": "address", -+ "name": "", -+ "type": "address" -+ } -+ ], -+ "name": "minimumReports", -+ "outputs": [ -+ { -+ "internalType": "uint256", -+ "name": "", -+ "type": "uint256" -+ } -+ ], -+ "stateMutability": "view", -+ "type": "function" ++ "2A43f97f8BF959E31F69A894ebD80A88572C8553": { ++ "balance": "10011000000000000000000" + }, -+ { -+ "inputs": [], -+ "name": "owner", -+ "outputs": [ -+ { -+ "internalType": "address", -+ "name": "", -+ "type": "address" -+ } -+ ], -+ "stateMutability": "view", -+ "type": "function" ++ "AD682035bE6Ab6f06e478D2BDab0EAb6477B460E": { ++ "balance": "10011000000000000000000" + }, -+ { -+ "inputs": [], -+ "name": "registry", -+ "outputs": [ -+ { -+ "internalType": "contract ICeloRegistry", -+ "name": "", -+ "type": "address" -+ } -+ ], -+ "stateMutability": "view", -+ "type": "function" ++ "30D060F129817c4DE5fBc1366d53e19f43c8c64f": { ++ "balance": "10011000000000000000000" + }, -+ { -+ "inputs": [ -+ { -+ "internalType": "address", -+ "name": "token", -+ "type": "address" -+ }, -+ { -+ "internalType": "address", -+ "name": "router", -+ "type": "address" -+ } -+ ], -+ "name": "removeRouter", -+ "outputs": [], -+ "stateMutability": "nonpayable", -+ "type": "function" ++ "22579CA45eE22E2E16dDF72D955D6cf4c767B0eF": { ++ "balance": "10011000000000000000000" + }, -+ { -+ "inputs": [], -+ "name": "renounceOwnership", -+ "outputs": [], -+ "stateMutability": "nonpayable", -+ "type": "function" ++ "1173C5A50bf025e8356823a068E396ccF2bE696C": { ++ "balance": "10011000000000000000000" + }, -+ { -+ "inputs": [ -+ { -+ "internalType": "address", -+ "name": "sellTokenAddress", -+ "type": "address" -+ }, -+ { -+ "internalType": "address", -+ "name": "buyTokenAddress", -+ "type": "address" -+ }, -+ { -+ "internalType": "uint256", -+ "name": "amount", -+ "type": "uint256" -+ }, -+ { -+ "internalType": "uint256", -+ "name": "maxSlippage", -+ "type": "uint256" -+ } -+ ], -+ "name": "sell", -+ "outputs": [ -+ { -+ "internalType": "uint256", -+ "name": "", -+ "type": "uint256" -+ } -+ ], -+ "stateMutability": "nonpayable", -+ "type": "function" ++ "40F71B525A96baa8d14Eaa7Bcd19929782659c64": { ++ "balance": "10011000000000000000000" + }, -+ { -+ "inputs": [ -+ { -+ "internalType": "address", -+ "name": "tokenAddress", -+ "type": "address" -+ }, -+ { -+ "internalType": "uint256", -+ "name": "newMininumReports", -+ "type": "uint256" -+ } -+ ], -+ "name": "setMinimumReports", -+ "outputs": [], -+ "stateMutability": "nonpayable", -+ "type": "function" ++ "b923626C6f1d237252793FB2aA12BA21328C51BC": { ++ "balance": "10011000000000000000000" + }, -+ { -+ "inputs": [ -+ { -+ "internalType": "address", -+ "name": "registryAddress", -+ "type": "address" -+ } -+ ], -+ "name": "setRegistry", -+ "outputs": [], -+ "stateMutability": "nonpayable", -+ "type": "function" ++ "B70f9ABf41F36B3ab60cc9aE1a85Ddda3C88D261": { ++ "balance": "10011000000000000000000" + }, -+ { -+ "inputs": [ -+ { -+ "internalType": "address", -+ "name": "token", -+ "type": "address" -+ }, -+ { -+ "internalType": "address", -+ "name": "router", -+ "type": "address" -+ } -+ ], -+ "name": "setRouter", -+ "outputs": [], -+ "stateMutability": "nonpayable", -+ "type": "function" ++ "d4369DB59eaDc4Cfa089c0a3c1004ceAb1b318D8": { ++ "balance": "10011000000000000000000" + }, -+ { -+ "inputs": [ -+ { -+ "internalType": "address", -+ "name": "token", -+ "type": "address" -+ }, -+ { -+ "internalType": "uint256", -+ "name": "amount", -+ "type": "uint256" -+ }, -+ { -+ "internalType": "address", -+ "name": "to", -+ "type": "address" -+ } -+ ], -+ "name": "transfer", -+ "outputs": [ -+ { -+ "internalType": "bool", -+ "name": "", -+ "type": "bool" -+ } -+ ], -+ "stateMutability": "nonpayable", -+ "type": "function" ++ "2fd430d3a96eadc38cc1B38b6685C5f52Cf7a083": { ++ "balance": "10011000000000000000000" + }, -+ { -+ "inputs": [ -+ { -+ "internalType": "address", -+ "name": "newOwner", -+ "type": "address" -+ } -+ ], -+ "name": "transferOwnership", -+ "outputs": [], -+ "stateMutability": "nonpayable", -+ "type": "function" ++ "Fecc71C8f33Ca5952534fd346ADdeDC38DBb9cb7": { ++ "balance": "10011000000000000000000" + }, -+ { -+ "anonymous": false, -+ "inputs": [ -+ { -+ "indexed": false, -+ "internalType": "address", -+ "name": "tokenAddress", -+ "type": "address" -+ }, -+ { -+ "indexed": false, -+ "internalType": "uint256", -+ "name": "minimumReports", -+ "type": "uint256" -+ } -+ ], -+ "name": "MinimumReportsSet", -+ "type": "event" ++ "0de78C89e7BF5060f28dd3f820C15C4A6A81AFB5": { ++ "balance": "10011000000000000000000" + }, -+ { -+ "anonymous": false, -+ "inputs": [ -+ { -+ "indexed": true, -+ "internalType": "address", -+ "name": "previousOwner", -+ "type": "address" -+ }, -+ { -+ "indexed": true, -+ "internalType": "address", -+ "name": "newOwner", -+ "type": "address" -+ } -+ ], -+ "name": "OwnershipTransferred", -+ "type": "event" ++ "75411b92fcE120C1e7fd171b1c2bF802f2E3CF48": { ++ "balance": "10011000000000000000000" + }, -+ { -+ "anonymous": false, -+ "inputs": [ -+ { -+ "indexed": true, -+ "internalType": "address", -+ "name": "tokneAddress", -+ "type": "address" -+ }, -+ { -+ "indexed": true, -+ "internalType": "address", -+ "name": "router", -+ "type": "address" -+ }, -+ { -+ "indexed": false, -+ "internalType": "uint256", -+ "name": "quote", -+ "type": "uint256" -+ } -+ ], -+ "name": "ReceivedQuote", -+ "type": "event" ++ "563433bD8357b06982Fe001df20B2b43393d21d2": { ++ "balance": "10011000000000000000000" + }, -+ { -+ "anonymous": false, -+ "inputs": [ -+ { -+ "indexed": true, -+ "internalType": "address", -+ "name": "registryAddress", -+ "type": "address" -+ } -+ ], -+ "name": "RegistrySet", -+ "type": "event" ++ "79dfB9d2367E7921d4139D7841d24ED82F48907F": { ++ "balance": "10011000000000000000000" + }, -+ { -+ "anonymous": false, -+ "inputs": [ -+ { -+ "indexed": false, -+ "internalType": "address", -+ "name": "token", -+ "type": "address" -+ }, -+ { -+ "indexed": false, -+ "internalType": "address", -+ "name": "router", -+ "type": "address" -+ } -+ ], -+ "name": "RouterAddressRemoved", -+ "type": "event" ++ "5809369FC5121a071eE67659a975e88ae40fBE3b": { ++ "balance": "10011000000000000000000" + }, -+ { -+ "anonymous": false, -+ "inputs": [ -+ { -+ "indexed": false, -+ "internalType": "address", -+ "name": "token", -+ "type": "address" -+ }, -+ { -+ "indexed": false, -+ "internalType": "address", -+ "name": "router", -+ "type": "address" -+ } -+ ], -+ "name": "RouterAddressSet", -+ "type": "event" ++ "7517E54a456bcc6c5c695B5d9f97EBc05d29a824": { ++ "balance": "10011000000000000000000" ++ }, ++ "B0a1A5Ffcb34E6Fa278D2b40613f0AE1042d32f8": { ++ "balance": "10011000000000000000000" ++ }, ++ "EeE9f4DDf49976251E84182AbfD3300Ee58D12aa": { ++ "balance": "10011000000000000000000" ++ }, ++ "Eb5Fd57f87a4e1c7bAa53ec1c0d021bb1710B743": { ++ "balance": "10011000000000000000000" ++ }, ++ "B7Dd51bFb73c5753778e5Af56f1D9669BCe6777F": { ++ "balance": "10011000000000000000000" + }, -+ { -+ "anonymous": false, -+ "inputs": [ -+ { -+ "indexed": false, -+ "internalType": "address", -+ "name": "router", -+ "type": "address" -+ } -+ ], -+ "name": "RouterUsed", -+ "type": "event" ++ "33C222BB13C63295AF32D6C91278AA34b573e776": { ++ "balance": "10011000000000000000000" + }, -+ { -+ "anonymous": false, -+ "inputs": [ -+ { -+ "indexed": false, -+ "internalType": "address", -+ "name": "soldTokenAddress", -+ "type": "address" -+ }, -+ { -+ "indexed": false, -+ "internalType": "address", -+ "name": "boughtTokenAddress", -+ "type": "address" -+ }, -+ { -+ "indexed": false, -+ "internalType": "uint256", -+ "name": "amount", -+ "type": "uint256" -+ } -+ ], -+ "name": "TokenSold", -+ "type": "event" ++ "83c58603bF72DA067D7f6238E7bF390d91B2f531": { ++ "balance": "10011000000000000000000" ++ }, ++ "6651112198C0da05921355642a2B8dF1fA3Ede93": { ++ "balance": "10011000000000000000000" ++ }, ++ "4EE72A98549eA7CF774C3E2E1b39fF166b4b68BE": { ++ "balance": "10011000000000000000000" ++ }, ++ "840b32F30e1a3b2E8b9E6C0972eBa0148E22B847": { ++ "balance": "100000000000000000000" ++ }, ++ "000000000000000000000000000000000000ce10": { ++ "code": "0x60806040526004361061004a5760003560e01c806303386ba3146101e757806342404e0714610280578063bb913f41146102d7578063d29d44ee14610328578063f7e6af8014610379575b6000600160405180807f656970313936372e70726f78792e696d706c656d656e746174696f6e00000000815250601c019050604051809103902060001c0360001b9050600081549050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610136576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f4e6f20496d706c656d656e746174696f6e20736574000000000000000000000081525060200191505060405180910390fd5b61013f816103d0565b6101b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f496e76616c696420636f6e74726163742061646472657373000000000000000081525060200191505060405180910390fd5b60405136810160405236600082376000803683855af43d604051818101604052816000823e82600081146101e3578282f35b8282fd5b61027e600480360360408110156101fd57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019064010000000081111561023a57600080fd5b82018360208201111561024c57600080fd5b8035906020019184600183028401116401000000008311171561026e57600080fd5b909192939192939050505061041b565b005b34801561028c57600080fd5b506102956105c1565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156102e357600080fd5b50610326600480360360208110156102fa57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061060d565b005b34801561033457600080fd5b506103776004803603602081101561034b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506107bd565b005b34801561038557600080fd5b5061038e610871565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b60008060007fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47060001b9050833f915080821415801561041257506000801b8214155b92505050919050565b610423610871565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146104c3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f73656e64657220776173206e6f74206f776e657200000000000000000000000081525060200191505060405180910390fd5b6104cc8361060d565b600060608473ffffffffffffffffffffffffffffffffffffffff168484604051808383808284378083019250505092505050600060405180830381855af49150503d8060008114610539576040519150601f19603f3d011682016040523d82523d6000602084013e61053e565b606091505b508092508193505050816105ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f696e697469616c697a6174696f6e2063616c6c6261636b206661696c6564000081525060200191505060405180910390fd5b5050505050565b600080600160405180807f656970313936372e70726f78792e696d706c656d656e746174696f6e00000000815250601c019050604051809103902060001c0360001b9050805491505090565b610615610871565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146106b5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f73656e64657220776173206e6f74206f776e657200000000000000000000000081525060200191505060405180910390fd5b6000600160405180807f656970313936372e70726f78792e696d706c656d656e746174696f6e00000000815250601c019050604051809103902060001c0360001b9050610701826103d0565b610773576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f496e76616c696420636f6e74726163742061646472657373000000000000000081525060200191505060405180910390fd5b8181558173ffffffffffffffffffffffffffffffffffffffff167fab64f92ab780ecbf4f3866f57cee465ff36c89450dcce20237ca7a8d81fb7d1360405160405180910390a25050565b6107c5610871565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610865576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f73656e64657220776173206e6f74206f776e657200000000000000000000000081525060200191505060405180910390fd5b61086e816108bd565b50565b600080600160405180807f656970313936372e70726f78792e61646d696e000000000000000000000000008152506013019050604051809103902060001c0360001b9050805491505090565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610960576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f6f776e65722063616e6e6f74206265203000000000000000000000000000000081525060200191505060405180910390fd5b6000600160405180807f656970313936372e70726f78792e61646d696e000000000000000000000000008152506013019050604051809103902060001c0360001b90508181558173ffffffffffffffffffffffffffffffffffffffff167f50146d0e3c60aa1d17a70635b05494f864e86144a2201275021014fbf08bafe260405160405180910390a2505056fea165627a7a723058202dbb6037e4381b4ad95015ed99441a23345cc2ae52ef27e2e91d34fb0acd277b0029", ++ "storage": { ++ "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "456f41406B32c45D59E539e4BBA3D7898c3584dA" ++ }, ++ "balance": "0" + } -+] -\ No newline at end of file
++}` ++ ++const mainnetAllocJSON = "{\"0x11901cf7eEae1E2644995FB2E47Ce46bC7F33246\":{\"balance\":\"120000000000000000000000000\"},\"0xC1cDA18694F5B86cFB80c1B4f8Cc046B0d7E6326\":{\"balance\":\"20000000000000000000000000\"},\"0xa5d40D93b01AfBafec84E20018Aff427628F645E\":{\"balance\":\"20000000000000000000000000\"},\"0x8d485780E84E23437f8F6938D96B964645529127\":{\"balance\":\"20000000000000000000000000\"},\"0x5F857c501b73ddFA804234f1f1418D6f75554076\":{\"balance\":\"20000000000000000000000000\"},\"0xaa9064F57F8d7de4b3e08c35561E21Afd6341390\":{\"balance\":\"20000000000000000000000000\"},\"0x7FA26b50b3e9a2eC8AD1850a4c4FBBF94D806E95\":{\"balance\":\"20000000000000000000000000\"},\"0x08960Ce6b58BE32FBc6aC1489d04364B4f7dC216\":{\"balance\":\"20000000000000000000000000\"},\"0x77B68B2e7091D4F242a8Af89F200Af941433C6d8\":{\"balance\":\"20000000000000000000000000\"},\"0x75Bb69C002C43f5a26a2A620518775795Fd45ecf\":{\"balance\":\"20000000000000000000000000\"},\"0x19992AE48914a178Bf138665CffDD8CD79b99513\":{\"balance\":\"20000000000000000000000000\"},\"0xE23a4c6615669526Ab58E9c37088bee4eD2b2dEE\":{\"balance\":\"20000000000000000000000\"},\"0xDe22679dCA843B424FD0BBd70A22D5F5a4B94fe4\":{\"balance\":\"10200014000000000000000000\"},\"0x743D80810fe10c5C3346D2940997cC9647035B13\":{\"balance\":\"20513322000000000000000000\"},\"0x8e1c4355307F1A59E7eD4Ae057c51368b9338C38\":{\"balance\":\"7291740000000000000000000\"},\"0x417fe63186C388812e342c85FF87187Dc584C630\":{\"balance\":\"20000062000000000000000000\"},\"0xF5720c180a6Fa14ECcE82FB1bB060A39E93A263c\":{\"balance\":\"30000061000000000000000000\"},\"0xB80d1e7F9CEbe4b5E1B1Acf037d3a44871105041\":{\"balance\":\"9581366833333333333333335\"},\"0xf8ed78A113cD2a34dF451Ba3D540FFAE66829AA0\":{\"balance\":\"11218686833333333333333333\"},\"0x9033ff75af27222c8f36a148800c7331581933F3\":{\"balance\":\"11218686833333333333333333\"},\"0x8A07541C2eF161F4e3f8de7c7894718dA26626B2\":{\"balance\":\"11218686833333333333333333\"},\"0xB2fe7AFe178335CEc3564d7671EEbD7634C626B0\":{\"balance\":\"11218686833333333333333333\"},\"0xc471776eA02705004C451959129bF09423B56526\":{\"balance\":\"11218686833333333333333333\"},\"0xeF283eca68DE87E051D427b4be152A7403110647\":{\"balance\":\"14375000000000000000000000\"},\"0x7cf091C954ed7E9304452d31fd59999505Ddcb7a\":{\"balance\":\"14375000000000000000000000\"},\"0xa5d2944C32a8D7b284fF0b84c20fDcc46937Cf64\":{\"balance\":\"14375000000000000000000000\"},\"0xFC89C17525f08F2Bc9bA8cb77BcF05055B1F7059\":{\"balance\":\"14375000000000000000000000\"},\"0x3Fa7C646599F3174380BD9a7B6efCde90b5d129d\":{\"balance\":\"14375000000000000000000000\"},\"0x989e1a3B344A43911e02cCC609D469fbc15AB1F1\":{\"balance\":\"14375000000000000000000000\"},\"0xAe1d640648009DbE0Aa4485d3BfBB68C37710924\":{\"balance\":\"20025000000000000000000000\"},\"0x1B6C64779F42BA6B54C853Ab70171aCd81b072F7\":{\"balance\":\"20025000000000000000000000\"},\"000000000000000000000000000000000000ce10\":{\"code\":\"0x60806040526004361061004a5760003560e01c806303386ba3146101e757806342404e0714610280578063bb913f41146102d7578063d29d44ee14610328578063f7e6af8014610379575b6000600160405180807f656970313936372e70726f78792e696d706c656d656e746174696f6e00000000815250601c019050604051809103902060001c0360001b9050600081549050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610136576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f4e6f20496d706c656d656e746174696f6e20736574000000000000000000000081525060200191505060405180910390fd5b61013f816103d0565b6101b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f496e76616c696420636f6e74726163742061646472657373000000000000000081525060200191505060405180910390fd5b60405136810160405236600082376000803683855af43d604051818101604052816000823e82600081146101e3578282f35b8282fd5b61027e600480360360408110156101fd57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019064010000000081111561023a57600080fd5b82018360208201111561024c57600080fd5b8035906020019184600183028401116401000000008311171561026e57600080fd5b909192939192939050505061041b565b005b34801561028c57600080fd5b506102956105c1565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156102e357600080fd5b50610326600480360360208110156102fa57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061060d565b005b34801561033457600080fd5b506103776004803603602081101561034b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506107bd565b005b34801561038557600080fd5b5061038e610871565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b60008060007fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47060001b9050833f915080821415801561041257506000801b8214155b92505050919050565b610423610871565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146104c3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f73656e64657220776173206e6f74206f776e657200000000000000000000000081525060200191505060405180910390fd5b6104cc8361060d565b600060608473ffffffffffffffffffffffffffffffffffffffff168484604051808383808284378083019250505092505050600060405180830381855af49150503d8060008114610539576040519150601f19603f3d011682016040523d82523d6000602084013e61053e565b606091505b508092508193505050816105ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f696e697469616c697a6174696f6e2063616c6c6261636b206661696c6564000081525060200191505060405180910390fd5b5050505050565b600080600160405180807f656970313936372e70726f78792e696d706c656d656e746174696f6e00000000815250601c019050604051809103902060001c0360001b9050805491505090565b610615610871565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146106b5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f73656e64657220776173206e6f74206f776e657200000000000000000000000081525060200191505060405180910390fd5b6000600160405180807f656970313936372e70726f78792e696d706c656d656e746174696f6e00000000815250601c019050604051809103902060001c0360001b9050610701826103d0565b610773576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f496e76616c696420636f6e74726163742061646472657373000000000000000081525060200191505060405180910390fd5b8181558173ffffffffffffffffffffffffffffffffffffffff167fab64f92ab780ecbf4f3866f57cee465ff36c89450dcce20237ca7a8d81fb7d1360405160405180910390a25050565b6107c5610871565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610865576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f73656e64657220776173206e6f74206f776e657200000000000000000000000081525060200191505060405180910390fd5b61086e816108bd565b50565b600080600160405180807f656970313936372e70726f78792e61646d696e000000000000000000000000008152506013019050604051809103902060001c0360001b9050805491505090565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610960576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f6f776e65722063616e6e6f74206265203000000000000000000000000000000081525060200191505060405180910390fd5b6000600160405180807f656970313936372e70726f78792e61646d696e000000000000000000000000008152506013019050604051809103902060001c0360001b90508181558173ffffffffffffffffffffffffffffffffffffffff167f50146d0e3c60aa1d17a70635b05494f864e86144a2201275021014fbf08bafe260405160405180910390a2505056fea165627a7a723058206808dd43e7d765afca53fe439122bc5eac16d708ce7d463451be5042426f101f0029\",\"storage\":{\"0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103\":\"0xE23a4c6615669526Ab58E9c37088bee4eD2b2dEE\"},\"balance\":\"0\"}}" ++ ++var celoL1GenesisAllocJSON = map[uint64]string{ ++ MainnetNetworkID: mainnetAllocJSON, ++ AlfajoresNetworkID: alfajoresAllocJSON, ++ BaklavaNetworkID: baklavaAllocJSON, ++} ++ ++// GetCeloL1GenesisAlloc returns the legacy Celo L1 genesis allocation JSON for the given network ID. ++func GetCeloL1GenesisAlloc(config *params.ChainConfig) ([]byte, error) { ++ chainID := config.ChainID.Uint64() ++ allocJSON, ok := celoL1GenesisAllocJSON[chainID] ++ if !ok { ++ return nil, fmt.Errorf("no genesis allocation JSON found for network ID %d", chainID) ++ } ++ return []byte(allocJSON), nil ++} ++ ++// BuildGenesis creates a genesis block from the given parameters. ++func BuildGenesis(config *params.ChainConfig, allocs, extraData []byte, timestamp uint64) (*core.Genesis, error) { ++ genesisAlloc := &types.GenesisAlloc{} ++ if err := genesisAlloc.UnmarshalJSON(allocs); err != nil { ++ return nil, err ++ } ++ return &core.Genesis{ ++ Config: config, ++ Timestamp: timestamp, ++ ExtraData: extraData, ++ Alloc: *genesisAlloc, ++ }, nil ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+455
+
-0
+ +
+ +
+
+
diff --git OP/op-chain-ops/cmd/celo-migrate/main.go CELO/op-chain-ops/cmd/celo-migrate/main.go +new file mode 100644 +index 0000000000000000000000000000000000000000..632ec8dd1587ebbb9f8deeafbacf871bc0907b99 +--- /dev/null ++++ CELO/op-chain-ops/cmd/celo-migrate/main.go +@@ -0,0 +1,455 @@ ++package main ++ ++import ( ++ "context" ++ "errors" ++ "fmt" ++ "math/big" ++ "os" ++ "os/exec" ++ "runtime/debug" ++ "time" ++ ++ "log/slog" ++ ++ "github.com/ethereum-optimism/optimism/op-chain-ops/foundry" ++ "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" ++ "github.com/ethereum-optimism/optimism/op-service/ioutil" ++ "github.com/ethereum-optimism/optimism/op-service/jsonutil" ++ oplog "github.com/ethereum-optimism/optimism/op-service/log" ++ "github.com/mattn/go-isatty" ++ ++ "github.com/urfave/cli/v2" ++ ++ "github.com/ethereum/go-ethereum/core/rawdb" ++ "github.com/ethereum/go-ethereum/core/types" ++ "github.com/ethereum/go-ethereum/ethclient" ++ "github.com/ethereum/go-ethereum/log" ++ "github.com/ethereum/go-ethereum/rpc" ++ ++ "golang.org/x/sync/errgroup" ++) ++ ++var ( ++ deployConfigFlag = &cli.PathFlag{ ++ Name: "deploy-config", ++ Usage: "Path to the JSON file that was used for the bedrock contracts deployment. A test example can be found here 'op-chain-ops/genesis/testdata/test-deploy-config-full.json' and documentation for the fields is at https://docs.optimism.io/builders/chain-operators/management/configuration", ++ Required: true, ++ } ++ l1DeploymentsFlag = &cli.PathFlag{ ++ Name: "l1-deployments", ++ Usage: "Path to L1 deployments JSON file, the output of running the bedrock contracts deployment for the given 'deploy-config'", ++ Required: true, ++ } ++ l1RPCFlag = &cli.StringFlag{ ++ Name: "l1-rpc", ++ Usage: "RPC URL for a node of the L1 defined in the 'deploy-config'", ++ Required: true, ++ } ++ l2AllocsFlag = &cli.PathFlag{ ++ Name: "l2-allocs", ++ Usage: "Path to L2 genesis allocs file. You can find instructions on how to generate this file in the README", ++ Required: true, ++ } ++ outfileRollupConfigFlag = &cli.PathFlag{ ++ Name: "outfile.rollup-config", ++ Usage: "Path to write the rollup config JSON file, to be provided to op-node with the 'rollup.config' flag", ++ Required: true, ++ } ++ outfileGenesisFlag = &cli.PathFlag{ ++ Name: "outfile.genesis", ++ Usage: "Path to write the genesis JSON file, to be used to sync new nodes", ++ Required: true, ++ } ++ migrationBlockNumberFlag = &cli.Uint64Flag{ ++ Name: "migration-block-number", ++ Usage: "Specifies the migration block number. If the source db is not synced exactly to the block immediately before this number (i.e. migration-block-number - 1), the migration will fail.", ++ Required: true, ++ } ++ migrationBlockTimeFlag = &cli.Uint64Flag{ ++ Name: "migration-block-time", ++ Usage: "Specifies a unix timestamp to use for the migration block. This should be set to the same timestamp as was used for the sequencer migration. If performing the sequencer migration, this should set to a time in the future around when the migration script is expected to complete.", ++ Required: true, ++ } ++ oldDBPathFlag = &cli.PathFlag{ ++ Name: "old-db", ++ Usage: "Path to the old Celo chaindata dir, can be found at '<datadir>/celo/chaindata'", ++ Required: true, ++ } ++ newDBPathFlag = &cli.PathFlag{ ++ Name: "new-db", ++ Usage: "Path to write migrated Celo chaindata, note the new node implementation expects to find this chaindata at the following path '<datadir>/geth/chaindata", ++ Required: true, ++ } ++ batchSizeFlag = &cli.Uint64Flag{ ++ Name: "batch-size", ++ Usage: "Batch size to use for block migration, larger batch sizes can speed up migration but require more memory. If increasing the batch size consider also increasing the memory-limit", ++ Value: 50000, // TODO(Alec) optimize default parameters ++ } ++ bufferSizeFlag = &cli.Uint64Flag{ ++ Name: "buffer-size", ++ Usage: "Buffer size to use for ancient block migration channels. Defaults to 0. Included to facilitate testing for performance improvements.", ++ Value: 0, ++ } ++ memoryLimitFlag = &cli.Int64Flag{ ++ Name: "memory-limit", ++ Usage: "Memory limit in MiB, should be set lower than the available amount of memory in your system to prevent out of memory errors", ++ Value: 7500, ++ } ++ reset = &cli.BoolFlag{ ++ Name: "reset", ++ Usage: "Delete everything in the destination directory aside from /ancients. This is useful if you need to re-run the full migration but do not want to repeat the lengthy ancients migration. If you'd like to reset the entire destination directory, you can delete it manually.", ++ Value: false, ++ } ++ ++ preMigrationFlags = []cli.Flag{ ++ oldDBPathFlag, ++ newDBPathFlag, ++ batchSizeFlag, ++ bufferSizeFlag, ++ memoryLimitFlag, ++ reset, ++ } ++ fullMigrationFlags = append( ++ preMigrationFlags, ++ deployConfigFlag, ++ l1DeploymentsFlag, ++ l1RPCFlag, ++ l2AllocsFlag, ++ outfileRollupConfigFlag, ++ outfileGenesisFlag, ++ migrationBlockTimeFlag, ++ migrationBlockNumberFlag, ++ ) ++) ++ ++type preMigrationOptions struct { ++ oldDBPath string ++ newDBPath string ++ batchSize uint64 ++ bufferSize uint64 ++ memoryLimit int64 ++ resetNonAncients bool ++} ++ ++type stateMigrationOptions struct { ++ deployConfig string ++ l1Deployments string ++ l1RPC string ++ l2AllocsPath string ++ outfileRollupConfig string ++ outfileGenesis string ++ migrationBlockTime uint64 ++} ++ ++type fullMigrationOptions struct { ++ preMigrationOptions ++ stateMigrationOptions ++ migrationBlockNumber uint64 ++} ++ ++func parsePreMigrationOptions(ctx *cli.Context) preMigrationOptions { ++ return preMigrationOptions{ ++ oldDBPath: ctx.String(oldDBPathFlag.Name), ++ newDBPath: ctx.String(newDBPathFlag.Name), ++ batchSize: ctx.Uint64(batchSizeFlag.Name), ++ bufferSize: ctx.Uint64(bufferSizeFlag.Name), ++ memoryLimit: ctx.Int64(memoryLimitFlag.Name), ++ resetNonAncients: ctx.Bool(reset.Name), ++ } ++} ++ ++func parseStateMigrationOptions(ctx *cli.Context) stateMigrationOptions { ++ return stateMigrationOptions{ ++ deployConfig: ctx.Path(deployConfigFlag.Name), ++ l1Deployments: ctx.Path(l1DeploymentsFlag.Name), ++ l1RPC: ctx.String(l1RPCFlag.Name), ++ l2AllocsPath: ctx.Path(l2AllocsFlag.Name), ++ outfileRollupConfig: ctx.Path(outfileRollupConfigFlag.Name), ++ outfileGenesis: ctx.Path(outfileGenesisFlag.Name), ++ migrationBlockTime: ctx.Uint64(migrationBlockTimeFlag.Name), ++ } ++} ++ ++func parseFullMigrationOptions(ctx *cli.Context) fullMigrationOptions { ++ return fullMigrationOptions{ ++ preMigrationOptions: parsePreMigrationOptions(ctx), ++ stateMigrationOptions: parseStateMigrationOptions(ctx), ++ migrationBlockNumber: ctx.Uint64(migrationBlockNumberFlag.Name), ++ } ++} ++ ++func main() { ++ ++ color := isatty.IsTerminal(os.Stderr.Fd()) ++ handler := log.NewTerminalHandlerWithLevel(os.Stderr, slog.LevelInfo, color) ++ oplog.SetGlobalLogHandler(handler) ++ ++ app := &cli.App{ ++ Name: "celo-migrate", ++ Usage: "Migrate Celo block and state data to a CeL2 DB", ++ Commands: []*cli.Command{ ++ { ++ Name: "pre", ++ Usage: "Perform a pre-migration of ancient blocks and copy over all other data without transforming it. This should be run a day before the full migration command is run to minimize downtime.", ++ Flags: preMigrationFlags, ++ Action: func(ctx *cli.Context) error { ++ if _, _, err := runPreMigration(parsePreMigrationOptions(ctx)); err != nil { ++ return fmt.Errorf("failed to run pre-migration: %w", err) ++ } ++ log.Info("Finished pre migration successfully!") ++ return nil ++ }, ++ }, ++ { ++ Name: "full", ++ Usage: "Perform a full migration of both block and state data to a CeL2 DB", ++ Flags: fullMigrationFlags, ++ Action: func(ctx *cli.Context) error { ++ if err := runFullMigration(parseFullMigrationOptions(ctx)); err != nil { ++ return fmt.Errorf("failed to run full migration: %w", err) ++ } ++ log.Info("Finished full migration successfully!") ++ return nil ++ }, ++ }, ++ }, ++ OnUsageError: func(ctx *cli.Context, err error, isSubcommand bool) error { ++ if isSubcommand { ++ return err ++ } ++ _ = cli.ShowAppHelp(ctx) ++ return fmt.Errorf("please provide a valid command") ++ }, ++ } ++ ++ if err := app.Run(os.Args); err != nil { ++ log.Crit("error in migration", "err", err) ++ } ++} ++ ++func runFullMigration(opts fullMigrationOptions) error { ++ defer timer("full migration")() ++ ++ log.Info("Full Migration Started", "oldDBPath", opts.oldDBPath, "newDBPath", opts.newDBPath) ++ ++ head, err := getHeadHeader(opts.oldDBPath) ++ if err != nil { ++ return fmt.Errorf("failed to get head header: %w", err) ++ } ++ if head.Number.Uint64() != opts.migrationBlockNumber-1 { ++ return fmt.Errorf("old-db head block number not synced to the block immediately before the migration block number: %d != %d", head.Number.Uint64(), opts.migrationBlockNumber-1) ++ } ++ ++ log.Info("Source db is synced to correct height", "head", head.Number.Uint64(), "migrationBlock", opts.migrationBlockNumber) ++ ++ var numAncients uint64 ++ var strayAncientBlocks []*rawdb.NumberHash ++ ++ if strayAncientBlocks, numAncients, err = runPreMigration(opts.preMigrationOptions); err != nil { ++ return fmt.Errorf("failed to run pre-migration: %w", err) ++ } ++ ++ if err = runNonAncientMigration(opts.newDBPath, strayAncientBlocks, opts.batchSize, numAncients); err != nil { ++ return fmt.Errorf("failed to run non-ancient migration: %w", err) ++ } ++ if err = runStateMigration(opts.newDBPath, opts.stateMigrationOptions); err != nil { ++ return fmt.Errorf("failed to run state migration: %w", err) ++ } ++ ++ log.Info("Full Migration Finished", "oldDBPath", opts.oldDBPath, "newDBPath", opts.newDBPath) ++ ++ return nil ++} ++ ++func runPreMigration(opts preMigrationOptions) ([]*rawdb.NumberHash, uint64, error) { ++ defer timer("pre-migration")() ++ ++ log.Info("Pre-Migration Started", "oldDBPath", opts.oldDBPath, "newDBPath", opts.newDBPath, "batchSize", opts.batchSize, "memoryLimit", opts.memoryLimit) ++ ++ // Check that `rsync` command is available. We use this to copy the db excluding ancients, which we will copy separately ++ if _, err := exec.LookPath("rsync"); err != nil { ++ return nil, 0, fmt.Errorf("please install `rsync` to run block migration") ++ } ++ ++ debug.SetMemoryLimit(opts.memoryLimit * 1 << 20) // Set memory limit, converting from MiB to bytes ++ ++ var err error ++ ++ if err = createNewDbPathIfNotExists(opts.newDBPath); err != nil { ++ return nil, 0, fmt.Errorf("failed to create new db path: %w", err) ++ } ++ ++ if opts.resetNonAncients { ++ if err = cleanupNonAncientDb(opts.newDBPath); err != nil { ++ return nil, 0, fmt.Errorf("failed to cleanup non-ancient db: %w", err) ++ } ++ } ++ ++ var numAncientsNewBefore uint64 ++ var numAncientsNewAfter uint64 ++ var strayAncientBlocks []*rawdb.NumberHash ++ g, ctx := errgroup.WithContext(context.Background()) ++ g.Go(func() error { ++ if numAncientsNewBefore, numAncientsNewAfter, err = migrateAncientsDb(ctx, opts.oldDBPath, opts.newDBPath, opts.batchSize, opts.bufferSize); err != nil { ++ return fmt.Errorf("failed to migrate ancients database: %w", err) ++ } ++ // Scanning for stray ancient blocks is slow, so we do it as soon as we can after the lock on oldDB is released by migrateAncientsDb ++ // Doing this in parallel with copyDbExceptAncients still saves time if ancients have already been pre-migrated ++ if strayAncientBlocks, err = getStrayAncientBlocks(opts.oldDBPath); err != nil { ++ return fmt.Errorf("failed to get stray ancient blocks: %w", err) ++ } ++ return nil ++ }) ++ g.Go(func() error { ++ // By doing this once during the premigration, we get a speedup when we run it again in a full migration. ++ return copyDbExceptAncients(opts.oldDBPath, opts.newDBPath) ++ }) ++ ++ if err = g.Wait(); err != nil { ++ return nil, 0, fmt.Errorf("failed to migrate blocks: %w", err) ++ } ++ ++ log.Info("Pre-Migration Finished", "oldDBPath", opts.oldDBPath, "newDBPath", opts.newDBPath, "migratedAncients", numAncientsNewAfter-numAncientsNewBefore, "strayAncientBlocks", len(strayAncientBlocks)) ++ ++ return strayAncientBlocks, numAncientsNewAfter, nil ++} ++ ++func runNonAncientMigration(newDBPath string, strayAncientBlocks []*rawdb.NumberHash, batchSize, numAncients uint64) error { ++ defer timer("non-ancient migration")() ++ ++ newDB, err := openDBWithoutFreezer(newDBPath, false) ++ if err != nil { ++ return fmt.Errorf("failed to open new database: %w", err) ++ } ++ defer newDB.Close() ++ ++ // get the last block number ++ hash := rawdb.ReadHeadHeaderHash(newDB) ++ lastBlock := *rawdb.ReadHeaderNumber(newDB, hash) ++ lastAncient := numAncients - 1 ++ ++ log.Info("Non-Ancient Block Migration Started", "process", "non-ancients", "newDBPath", newDBPath, "batchSize", batchSize, "startBlock", numAncients, "endBlock", lastBlock, "count", lastBlock-lastAncient, "lastAncientBlock", lastAncient) ++ ++ var numNonAncients uint64 ++ if numNonAncients, err = migrateNonAncientsDb(newDB, lastBlock, numAncients, batchSize); err != nil { ++ return fmt.Errorf("failed to migrate non-ancients database: %w", err) ++ } ++ ++ err = removeBlocks(newDB, strayAncientBlocks) ++ if err != nil { ++ return fmt.Errorf("failed to remove stray ancient blocks: %w", err) ++ } ++ log.Info("Removed stray ancient blocks still in leveldb", "process", "non-ancients", "removedBlocks", len(strayAncientBlocks)) ++ ++ log.Info("Non-Ancient Block Migration Completed", "process", "non-ancients", "migratedNonAncients", numNonAncients) ++ ++ return nil ++} ++ ++func runStateMigration(newDBPath string, opts stateMigrationOptions) error { ++ defer timer("state migration")() ++ ++ log.Info("State Migration Started", "newDBPath", newDBPath, "deployConfig", opts.deployConfig, "l1Deployments", opts.l1Deployments, "l1RPC", opts.l1RPC, "l2AllocsPath", opts.l2AllocsPath, "outfileRollupConfig", opts.outfileRollupConfig) ++ ++ // Read deployment configuration ++ config, err := genesis.NewDeployConfig(opts.deployConfig) ++ if err != nil { ++ return err ++ } ++ ++ if config.DeployCeloContracts { ++ return errors.New("DeployCeloContracts is not supported in migration") ++ } ++ if config.FundDevAccounts { ++ return errors.New("FundDevAccounts is not supported in migration") ++ } ++ ++ // Try reading the L1 deployment information ++ deployments, err := genesis.NewL1Deployments(opts.l1Deployments) ++ if err != nil { ++ return fmt.Errorf("cannot read L1 deployments at %s: %w", opts.l1Deployments, err) ++ } ++ config.SetDeployments(deployments) ++ ++ // Get latest block information from L1 ++ var l1StartBlock *types.Block ++ client, err := ethclient.Dial(opts.l1RPC) ++ if err != nil { ++ return fmt.Errorf("cannot dial %s: %w", opts.l1RPC, err) ++ } ++ ++ if config.L1StartingBlockTag == nil { ++ l1StartBlock, err = client.BlockByNumber(context.Background(), nil) ++ if err != nil { ++ return fmt.Errorf("cannot fetch latest block: %w", err) ++ } ++ tag := rpc.BlockNumberOrHashWithHash(l1StartBlock.Hash(), true) ++ config.L1StartingBlockTag = (*genesis.MarshalableRPCBlockNumberOrHash)(&tag) ++ } else if config.L1StartingBlockTag.BlockHash != nil { ++ l1StartBlock, err = client.BlockByHash(context.Background(), *config.L1StartingBlockTag.BlockHash) ++ if err != nil { ++ return fmt.Errorf("cannot fetch block by hash: %w", err) ++ } ++ } else if config.L1StartingBlockTag.BlockNumber != nil { ++ l1StartBlock, err = client.BlockByNumber(context.Background(), big.NewInt(config.L1StartingBlockTag.BlockNumber.Int64())) ++ if err != nil { ++ return fmt.Errorf("cannot fetch block by number: %w", err) ++ } ++ } ++ ++ // Ensure that there is a starting L1 block ++ if l1StartBlock == nil { ++ return fmt.Errorf("no starting L1 block") ++ } ++ ++ // Sanity check the config. Do this after filling in the L1StartingBlockTag ++ // if it is not defined. ++ if err := config.Check(log.New()); err != nil { ++ return err ++ } ++ ++ log.Info("Using L1 Start Block", "number", l1StartBlock.Number(), "hash", l1StartBlock.Hash().Hex()) ++ ++ // Build the L2 genesis block ++ l2Allocs, err := foundry.LoadForgeAllocs(opts.l2AllocsPath) ++ if err != nil { ++ return err ++ } ++ ++ l2Genesis, err := genesis.BuildL2Genesis(config, l2Allocs, l1StartBlock.Header()) ++ if err != nil { ++ return fmt.Errorf("error creating l2 genesis: %w", err) ++ } ++ ++ // Write changes to state to actual state database ++ cel2Header, err := applyStateMigrationChanges(config, l2Genesis.Alloc, newDBPath, opts.outfileGenesis, opts.migrationBlockTime, l1StartBlock) ++ if err != nil { ++ return err ++ } ++ log.Info("Updated Cel2 state") ++ ++ rollupConfig, err := config.RollupConfig(l1StartBlock.Header(), cel2Header.Hash(), cel2Header.Number.Uint64()) ++ if err != nil { ++ return err ++ } ++ if err := rollupConfig.Check(); err != nil { ++ return fmt.Errorf("generated rollup config does not pass validation: %w", err) ++ } ++ ++ log.Info("Writing rollup config", "file", opts.outfileRollupConfig) ++ if err := jsonutil.WriteJSON(rollupConfig, ioutil.ToStdOutOrFileOrNoop(opts.outfileRollupConfig, OutFilePerm)); err != nil { ++ return err ++ } ++ ++ log.Info("State Migration Completed") ++ ++ return nil ++} ++ ++func timer(name string) func() { ++ start := time.Now() ++ return func() { ++ log.Info("TIMER", "process", name, "duration", time.Since(start)) ++ } ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+118
+
-0
+ +
+ +
+
+
diff --git OP/op-chain-ops/cmd/celo-migrate/non-ancients.go CELO/op-chain-ops/cmd/celo-migrate/non-ancients.go +new file mode 100644 +index 0000000000000000000000000000000000000000..5ad184e2dd248e2387b57f986fa1a7a55f0b225b +--- /dev/null ++++ CELO/op-chain-ops/cmd/celo-migrate/non-ancients.go +@@ -0,0 +1,118 @@ ++package main ++ ++import ( ++ "fmt" ++ "os" ++ "os/exec" ++ "strings" ++ ++ "github.com/ethereum/go-ethereum/common" ++ "github.com/ethereum/go-ethereum/core/rawdb" ++ "github.com/ethereum/go-ethereum/ethdb" ++ "github.com/ethereum/go-ethereum/log" ++) ++ ++func copyDbExceptAncients(oldDbPath, newDbPath string) error { ++ defer timer("copyDbExceptAncients")() ++ ++ log.Info("Copying files from old database (excluding ancients)", "process", "non-ancients") ++ ++ // Get rsync help output ++ cmdHelp := exec.Command("rsync", "--help") ++ output, _ := cmdHelp.CombinedOutput() ++ ++ // Convert output to string ++ outputStr := string(output) ++ ++ opts := []string{"-v", "-a", "--exclude=ancient", "--checksum", "--delete"} ++ ++ // Check for supported options ++ // Prefer --info=progress2 over --progress ++ if strings.Contains(outputStr, "--info") { ++ opts = append(opts, "--info=progress2") ++ } else if strings.Contains(outputStr, "--progress") { ++ opts = append(opts, "--progress") ++ } ++ ++ cmd := exec.Command("rsync", append(opts, oldDbPath+"/", newDbPath)...) ++ ++ // rsync copies any file with a different timestamp or size. ++ // ++ // '--exclude=ancient' excludes the ancient directory from the copy ++ // ++ // '--delete' Tells rsync to delete extraneous files from the receiving side (ones that aren’t on the sending side) ++ // ++ // '-a' archive mode; equals -rlptgoD. It is a quick way of saying you want recursion and want to preserve almost everything, including timestamps, ownerships, permissions, etc. ++ // Timestamps are important here because they are used to determine which files are newer and should be copied over. ++ // ++ // '--whole-file' This is the default when both the source and destination are specified as local paths, which they are here (oldDbPath and newDbPath). ++ // This option disables rsync’s delta-transfer algorithm, which causes all transferred files to be sent whole. The delta-transfer algorithm is normally used when the destination is a remote system. ++ // ++ // '--checksum' This forces rsync to compare the checksums of all files to determine if they are the same. This is slows down the transfer but ensures that source and destination directories end up with the same contents (excluding /ancients). ++ ++ log.Info("Running rsync command", "command", cmd.String()) ++ cmd.Stdout = os.Stdout ++ cmd.Stderr = os.Stderr ++ if err := cmd.Run(); err != nil { ++ return fmt.Errorf("failed to copy old database to new database: %w", err) ++ } ++ return nil ++} ++ ++func migrateNonAncientsDb(newDB ethdb.Database, lastBlock, numAncients, batchSize uint64) (uint64, error) { ++ defer timer("migrateNonAncientsDb")() ++ ++ // The genesis block is also migrated in the ancient db migration as it is stored in both places. ++ // The genesis block is the only block that should remain stored in the non-ancient db even after it is frozen. ++ if numAncients > 0 { ++ log.Info("Migrating genesis block in non-ancient db", "process", "non-ancients") ++ if err := migrateNonAncientBlock(0, rawdb.ReadCanonicalHash(newDB, 0), newDB); err != nil { ++ return 0, err ++ } ++ } ++ ++ for i := numAncients; i <= lastBlock; i += batchSize { ++ numbersHash := rawdb.ReadAllHashesInRange(newDB, i, i+batchSize-1) ++ ++ log.Info("Processing Block Range", "process", "non-ancients", "from", i, "to(inclusve)", i+batchSize-1, "count", len(numbersHash)) ++ for _, numberHash := range numbersHash { ++ if err := migrateNonAncientBlock(numberHash.Number, numberHash.Hash, newDB); err != nil { ++ return 0, err ++ } ++ } ++ } ++ ++ migratedCount := lastBlock - numAncients + 1 ++ return migratedCount, nil ++} ++ ++func migrateNonAncientBlock(number uint64, hash common.Hash, newDB ethdb.Database) error { ++ // read header and body ++ header := rawdb.ReadHeaderRLP(newDB, hash, number) ++ body := rawdb.ReadBodyRLP(newDB, hash, number) ++ ++ // transform header and body ++ newHeader, err := transformHeader(header) ++ if err != nil { ++ return fmt.Errorf("failed to transform header: block %d - %x: %w", number, hash, err) ++ } ++ newBody, err := transformBlockBody(body) ++ if err != nil { ++ return fmt.Errorf("failed to transform body: block %d - %x: %w", number, hash, err) ++ } ++ ++ if yes, newHash := hasSameHash(newHeader, hash[:]); !yes { ++ log.Error("Hash mismatch", "block", number, "oldHash", hash, "newHash", newHash) ++ return fmt.Errorf("hash mismatch at block %d - %x", number, hash) ++ } ++ ++ // write header and body ++ batch := newDB.NewBatch() ++ rawdb.WriteBodyRLP(batch, hash, number, newBody) ++ _ = batch.Put(headerKey(number, hash), newHeader) ++ if err := batch.Write(); err != nil { ++ return fmt.Errorf("failed to write header and body: block %d - %x: %w", number, hash, err) ++ } ++ ++ return nil ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+454
+
-0
+ +
+ +
+
+
diff --git OP/op-chain-ops/cmd/celo-migrate/state.go CELO/op-chain-ops/cmd/celo-migrate/state.go +new file mode 100644 +index 0000000000000000000000000000000000000000..5c029c8453b0318358fb59ed666cfd27919e9011 +--- /dev/null ++++ CELO/op-chain-ops/cmd/celo-migrate/state.go +@@ -0,0 +1,454 @@ ++package main ++ ++import ( ++ "encoding/json" ++ "errors" ++ "fmt" ++ "math/big" ++ "os" ++ ++ "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" ++ "github.com/ethereum-optimism/optimism/op-service/ioutil" ++ "github.com/ethereum-optimism/optimism/op-service/jsonutil" ++ "github.com/ethereum-optimism/optimism/op-service/predeploys" ++ "github.com/ethereum/go-ethereum/common" ++ "github.com/ethereum/go-ethereum/consensus/misc/eip1559" ++ "github.com/ethereum/go-ethereum/contracts/addresses" ++ "github.com/ethereum/go-ethereum/core/rawdb" ++ "github.com/ethereum/go-ethereum/core/state" ++ "github.com/ethereum/go-ethereum/core/tracing" ++ "github.com/ethereum/go-ethereum/core/types" ++ "github.com/ethereum/go-ethereum/core/vm" ++ "github.com/ethereum/go-ethereum/ethdb" ++ "github.com/ethereum/go-ethereum/log" ++ "github.com/ethereum/go-ethereum/params" ++ "github.com/ethereum/go-ethereum/trie" ++ ++ "github.com/holiman/uint256" ++) ++ ++const ( ++ MainnetNetworkID = uint64(42220) ++ BaklavaNetworkID = uint64(62320) ++ AlfajoresNetworkID = uint64(44787) ++ ++ OutFilePerm = os.FileMode(0o440) ++) ++ ++var ( ++ Big10 = uint256.NewInt(10) ++ Big9 = uint256.NewInt(9) ++ Big18 = uint256.NewInt(18) ++ ++ // Allowlist of accounts that are allowed to be overwritten ++ // If the value for an account is set to true, the nonce and storage will be overwritten ++ // This must be checked for each account, as this might create issues with contracts ++ // calling `CREATE` or `CREATE2` ++ accountOverwriteAllowlist = map[uint64]map[common.Address]bool{ ++ // Add any addresses that should be allowed to overwrite existing accounts here. ++ AlfajoresNetworkID: { ++ // Create2Deployer ++ // OP uses a version without an owner who can pause the contract, ++ // so we overwrite the existing contract during migration ++ common.HexToAddress("0x13b0D85CcB8bf860b6b79AF3029fCA081AE9beF2"): true, ++ ++ // Same code as in allocs file ++ // EntryPoint_v070 ++ common.HexToAddress("0x0000000071727De22E5E9d8BAf0edAc6f37da032"): false, ++ // Permit2 ++ common.HexToAddress("0x000000000022D473030F116dDEE9F6B43aC78BA3"): false, ++ // EntryPoint_v060 ++ common.HexToAddress("0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789"): false, ++ // DeterministicDeploymentProxy ++ common.HexToAddress("0x4e59b44847b379578588920cA78FbF26c0B4956C"): false, ++ // SafeL2_v130 ++ common.HexToAddress("0xfb1bffC9d739B8D520DaF37dF666da4C687191EA"): false, ++ // MultiSend_v130 ++ common.HexToAddress("0x998739BFdAAdde7C933B942a68053933098f9EDa"): false, ++ // SenderCreator_v070 ++ common.HexToAddress("0xEFC2c1444eBCC4Db75e7613d20C6a62fF67A167C"): false, ++ // SenderCreator_v060 ++ common.HexToAddress("0x7fc98430eAEdbb6070B35B39D798725049088348"): false, ++ // MultiCall3 ++ common.HexToAddress("0xcA11bde05977b3631167028862bE2a173976CA11"): false, ++ // Safe_v130 ++ common.HexToAddress("0x69f4D1788e39c87893C980c06EdF4b7f686e2938"): false, ++ // MultiSendCallOnly_v130 ++ common.HexToAddress("0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B"): false, ++ // SafeSingletonFactory ++ common.HexToAddress("0x914d7Fec6aaC8cd542e72Bca78B30650d45643d7"): false, ++ // CreateX ++ common.HexToAddress("0xba5Ed099633D3B313e4D5F7bdc1305d3c28ba5Ed"): false, ++ }, ++ } ++ unreleasedTreasuryAddressMap = map[uint64]common.Address{ ++ AlfajoresNetworkID: common.HexToAddress("0x07bf0b2461A0cb608D5CF9a82ba97dAbA850F79F"), ++ } ++ celoTokenAddressMap = map[uint64]common.Address{ ++ AlfajoresNetworkID: addresses.CeloTokenAlfajoresAddress, ++ MainnetNetworkID: addresses.CeloTokenAddress, ++ } ++) ++ ++func applyStateMigrationChanges(config *genesis.DeployConfig, l2Allocs types.GenesisAlloc, dbPath, genesisOutPath string, migrationBlockTime uint64, l1StartBlock *types.Block) (*types.Header, error) { ++ log.Info("Opening Celo database", "dbPath", dbPath) ++ ++ ldb, err := openDBWithoutFreezer(dbPath, false) ++ if err != nil { ++ return nil, fmt.Errorf("cannot open DB: %w", err) ++ } ++ log.Info("Loaded Celo L1 DB", "db", ldb) ++ ++ // Grab the hash of the tip of the legacy chain. ++ hash := rawdb.ReadHeadHeaderHash(ldb) ++ log.Info("Reading chain tip from database", "hash", hash) ++ ++ // Grab the header number. ++ num := rawdb.ReadHeaderNumber(ldb, hash) ++ if num == nil { ++ return nil, fmt.Errorf("cannot find header number for %s", hash) ++ } ++ log.Info("Reading chain tip num from database", "number", *num) ++ ++ // Grab the full header. ++ header := rawdb.ReadHeader(ldb, hash, *num) ++ log.Info("Read header from database", "header", header) ++ ++ // We need to update the chain config to set the correct hardforks. ++ genesisHash := rawdb.ReadCanonicalHash(ldb, 0) ++ cfg := rawdb.ReadChainConfig(ldb, genesisHash) ++ if cfg == nil { ++ log.Crit("chain config not found") ++ } ++ log.Info("Read chain config from database", "config", cfg) ++ ++ // Set up the backing store. ++ underlyingDB := state.NewDatabase(ldb) ++ ++ // Open up the state database. ++ db, err := state.New(header.Root, underlyingDB, nil) ++ if err != nil { ++ return nil, fmt.Errorf("cannot open StateDB: %w", err) ++ } ++ ++ // Apply the changes to the state DB. ++ err = applyAllocsToState(db, l2Allocs, accountOverwriteAllowlist[cfg.ChainID.Uint64()]) ++ if err != nil { ++ return nil, fmt.Errorf("cannot apply allocations to state: %w", err) ++ } ++ ++ // Initialize the unreleased treasury contract ++ // This uses the original config which won't enable recent hardforks (and things like the PUSH0 opcode) ++ // This is fine, as the token uses solc 0.5.x and therefore compatible bytecode ++ err = setupUnreleasedTreasury(db, cfg) ++ if err != nil { ++ // An error here shouldn't stop the migration, just log it ++ log.Warn("Error setting up unreleased treasury", "error", err) ++ } ++ ++ migrationBlockNumber := new(big.Int).Add(header.Number, common.Big1) ++ ++ // We're done messing around with the database, so we can now commit the changes to the DB. ++ // Note that this doesn't actually write the changes to disk. ++ log.Info("Committing state DB") ++ newRoot, err := db.Commit(migrationBlockNumber.Uint64(), true) ++ if err != nil { ++ return nil, err ++ } ++ ++ // Set the standard options. ++ cfg.LondonBlock = migrationBlockNumber ++ cfg.BerlinBlock = migrationBlockNumber ++ cfg.ArrowGlacierBlock = migrationBlockNumber ++ cfg.GrayGlacierBlock = migrationBlockNumber ++ cfg.MergeNetsplitBlock = migrationBlockNumber ++ cfg.TerminalTotalDifficulty = big.NewInt(0) ++ cfg.TerminalTotalDifficultyPassed = true ++ cfg.ShanghaiTime = &migrationBlockTime ++ cfg.CancunTime = &migrationBlockTime ++ ++ // Set the Optimism options. ++ cfg.Optimism = &params.OptimismConfig{ ++ EIP1559Denominator: config.EIP1559Denominator, ++ EIP1559DenominatorCanyon: &config.EIP1559DenominatorCanyon, ++ EIP1559Elasticity: config.EIP1559Elasticity, ++ } ++ ++ // Set the Celo options. ++ cfg.Celo = &params.CeloConfig{ ++ EIP1559BaseFeeFloor: config.EIP1559BaseFeeFloor, ++ } ++ ++ // Set Optimism hardforks ++ cfg.BedrockBlock = migrationBlockNumber ++ cfg.RegolithTime = &migrationBlockTime ++ cfg.CanyonTime = &migrationBlockTime ++ cfg.EcotoneTime = &migrationBlockTime ++ cfg.FjordTime = &migrationBlockTime ++ cfg.GraniteTime = &migrationBlockTime ++ cfg.Cel2Time = &migrationBlockTime ++ ++ // Calculate the base fee for the migration block. ++ baseFee := new(big.Int).SetUint64(params.InitialBaseFee) ++ if header.BaseFee != nil { ++ baseFee = eip1559.CalcBaseFee(cfg, header, migrationBlockTime) ++ } ++ ++ // If gas limit was zero at the transition point use a default of 30M. ++ // Note that in op-geth we use gasLimit==0 to indicate a pre-gingerbread ++ // block and adjust encoding appropriately, so we must make sure that ++ // gasLimit is non-zero, because L2 blocks are all post gingerbread. ++ gasLimit := header.GasLimit ++ if gasLimit == 0 { ++ gasLimit = 30e6 ++ } ++ // Create the header for the Cel2 transition block. ++ cel2Header := &types.Header{ ++ ParentHash: header.Hash(), ++ UncleHash: types.EmptyUncleHash, ++ Coinbase: predeploys.SequencerFeeVaultAddr, ++ Root: newRoot, ++ TxHash: types.EmptyTxsHash, ++ ReceiptHash: types.EmptyReceiptsHash, ++ Bloom: types.Bloom{}, ++ Difficulty: new(big.Int).Set(common.Big0), ++ Number: migrationBlockNumber, ++ GasLimit: gasLimit, ++ GasUsed: 0, ++ Time: migrationBlockTime, ++ Extra: []byte("Celo L2 migration"), ++ MixDigest: common.Hash{}, ++ Nonce: types.BlockNonce{}, ++ BaseFee: baseFee, ++ // Added during Shanghai hardfork ++ // As there're no withdrawals in L2, we set it to the empty hash ++ WithdrawalsHash: &types.EmptyWithdrawalsHash, ++ // Blobs are disabled in L2 ++ BlobGasUsed: new(uint64), ++ ExcessBlobGas: new(uint64), ++ // This is set to the ParentBeaconRoot of the L1 origin (see `PreparePayloadAttributes`) ++ // Use the L1 start block's ParentBeaconRoot ++ ParentBeaconRoot: l1StartBlock.Header().ParentBeaconRoot, ++ } ++ log.Info("Build Cel2 migration header", "header", cel2Header) ++ ++ // We need to set empty withdrawals in the body, otherwise types.NewBlock will nullify the withdrawals hash in the given header. ++ b := &types.Body{ ++ Withdrawals: []*types.Withdrawal{}, ++ } ++ // Create the Cel2 transition block from the header. Note that there are no transactions, ++ // uncle blocks, or receipts in the Cel2 transition block. ++ cel2Block := types.NewBlock(cel2Header, b, nil, trie.NewStackTrie(nil)) ++ ++ // We did it! ++ log.Info( ++ "Built Cel2 migration block", ++ "hash", cel2Block.Hash(), ++ "root", cel2Block.Root(), ++ "number", cel2Block.NumberU64(), ++ ) ++ ++ log.Info("Committing trie DB") ++ if err := db.Database().TrieDB().Commit(newRoot, true); err != nil { ++ return nil, err ++ } ++ ++ // Next we write the Cel2 migration block to the database. ++ rawdb.WriteTd(ldb, cel2Block.Hash(), cel2Block.NumberU64(), cel2Block.Difficulty()) ++ rawdb.WriteBlock(ldb, cel2Block) ++ rawdb.WriteReceipts(ldb, cel2Block.Hash(), cel2Block.NumberU64(), nil) ++ rawdb.WriteCanonicalHash(ldb, cel2Block.Hash(), cel2Block.NumberU64()) ++ rawdb.WriteHeadBlockHash(ldb, cel2Block.Hash()) ++ rawdb.WriteHeadFastBlockHash(ldb, cel2Block.Hash()) ++ rawdb.WriteHeadHeaderHash(ldb, cel2Block.Hash()) ++ ++ // Mark the first CeL2 block as finalized ++ rawdb.WriteFinalizedBlockHash(ldb, cel2Block.Hash()) ++ ++ // Write the chain config to disk. ++ rawdb.WriteChainConfig(ldb, genesisHash, cfg) ++ marshalledConfig, err := json.Marshal(cfg) ++ if err != nil { ++ return nil, fmt.Errorf("failed to marshal chain config to JSON: %w", err) ++ } ++ log.Info("Wrote updated chain config", "config", string(marshalledConfig)) ++ ++ // Write genesis JSON to outfile and store genesis state spec in the database. ++ if err = writeGenesis(cfg, ldb, genesisOutPath, genesisHash); err != nil { ++ return nil, err ++ } ++ ++ // We're done! ++ log.Info( ++ "Wrote CeL2 migration block", ++ "height", cel2Header.Number, ++ "root", cel2Header.Root.String(), ++ "hash", cel2Header.Hash().String(), ++ "timestamp", cel2Header.Time, ++ ) ++ ++ // Close the database handle ++ if err := ldb.Close(); err != nil { ++ return nil, err ++ } ++ ++ return cel2Header, nil ++} ++ ++// applyAllocsToState applies the account allocations from the allocation file to the state database. ++// It creates new accounts, sets their nonce, balance, code, and storage values. ++// If an account already exists, it adds the balance of the new account to the existing balance. ++// If the code of an existing account is different from the code in the genesis block, it logs a warning. ++// This changes the state root, so `Commit` needs to be called after this function. ++func applyAllocsToState(db vm.StateDB, allocs types.GenesisAlloc, allowlist map[common.Address]bool) error { ++ log.Info("Starting to migrate OP contracts into state DB") ++ ++ copyCounter := 0 ++ overwriteCounter := 0 ++ ++ for k, v := range allocs { ++ // Check that the balance of the account to written is zero, ++ // as we must not create new CELO tokens ++ if v.Balance != nil && v.Balance.Cmp(big.NewInt(0)) != 0 { ++ return fmt.Errorf("account balance is not zero, would change celo supply: %s", k.Hex()) ++ } ++ ++ if db.Exist(k) { ++ writeNonceAndStorage := false ++ writeCode, allowed := allowlist[k] ++ ++ // If the account is not allowed and has a non zero nonce or code size, bail out we will need to manually investigate how to handle this. ++ if !allowed && (db.GetCodeSize(k) > 0 || db.GetNonce(k) > 0) { ++ return fmt.Errorf("account exists and is not allowed, account: %s, nonce: %d, code: %d", k.Hex(), db.GetNonce(k), db.GetCode(k)) ++ } ++ ++ // This means that the account just has balance, in that case we wan to copy over the account ++ if db.GetCodeSize(k) == 0 && db.GetNonce(k) == 0 { ++ writeCode = true ++ writeNonceAndStorage = true ++ } ++ ++ if writeCode { ++ overwriteCounter++ ++ ++ db.SetCode(k, v.Code) ++ ++ if writeNonceAndStorage { ++ db.SetNonce(k, v.Nonce) ++ for key, value := range v.Storage { ++ db.SetState(k, key, value) ++ } ++ } ++ log.Info("Overwrote account", "address", k.Hex(), "writeNonceAndStorage", writeNonceAndStorage) ++ } ++ continue ++ } ++ ++ // Account does not exist, create it ++ db.CreateAccount(k) ++ db.SetCode(k, v.Code) ++ db.SetNonce(k, v.Nonce) ++ for key, value := range v.Storage { ++ db.SetState(k, key, value) ++ } ++ ++ copyCounter++ ++ log.Info("Copied account", "address", k.Hex()) ++ } ++ ++ log.Info("Migrated OP contracts into state DB", "totalAllocs", len(allocs), "copiedAccounts", copyCounter, "overwrittenAccounts", overwriteCounter) ++ return nil ++} ++ ++// setupUnreleasedTreasury sets up the unreleased treasury contract with the correct balance ++// The balance is set to the difference between the ceiling and the total supply of the token ++func setupUnreleasedTreasury(db *state.StateDB, config *params.ChainConfig) error { ++ log.Info("Setting up CeloUnreleasedTreasury balance") ++ ++ celoUnreleasedTreasuryAddress, exists := unreleasedTreasuryAddressMap[config.ChainID.Uint64()] ++ if !exists { ++ return errors.New("CeloUnreleasedTreasury address not configured for this chain, skipping migration step") ++ } ++ ++ if !db.Exist(celoUnreleasedTreasuryAddress) { ++ return errors.New("CeloUnreleasedTreasury account does not exist, skipping migration step") ++ } ++ ++ tokenAddress, exists := celoTokenAddressMap[config.ChainID.Uint64()] ++ if !exists { ++ return errors.New("celo token address not configured for this chain, skipping migration step") ++ } ++ log.Info("Read contract addresses", "tokenAddress", tokenAddress, "celoUnreleasedTreasuryAddress", celoUnreleasedTreasuryAddress) ++ ++ // totalSupply is stored in the third slot ++ totalSupply := db.GetState(tokenAddress, common.HexToHash("0x02")).Big() ++ ++ // Get total supply of celo token ++ billion := new(uint256.Int).Exp(Big10, Big9) ++ ethInWei := new(uint256.Int).Exp(Big10, Big18) ++ ++ ceiling := new(uint256.Int).Mul(billion, ethInWei) ++ ++ supplyU256 := uint256.MustFromBig(totalSupply) ++ if supplyU256.Cmp(ceiling) > 0 { ++ return fmt.Errorf("supply %s is greater than ceiling %s", totalSupply, ceiling) ++ } ++ ++ balance := new(uint256.Int).Sub(ceiling, supplyU256) ++ // Don't discard existing balance of the account ++ balance = new(uint256.Int).Add(balance, db.GetBalance(celoUnreleasedTreasuryAddress)) ++ db.SetBalance(celoUnreleasedTreasuryAddress, balance, tracing.BalanceChangeUnspecified) ++ ++ log.Info("Set up CeloUnreleasedTreasury balance", "celoUnreleasedTreasuryAddress", celoUnreleasedTreasuryAddress, "balance", balance, "total_supply", supplyU256, "ceiling", ceiling) ++ return nil ++} ++ ++// writeGenesis writes the genesis json to --outfile.genesis and stores the genesis state spec (alloc) in the database. ++// Note that this is different than the cel2Block / migration block. Rather, this is the migrated genesis block of Celo from before the L2 transition. ++// Nodes will need the genesis json file in order to snap sync on the L2 chain. ++func writeGenesis(config *params.ChainConfig, db ethdb.Database, genesisOutPath string, genesisHash common.Hash) error { ++ // Derive the genesis object using hardcoded legacy alloc and the transformed extra data stored in the new db. ++ legacyGenesisAlloc, err := GetCeloL1GenesisAlloc(config) ++ if err != nil { ++ return err ++ } ++ genesisHeader := rawdb.ReadHeader(db, genesisHash, 0) ++ genesis, err := BuildGenesis(config, legacyGenesisAlloc, genesisHeader.Extra, genesisHeader.Time) ++ if err != nil { ++ return err ++ } ++ ++ // Convert genesis to JSON byte slice ++ genesisBytes, err := json.Marshal(genesis) ++ if err != nil { ++ return fmt.Errorf("failed to marshal genesis to JSON: %w", err) ++ } ++ ++ // Unmarshal JSON byte slice to map ++ var genesisMap map[string]interface{} ++ if err := json.Unmarshal(genesisBytes, &genesisMap); err != nil { ++ return fmt.Errorf("failed to unmarshal genesis JSON to map: %w", err) ++ } ++ ++ // Delete fields that are not in Celo Legacy Genesis, otherwise genesis hashes won't match when syncing ++ delete(genesisMap, "difficulty") ++ delete(genesisMap, "gasLimit") ++ delete(genesisMap, "excessBlobGas") ++ delete(genesisMap, "blobGasUsed") ++ delete(genesisMap, "baseFeePerGas") ++ delete(genesisMap, "mixHash") ++ delete(genesisMap, "nonce") ++ ++ // Write the modified JSON to the file ++ if err := jsonutil.WriteJSON(genesisMap, ioutil.ToStdOutOrFileOrNoop(genesisOutPath, OutFilePerm)); err != nil { ++ return fmt.Errorf("failed to write genesis JSON to file: %w", err) ++ } ++ log.Info("Wrote genesis file for syncing new nodes", "path", genesisOutPath) ++ ++ // Legacy Celo did not store the genesis state spec (alloc) in the database. ++ // Write it now for forward compatibility. ++ rawdb.WriteGenesisStateSpec(db, genesisHash, legacyGenesisAlloc) ++ log.Info("Wrote genesis state spec (alloc) to database") ++ ++ return nil ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+147
+
-0
+ +
+ +
+
+
diff --git OP/op-chain-ops/cmd/celo-migrate/state_test.go CELO/op-chain-ops/cmd/celo-migrate/state_test.go +new file mode 100644 +index 0000000000000000000000000000000000000000..dbe6ce90ef4e51f31ade77933a6656b94dcad98a +--- /dev/null ++++ CELO/op-chain-ops/cmd/celo-migrate/state_test.go +@@ -0,0 +1,147 @@ ++package main ++ ++import ( ++ "bytes" ++ "math/big" ++ "testing" ++ ++ "github.com/ethereum/go-ethereum/common" ++ "github.com/ethereum/go-ethereum/core/rawdb" ++ "github.com/ethereum/go-ethereum/core/state" ++ "github.com/ethereum/go-ethereum/core/tracing" ++ "github.com/ethereum/go-ethereum/core/types" ++ "github.com/holiman/uint256" ++ "github.com/stretchr/testify/assert" ++) ++ ++var ( ++ contractCode = []byte{0x01, 0x02} ++ defaultBalance int64 = 123 ++ address = common.HexToAddress("a") ++) ++ ++func TestApplyAllocsToState(t *testing.T) { ++ tests := []struct { ++ name string ++ existingAccount *types.Account ++ newAccount types.Account ++ allowlist map[common.Address]bool ++ wantErr bool ++ }{ ++ { ++ name: "Write to empty account", ++ newAccount: types.Account{ ++ Code: contractCode, ++ Nonce: 1, ++ }, ++ wantErr: false, ++ }, ++ { ++ name: "Copy account with non-zero balance fails", ++ existingAccount: &types.Account{ ++ Balance: big.NewInt(defaultBalance), ++ }, ++ newAccount: types.Account{ ++ Balance: big.NewInt(1), ++ }, ++ wantErr: true, ++ }, ++ { ++ name: "Write to account with only balance should overwrite and keep balance", ++ existingAccount: &types.Account{ ++ Balance: big.NewInt(defaultBalance), ++ }, ++ newAccount: types.Account{ ++ Code: contractCode, ++ Nonce: 5, ++ }, ++ wantErr: false, ++ }, ++ { ++ name: "Write to account with existing nonce fails", ++ existingAccount: &types.Account{ ++ Balance: big.NewInt(defaultBalance), ++ Nonce: 5, ++ }, ++ newAccount: types.Account{ ++ Code: contractCode, ++ Nonce: 5, ++ }, ++ wantErr: true, ++ }, ++ { ++ name: "Write to account with contract code fails", ++ existingAccount: &types.Account{ ++ Balance: big.NewInt(defaultBalance), ++ Code: bytes.Repeat([]byte{0x01}, 10), ++ }, ++ newAccount: types.Account{ ++ Code: contractCode, ++ Nonce: 5, ++ }, ++ wantErr: true, ++ }, ++ { ++ name: "Write account with allowlist overwrite, keeps nonce", ++ existingAccount: &types.Account{ ++ Balance: big.NewInt(defaultBalance), ++ Nonce: 4, ++ Code: bytes.Repeat([]byte{0x01}, 10), ++ }, ++ newAccount: types.Account{ ++ Code: contractCode, ++ Nonce: 5, ++ }, ++ allowlist: map[common.Address]bool{address: true}, ++ wantErr: false, ++ }, ++ } ++ for _, tt := range tests { ++ t.Run(tt.name, func(t *testing.T) { ++ db := rawdb.NewMemoryDatabase() ++ tdb := state.NewDatabase(db) ++ sdb, _ := state.New(types.EmptyRootHash, tdb, nil) ++ ++ if tt.existingAccount != nil { ++ sdb.CreateAccount(address) ++ ++ if tt.existingAccount.Balance != nil { ++ sdb.SetBalance(address, uint256.MustFromBig(tt.existingAccount.Balance), tracing.BalanceChangeUnspecified) ++ } ++ if tt.existingAccount.Nonce != 0 { ++ sdb.SetNonce(address, tt.existingAccount.Nonce) ++ } ++ if tt.existingAccount.Code != nil { ++ sdb.SetCode(address, tt.existingAccount.Code) ++ } ++ } ++ ++ if err := applyAllocsToState(sdb, types.GenesisAlloc{address: tt.newAccount}, tt.allowlist); (err != nil) != tt.wantErr { ++ t.Errorf("applyAllocsToState() error = %v, wantErr %v", err, tt.wantErr) ++ } ++ ++ // Don't check account state if an error was thrown ++ if tt.wantErr { ++ return ++ } ++ ++ if !sdb.Exist(address) { ++ t.Errorf("account does not exists as expected: %v", address.Hex()) ++ } ++ ++ assert.Equal(t, tt.newAccount.Code, sdb.GetCode(address)) ++ ++ if tt.existingAccount != nil && tt.existingAccount.Nonce != 0 { ++ assert.Equal(t, tt.existingAccount.Nonce, sdb.GetNonce(address)) ++ } else { ++ assert.Equal(t, tt.newAccount.Nonce, sdb.GetNonce(address)) ++ } ++ ++ if tt.existingAccount != nil { ++ assert.True(t, big.NewInt(defaultBalance).Cmp(sdb.GetBalance(address).ToBig()) == 0) ++ } else { ++ assert.True(t, big.NewInt(0).Cmp(sdb.GetBalance(address).ToBig()) == 0) ++ } ++ }) ++ } ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+109
+
-0
+ +
+ +
+
+
diff --git OP/op-chain-ops/cmd/celo-migrate/transform.go CELO/op-chain-ops/cmd/celo-migrate/transform.go +new file mode 100644 +index 0000000000000000000000000000000000000000..5a80e8a51566f47408976d16f94885e4937108d3 +--- /dev/null ++++ CELO/op-chain-ops/cmd/celo-migrate/transform.go +@@ -0,0 +1,109 @@ ++package main ++ ++import ( ++ "bytes" ++ "errors" ++ "fmt" ++ "math/big" ++ ++ "github.com/ethereum/go-ethereum/common" ++ "github.com/ethereum/go-ethereum/core/types" ++ "github.com/ethereum/go-ethereum/crypto" ++ "github.com/ethereum/go-ethereum/rlp" ++) ++ ++var ( ++ IstanbulExtraVanity = 32 // Fixed number of extra-data bytes reserved for validator vanity ++) ++ ++// IstanbulAggregatedSeal is the aggregated seal for Istanbul blocks ++type IstanbulAggregatedSeal struct { ++ // Bitmap is a bitmap having an active bit for each validator that signed this block ++ Bitmap *big.Int ++ // Signature is an aggregated BLS signature resulting from signatures by each validator that signed this block ++ Signature []byte ++ // Round is the round in which the signature was created. ++ Round *big.Int ++} ++ ++// IstanbulExtra is the extra-data for Istanbul blocks ++type IstanbulExtra struct { ++ // AddedValidators are the validators that have been added in the block ++ AddedValidators []common.Address ++ // AddedValidatorsPublicKeys are the BLS public keys for the validators added in the block ++ AddedValidatorsPublicKeys [][96]byte ++ // RemovedValidators is a bitmap having an active bit for each removed validator in the block ++ RemovedValidators *big.Int ++ // Seal is an ECDSA signature by the proposer ++ Seal []byte ++ // AggregatedSeal contains the aggregated BLS signature created via IBFT consensus. ++ AggregatedSeal IstanbulAggregatedSeal ++ // ParentAggregatedSeal contains and aggregated BLS signature for the previous block. ++ ParentAggregatedSeal IstanbulAggregatedSeal ++} ++ ++// transformHeader removes the aggregated seal from the header ++func transformHeader(header []byte) ([]byte, error) { ++ newHeader := new(types.Header) ++ err := rlp.DecodeBytes(header, &newHeader) ++ if err != nil { ++ return nil, err ++ } ++ ++ if len(newHeader.Extra) < IstanbulExtraVanity { ++ return nil, errors.New("invalid istanbul header extra-data") ++ } ++ ++ istanbulExtra := IstanbulExtra{} ++ err = rlp.DecodeBytes(newHeader.Extra[IstanbulExtraVanity:], &istanbulExtra) ++ if err != nil { ++ return nil, err ++ } ++ ++ istanbulExtra.AggregatedSeal = IstanbulAggregatedSeal{} ++ ++ payload, err := rlp.EncodeToBytes(&istanbulExtra) ++ if err != nil { ++ return nil, err ++ } ++ ++ newHeader.Extra = append(newHeader.Extra[:IstanbulExtraVanity], payload...) ++ ++ return rlp.EncodeToBytes(newHeader) ++} ++ ++func hasSameHash(newHeader, oldHash []byte) (bool, common.Hash) { ++ newHash := crypto.Keccak256Hash(newHeader) ++ return bytes.Equal(oldHash, newHash.Bytes()), newHash ++} ++ ++// transformBlockBody migrates the block body from the old format to the new format (works with []byte input output) ++func transformBlockBody(oldBodyData []byte) ([]byte, error) { ++ // decode body into celo-blockchain Body structure ++ // remove epochSnarkData and randomness data ++ var celoBody struct { ++ Transactions types.Transactions ++ Randomness rlp.RawValue ++ EpochSnarkData rlp.RawValue ++ } ++ if err := rlp.DecodeBytes(oldBodyData, &celoBody); err != nil { ++ // body may have already been transformed in a previous migration ++ body := types.Body{} ++ if err := rlp.DecodeBytes(oldBodyData, &body); err == nil { ++ return oldBodyData, nil ++ } ++ return nil, fmt.Errorf("failed to RLP decode body: %w", err) ++ } ++ ++ // transform into op-geth types.Body structure ++ newBody := types.Body{ ++ Transactions: celoBody.Transactions, ++ Uncles: []*types.Header{}, ++ } ++ newBodyData, err := rlp.EncodeToBytes(newBody) ++ if err != nil { ++ return nil, fmt.Errorf("failed to RLP encode body: %w", err) ++ } ++ ++ return newBodyData, nil ++}
+
diff --git OP/op-chain-ops/cmd/check-derivation/main.go CELO/op-chain-ops/cmd/check-derivation/main.go +index 499b128f8767fe560d92ee66f3ed770c373d7bf4..5f846450138445c62ccb4b5194d634382fe24d2b 100644 +--- OP/op-chain-ops/cmd/check-derivation/main.go ++++ CELO/op-chain-ops/cmd/check-derivation/main.go +@@ -225,7 +225,7 @@ data := testutils.RandomData(rng, 10) + var txData types.TxData + switch txType { + case types.LegacyTxType: +- gasLimit, err := core.IntrinsicGas(data, nil, false, true, true, false) ++ gasLimit, err := core.IntrinsicGas(data, nil, false, true, true, false, nil, nil) + if err != nil { + return nil, fmt.Errorf("failed to get intrinsicGas: %w", err) + } +@@ -242,7 +242,7 @@ accessList := types.AccessList{types.AccessTuple{ + Address: randomAddress, + StorageKeys: []common.Hash{common.HexToHash("0x1234")}, + }} +- gasLimit, err := core.IntrinsicGas(data, accessList, false, true, true, false) ++ gasLimit, err := core.IntrinsicGas(data, accessList, false, true, true, false, nil, nil) + if err != nil { + return nil, fmt.Errorf("failed to get intrinsicGas: %w", err) + } +@@ -257,7 +257,7 @@ AccessList: accessList, + Data: data, + } + case types.DynamicFeeTxType: +- gasLimit, err := core.IntrinsicGas(data, nil, false, true, true, false) ++ gasLimit, err := core.IntrinsicGas(data, nil, false, true, true, false, nil, nil) + if err != nil { + return nil, fmt.Errorf("failed to get intrinsicGas: %w", err) + }
+
+ + +
@@ -8427,122 +49885,85 @@
-
+92
+
+57
-0
-
diff --git OP/packages/contracts-bedrock/snapshots/abi/UsingRegistry.json CELO/packages/contracts-bedrock/snapshots/abi/UsingRegistry.json +
diff --git OP/op-chain-ops/cmd/op-deployer/main.go CELO/op-chain-ops/cmd/op-deployer/main.go new file mode 100644 -index 0000000000000000000000000000000000000000..dc8fa7e0f21ca37add36efa01627337c9521293c +index 0000000000000000000000000000000000000000..023d8adca39d11678faeb795db0e15a8aab28afc --- /dev/null -+++ CELO/packages/contracts-bedrock/snapshots/abi/UsingRegistry.json -@@ -0,0 +1,93 @@ -+[ -+ { -+ "inputs": [], -+ "name": "owner", -+ "outputs": [ -+ { -+ "internalType": "address", -+ "name": "", -+ "type": "address" -+ } -+ ], -+ "stateMutability": "view", -+ "type": "function" -+ }, -+ { -+ "inputs": [], -+ "name": "registry", -+ "outputs": [ -+ { -+ "internalType": "contract ICeloRegistry", -+ "name": "", -+ "type": "address" -+ } -+ ], -+ "stateMutability": "view", -+ "type": "function" -+ }, -+ { -+ "inputs": [], -+ "name": "renounceOwnership", -+ "outputs": [], -+ "stateMutability": "nonpayable", -+ "type": "function" -+ }, -+ { -+ "inputs": [ -+ { -+ "internalType": "address", -+ "name": "registryAddress", -+ "type": "address" -+ } -+ ], -+ "name": "setRegistry", -+ "outputs": [], -+ "stateMutability": "nonpayable", -+ "type": "function" -+ }, -+ { -+ "inputs": [ -+ { -+ "internalType": "address", -+ "name": "newOwner", -+ "type": "address" -+ } -+ ], -+ "name": "transferOwnership", -+ "outputs": [], -+ "stateMutability": "nonpayable", -+ "type": "function" -+ }, -+ { -+ "anonymous": false, -+ "inputs": [ -+ { -+ "indexed": true, -+ "internalType": "address", -+ "name": "previousOwner", -+ "type": "address" -+ }, -+ { -+ "indexed": true, -+ "internalType": "address", -+ "name": "newOwner", -+ "type": "address" -+ } -+ ], -+ "name": "OwnershipTransferred", -+ "type": "event" -+ }, -+ { -+ "anonymous": false, -+ "inputs": [ -+ { -+ "indexed": true, -+ "internalType": "address", -+ "name": "registryAddress", -+ "type": "address" -+ } -+ ], -+ "name": "RegistrySet", -+ "type": "event" -+ } -+] -\ No newline at end of file
++++ CELO/op-chain-ops/cmd/op-deployer/main.go +@@ -0,0 +1,57 @@ ++package main ++ ++import ( ++ "fmt" ++ "os" ++ ++ "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/version" ++ opservice "github.com/ethereum-optimism/optimism/op-service" ++ ++ "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/inspect" ++ ++ "github.com/ethereum-optimism/optimism/op-chain-ops/deployer" ++ "github.com/ethereum-optimism/optimism/op-service/cliapp" ++ "github.com/urfave/cli/v2" ++) ++ ++var ( ++ GitCommit = "" ++ GitDate = "" ++) ++ ++// VersionWithMeta holds the textual version string including the metadata. ++var VersionWithMeta = opservice.FormatVersion(version.Version, GitCommit, GitDate, version.Meta) ++ ++func main() { ++ app := cli.NewApp() ++ app.Version = VersionWithMeta ++ app.Name = "op-deployer" ++ app.Usage = "Tool to configure and deploy OP Chains." ++ app.Flags = cliapp.ProtectFlags(deployer.GlobalFlags) ++ app.Commands = []*cli.Command{ ++ { ++ Name: "init", ++ Usage: "initializes a chain intent and state file", ++ Flags: cliapp.ProtectFlags(deployer.InitFlags), ++ Action: deployer.InitCLI(), ++ }, ++ { ++ Name: "apply", ++ Usage: "applies a chain intent to the chain", ++ Flags: cliapp.ProtectFlags(deployer.ApplyFlags), ++ Action: deployer.ApplyCLI(), ++ }, ++ { ++ Name: "inspect", ++ Usage: "inspects the state of a deployment", ++ Subcommands: inspect.Commands, ++ }, ++ } ++ app.Writer = os.Stdout ++ app.ErrWriter = os.Stderr ++ err := app.Run(os.Args) ++ if err != nil { ++ _, _ = fmt.Fprintf(os.Stderr, "Application failed: %v\n", err) ++ os.Exit(1) ++ } ++}
-
diff --git OP/packages/contracts-bedrock/snapshots/storageLayout/CalledByVm.json CELO/packages/contracts-bedrock/snapshots/storageLayout/CalledByVm.json +
diff --git OP/op-chain-ops/deployer/apply.go CELO/op-chain-ops/deployer/apply.go new file mode 100644 -index 0000000000000000000000000000000000000000..0637a088a01e8ddab3bf3fa98dbe804cbde1a0dc +index 0000000000000000000000000000000000000000..ca34d4266df796ea2686d3ccef390a637b5f4a9e --- /dev/null -+++ CELO/packages/contracts-bedrock/snapshots/storageLayout/CalledByVm.json -@@ -0,0 +1 @@ -+[] -\ No newline at end of file
++++ CELO/op-chain-ops/deployer/apply.go +@@ -0,0 +1,189 @@ ++package deployer ++ ++import ( ++ "context" ++ "crypto/ecdsa" ++ "fmt" ++ "strings" ++ ++ "github.com/ethereum-optimism/optimism/op-chain-ops/foundry" ++ ++ "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/state" ++ ++ "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/pipeline" ++ opcrypto "github.com/ethereum-optimism/optimism/op-service/crypto" ++ "github.com/ethereum-optimism/optimism/op-service/ctxinterrupt" ++ oplog "github.com/ethereum-optimism/optimism/op-service/log" ++ "github.com/ethereum/go-ethereum/crypto" ++ "github.com/ethereum/go-ethereum/ethclient" ++ "github.com/ethereum/go-ethereum/log" ++ "github.com/urfave/cli/v2" ++) ++ ++type ApplyConfig struct { ++ L1RPCUrl string ++ Workdir string ++ PrivateKey string ++ Logger log.Logger ++ ++ privateKeyECDSA *ecdsa.PrivateKey ++} ++ ++func (a *ApplyConfig) Check() error { ++ if a.L1RPCUrl == "" { ++ return fmt.Errorf("l1RPCUrl must be specified") ++ } ++ ++ if a.Workdir == "" { ++ return fmt.Errorf("workdir must be specified") ++ } ++ ++ if a.PrivateKey == "" { ++ return fmt.Errorf("private key must be specified") ++ } ++ ++ privECDSA, err := crypto.HexToECDSA(strings.TrimPrefix(a.PrivateKey, "0x")) ++ if err != nil { ++ return fmt.Errorf("failed to parse private key: %w", err) ++ } ++ a.privateKeyECDSA = privECDSA ++ ++ if a.Logger == nil { ++ return fmt.Errorf("logger must be specified") ++ } ++ ++ return nil ++} ++ ++func ApplyCLI() func(cliCtx *cli.Context) error { ++ return func(cliCtx *cli.Context) error { ++ logCfg := oplog.ReadCLIConfig(cliCtx) ++ l := oplog.NewLogger(oplog.AppOut(cliCtx), logCfg) ++ oplog.SetGlobalLogHandler(l.Handler()) ++ ++ l1RPCUrl := cliCtx.String(L1RPCURLFlagName) ++ workdir := cliCtx.String(WorkdirFlagName) ++ privateKey := cliCtx.String(PrivateKeyFlagName) ++ ++ ctx := ctxinterrupt.WithCancelOnInterrupt(cliCtx.Context) ++ ++ return Apply(ctx, ApplyConfig{ ++ L1RPCUrl: l1RPCUrl, ++ Workdir: workdir, ++ PrivateKey: privateKey, ++ Logger: l, ++ }) ++ } ++} ++ ++func Apply(ctx context.Context, cfg ApplyConfig) error { ++ if err := cfg.Check(); err != nil { ++ return fmt.Errorf("invalid config for apply: %w", err) ++ } ++ ++ l1Client, err := ethclient.Dial(cfg.L1RPCUrl) ++ if err != nil { ++ return fmt.Errorf("failed to connect to L1 RPC: %w", err) ++ } ++ ++ chainID, err := l1Client.ChainID(ctx) ++ if err != nil { ++ return fmt.Errorf("failed to get chain ID: %w", err) ++ } ++ ++ signer := opcrypto.SignerFnFromBind(opcrypto.PrivateKeySignerFn(cfg.privateKeyECDSA, chainID)) ++ deployer := crypto.PubkeyToAddress(cfg.privateKeyECDSA.PublicKey) ++ ++ env := &pipeline.Env{ ++ Workdir: cfg.Workdir, ++ L1Client: l1Client, ++ Logger: cfg.Logger, ++ Signer: signer, ++ Deployer: deployer, ++ } ++ ++ intent, err := env.ReadIntent() ++ if err != nil { ++ return err ++ } ++ ++ if err := intent.Check(); err != nil { ++ return fmt.Errorf("invalid intent: %w", err) ++ } ++ ++ st, err := env.ReadState() ++ if err != nil { ++ return err ++ } ++ ++ if err := ApplyPipeline(ctx, env, intent, st); err != nil { ++ return err ++ } ++ ++ st.AppliedIntent = intent ++ if err := env.WriteState(st); err != nil { ++ return err ++ } ++ ++ return nil ++} ++ ++type pipelineStage struct { ++ name string ++ apply pipeline.Stage ++} ++ ++func ApplyPipeline( ++ ctx context.Context, ++ env *pipeline.Env, ++ intent *state.Intent, ++ st *state.State, ++) error { ++ progressor := func(curr, total int64) { ++ env.Logger.Info("artifacts download progress", "current", curr, "total", total) ++ } ++ ++ artifactsFS, cleanup, err := pipeline.DownloadArtifacts(ctx, intent.ContractArtifactsURL, progressor) ++ if err != nil { ++ return fmt.Errorf("failed to download artifacts: %w", err) ++ } ++ defer func() { ++ if err := cleanup(); err != nil { ++ env.Logger.Warn("failed to clean up artifacts", "err", err) ++ } ++ }() ++ ++ pline := []pipelineStage{ ++ {"init", pipeline.Init}, ++ {"deploy-superchain", pipeline.DeploySuperchain}, ++ {"deploy-implementations", pipeline.DeployImplementations}, ++ } ++ ++ for _, chain := range intent.Chains { ++ chainID := chain.ID ++ pline = append(pline, pipelineStage{ ++ fmt.Sprintf("deploy-opchain-%s", chainID.Hex()), ++ func(ctx context.Context, env *pipeline.Env, artifactsFS foundry.StatDirFs, intent *state.Intent, st *state.State) error { ++ return pipeline.DeployOPChain(ctx, env, artifactsFS, intent, st, chainID) ++ }, ++ }, pipelineStage{ ++ fmt.Sprintf("generate-l2-genesis-%s", chainID.Hex()), ++ func(ctx context.Context, env *pipeline.Env, artifactsFS foundry.StatDirFs, intent *state.Intent, st *state.State) error { ++ return pipeline.GenerateL2Genesis(ctx, env, artifactsFS, intent, st, chainID) ++ }, ++ }) ++ } ++ ++ for _, stage := range pline { ++ if err := stage.apply(ctx, env, artifactsFS, intent, st); err != nil { ++ return fmt.Errorf("error in pipeline stage apply: %w", err) ++ } ++ } ++ ++ st.AppliedIntent = intent ++ if err := env.WriteState(st); err != nil { ++ return fmt.Errorf("failed to write state: %w", err) ++ } ++ ++ return nil ++}
@@ -8615,52 +50223,49 @@
-
+22
+
+21
-0
-
diff --git OP/packages/contracts-bedrock/snapshots/storageLayout/CeloRegistry.json CELO/packages/contracts-bedrock/snapshots/storageLayout/CeloRegistry.json +
diff --git OP/op-chain-ops/deployer/broadcaster/broadcaster.go CELO/op-chain-ops/deployer/broadcaster/broadcaster.go new file mode 100644 -index 0000000000000000000000000000000000000000..17b0df2bd7f9e8254e7ac4730d34917b70b3063b +index 0000000000000000000000000000000000000000..641d1f73dfb5d927f2dbc784ee318e003e7c9f49 --- /dev/null -+++ CELO/packages/contracts-bedrock/snapshots/storageLayout/CeloRegistry.json -@@ -0,0 +1,23 @@ -+[ -+ { -+ "bytes": "20", -+ "label": "_owner", -+ "offset": 0, -+ "slot": "0", -+ "type": "address" -+ }, -+ { -+ "bytes": "1", -+ "label": "initialized", -+ "offset": 20, -+ "slot": "0", -+ "type": "bool" -+ }, -+ { -+ "bytes": "32", -+ "label": "registry", -+ "offset": 0, -+ "slot": "1", -+ "type": "mapping(bytes32 => address)" -+ } -+] -\ No newline at end of file
++++ CELO/op-chain-ops/deployer/broadcaster/broadcaster.go +@@ -0,0 +1,21 @@ ++package broadcaster ++ ++import ( ++ "context" ++ ++ "github.com/ethereum-optimism/optimism/op-chain-ops/script" ++ "github.com/ethereum/go-ethereum/common" ++ "github.com/ethereum/go-ethereum/core/types" ++) ++ ++type Broadcaster interface { ++ Broadcast(ctx context.Context) ([]BroadcastResult, error) ++ Hook(bcast script.Broadcast) ++} ++ ++type BroadcastResult struct { ++ Broadcast script.Broadcast `json:"broadcast"` ++ TxHash common.Hash `json:"txHash"` ++ Receipt *types.Receipt `json:"receipt"` ++ Err error `json:"-"` ++}
@@ -8675,7 +50280,7 @@
@@ -8685,94 +50290,318 @@
-
+64
+
+20
-0
-
diff --git OP/packages/contracts-bedrock/snapshots/storageLayout/CeloTokenL1.json CELO/packages/contracts-bedrock/snapshots/storageLayout/CeloTokenL1.json +
diff --git OP/op-chain-ops/deployer/broadcaster/discard.go CELO/op-chain-ops/deployer/broadcaster/discard.go new file mode 100644 -index 0000000000000000000000000000000000000000..e3c218589ca31c3e34d65496c25c72a83d999397 +index 0000000000000000000000000000000000000000..42f5b1b0a9642d686c2007dcec6ef7b5688a3eb5 --- /dev/null -+++ CELO/packages/contracts-bedrock/snapshots/storageLayout/CeloTokenL1.json -@@ -0,0 +1,65 @@ -+[ -+ { -+ "bytes": "1", -+ "label": "_initialized", -+ "offset": 0, -+ "slot": "0", -+ "type": "uint8" -+ }, -+ { -+ "bytes": "1", -+ "label": "_initializing", -+ "offset": 1, -+ "slot": "0", -+ "type": "bool" -+ }, -+ { -+ "bytes": "1600", -+ "label": "__gap", -+ "offset": 0, -+ "slot": "1", -+ "type": "uint256[50]" -+ }, -+ { -+ "bytes": "32", -+ "label": "_balances", -+ "offset": 0, -+ "slot": "51", -+ "type": "mapping(address => uint256)" -+ }, -+ { -+ "bytes": "32", -+ "label": "_allowances", -+ "offset": 0, -+ "slot": "52", -+ "type": "mapping(address => mapping(address => uint256))" -+ }, -+ { -+ "bytes": "32", -+ "label": "_totalSupply", -+ "offset": 0, -+ "slot": "53", -+ "type": "uint256" -+ }, -+ { -+ "bytes": "32", -+ "label": "_name", -+ "offset": 0, -+ "slot": "54", -+ "type": "string" -+ }, -+ { -+ "bytes": "32", -+ "label": "_symbol", -+ "offset": 0, -+ "slot": "55", -+ "type": "string" -+ }, -+ { -+ "bytes": "1440", -+ "label": "__gap", -+ "offset": 0, -+ "slot": "56", -+ "type": "uint256[45]" -+ } -+] -\ No newline at end of file
++++ CELO/op-chain-ops/deployer/broadcaster/discard.go +@@ -0,0 +1,20 @@ ++package broadcaster ++ ++import ( ++ "context" ++ ++ "github.com/ethereum-optimism/optimism/op-chain-ops/script" ++) ++ ++type discardBroadcaster struct { ++} ++ ++func DiscardBroadcaster() Broadcaster { ++ return &discardBroadcaster{} ++} ++ ++func (d *discardBroadcaster) Broadcast(ctx context.Context) ([]BroadcastResult, error) { ++ return nil, nil ++} ++ ++func (d *discardBroadcaster) Hook(bcast script.Broadcast) {}
+ + + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+224
+
-0
+ +
+ +
+
+
diff --git OP/op-chain-ops/deployer/broadcaster/keyed.go CELO/op-chain-ops/deployer/broadcaster/keyed.go +new file mode 100644 +index 0000000000000000000000000000000000000000..dda6221bb30532269d81ef4d89cade311ba1f0f2 +--- /dev/null ++++ CELO/op-chain-ops/deployer/broadcaster/keyed.go +@@ -0,0 +1,224 @@ ++package broadcaster ++ ++import ( ++ "context" ++ "fmt" ++ "math/big" ++ "time" ++ ++ "github.com/ethereum-optimism/optimism/op-chain-ops/script" ++ opcrypto "github.com/ethereum-optimism/optimism/op-service/crypto" ++ "github.com/ethereum-optimism/optimism/op-service/eth" ++ "github.com/ethereum-optimism/optimism/op-service/txmgr" ++ "github.com/ethereum-optimism/optimism/op-service/txmgr/metrics" ++ "github.com/ethereum/go-ethereum/common" ++ "github.com/ethereum/go-ethereum/core" ++ "github.com/ethereum/go-ethereum/ethclient" ++ "github.com/ethereum/go-ethereum/log" ++ "github.com/hashicorp/go-multierror" ++ "github.com/holiman/uint256" ++) ++ ++const ( ++ GasPadFactor = 2.0 ++) ++ ++type KeyedBroadcaster struct { ++ lgr log.Logger ++ mgr txmgr.TxManager ++ bcasts []script.Broadcast ++ client *ethclient.Client ++} ++ ++type KeyedBroadcasterOpts struct { ++ Logger log.Logger ++ ChainID *big.Int ++ Client *ethclient.Client ++ Signer opcrypto.SignerFn ++ From common.Address ++ TXManagerLogger log.Logger ++} ++ ++func NewKeyedBroadcaster(cfg KeyedBroadcasterOpts) (*KeyedBroadcaster, error) { ++ mgrCfg := &txmgr.Config{ ++ Backend: cfg.Client, ++ ChainID: cfg.ChainID, ++ TxSendTimeout: 5 * time.Minute, ++ TxNotInMempoolTimeout: time.Minute, ++ NetworkTimeout: 10 * time.Second, ++ ReceiptQueryInterval: time.Second, ++ NumConfirmations: 1, ++ SafeAbortNonceTooLowCount: 3, ++ Signer: cfg.Signer, ++ From: cfg.From, ++ } ++ ++ minTipCap, err := eth.GweiToWei(1.0) ++ if err != nil { ++ panic(err) ++ } ++ minBaseFee, err := eth.GweiToWei(1.0) ++ if err != nil { ++ panic(err) ++ } ++ ++ mgrCfg.ResubmissionTimeout.Store(int64(48 * time.Second)) ++ mgrCfg.FeeLimitMultiplier.Store(5) ++ mgrCfg.FeeLimitThreshold.Store(big.NewInt(100)) ++ mgrCfg.MinTipCap.Store(minTipCap) ++ mgrCfg.MinTipCap.Store(minBaseFee) ++ ++ txmLogger := log.NewLogger(log.DiscardHandler()) ++ if cfg.TXManagerLogger != nil { ++ txmLogger = cfg.TXManagerLogger ++ } ++ ++ mgr, err := txmgr.NewSimpleTxManagerFromConfig( ++ "transactor", ++ txmLogger, ++ &metrics.NoopTxMetrics{}, ++ mgrCfg, ++ ) ++ ++ if err != nil { ++ return nil, fmt.Errorf("failed to create tx manager: %w", err) ++ } ++ ++ return &KeyedBroadcaster{ ++ lgr: cfg.Logger, ++ mgr: mgr, ++ client: cfg.Client, ++ }, nil ++} ++ ++func (t *KeyedBroadcaster) Hook(bcast script.Broadcast) { ++ t.bcasts = append(t.bcasts, bcast) ++} ++ ++func (t *KeyedBroadcaster) Broadcast(ctx context.Context) ([]BroadcastResult, error) { ++ results := make([]BroadcastResult, len(t.bcasts)) ++ futures := make([]<-chan txmgr.SendResponse, len(t.bcasts)) ++ ids := make([]common.Hash, len(t.bcasts)) ++ ++ latestBlock, err := t.client.BlockByNumber(ctx, nil) ++ if err != nil { ++ return nil, fmt.Errorf("failed to get latest block: %w", err) ++ } ++ ++ for i, bcast := range t.bcasts { ++ futures[i], ids[i] = t.broadcast(ctx, bcast, latestBlock.GasLimit()) ++ t.lgr.Info( ++ "transaction broadcasted", ++ "id", ids[i], ++ "nonce", bcast.Nonce, ++ ) ++ } ++ ++ var txErr *multierror.Error ++ var completed int ++ for i, fut := range futures { ++ bcastRes := <-fut ++ completed++ ++ outRes := BroadcastResult{ ++ Broadcast: t.bcasts[i], ++ } ++ ++ if bcastRes.Err == nil { ++ outRes.Receipt = bcastRes.Receipt ++ outRes.TxHash = bcastRes.Receipt.TxHash ++ ++ if bcastRes.Receipt.Status == 0 { ++ failErr := fmt.Errorf("transaction failed: %s", outRes.Receipt.TxHash.String()) ++ txErr = multierror.Append(txErr, failErr) ++ outRes.Err = failErr ++ t.lgr.Error( ++ "transaction failed on chain", ++ "id", ids[i], ++ "completed", completed, ++ "total", len(t.bcasts), ++ "hash", outRes.Receipt.TxHash.String(), ++ "nonce", outRes.Broadcast.Nonce, ++ ) ++ } else { ++ t.lgr.Info( ++ "transaction confirmed", ++ "id", ids[i], ++ "completed", completed, ++ "total", len(t.bcasts), ++ "hash", outRes.Receipt.TxHash.String(), ++ "nonce", outRes.Broadcast.Nonce, ++ "creation", outRes.Receipt.ContractAddress, ++ ) ++ } ++ } else { ++ txErr = multierror.Append(txErr, bcastRes.Err) ++ outRes.Err = bcastRes.Err ++ t.lgr.Error( ++ "transaction failed", ++ "id", ids[i], ++ "completed", completed, ++ "total", len(t.bcasts), ++ "err", bcastRes.Err, ++ ) ++ } ++ ++ results[i] = outRes ++ } ++ return results, txErr.ErrorOrNil() ++} ++ ++func (t *KeyedBroadcaster) broadcast(ctx context.Context, bcast script.Broadcast, blockGasLimit uint64) (<-chan txmgr.SendResponse, common.Hash) { ++ ch := make(chan txmgr.SendResponse, 1) ++ ++ id := bcast.ID() ++ value := ((*uint256.Int)(bcast.Value)).ToBig() ++ var candidate txmgr.TxCandidate ++ switch bcast.Type { ++ case script.BroadcastCall: ++ to := &bcast.To ++ candidate = txmgr.TxCandidate{ ++ TxData: bcast.Input, ++ To: to, ++ Value: value, ++ GasLimit: padGasLimit(bcast.Input, bcast.GasUsed, false, blockGasLimit), ++ } ++ case script.BroadcastCreate: ++ candidate = txmgr.TxCandidate{ ++ TxData: bcast.Input, ++ To: nil, ++ GasLimit: padGasLimit(bcast.Input, bcast.GasUsed, true, blockGasLimit), ++ } ++ case script.BroadcastCreate2: ++ txData := make([]byte, len(bcast.Salt)+len(bcast.Input)) ++ copy(txData, bcast.Salt[:]) ++ copy(txData[len(bcast.Salt):], bcast.Input) ++ ++ candidate = txmgr.TxCandidate{ ++ TxData: txData, ++ To: &script.DeterministicDeployerAddress, ++ Value: value, ++ GasLimit: padGasLimit(bcast.Input, bcast.GasUsed, true, blockGasLimit), ++ } ++ } ++ ++ t.mgr.SendAsync(ctx, candidate, ch) ++ return ch, id ++} ++ ++// padGasLimit calculates the gas limit for a transaction based on the intrinsic gas and the gas used by ++// the underlying call. Values are multiplied by a pad factor to account for any discrepancies. The output ++// is clamped to the block gas limit since Geth will reject transactions that exceed it before letting them ++// into the mempool. ++func padGasLimit(data []byte, gasUsed uint64, creation bool, blockGasLimit uint64) uint64 { ++ intrinsicGas, err := core.IntrinsicGas(data, nil, creation, true, true, false, nil, nil) ++ // This method never errors - we should look into it if it does. ++ if err != nil { ++ panic(err) ++ } ++ ++ limit := uint64(float64(intrinsicGas+gasUsed) * GasPadFactor) ++ if limit > blockGasLimit { ++ return blockGasLimit ++ } ++ return limit ++}
@@ -8787,7 +50616,7 @@
@@ -8797,66 +50626,110 @@
-
+36
+
+82
-0
-
diff --git OP/packages/contracts-bedrock/snapshots/storageLayout/FeeCurrency.json CELO/packages/contracts-bedrock/snapshots/storageLayout/FeeCurrency.json +
diff --git OP/op-chain-ops/deployer/flags.go CELO/op-chain-ops/deployer/flags.go new file mode 100644 -index 0000000000000000000000000000000000000000..418a98546cf776bc340d3ebdd5775412a3e7986e +index 0000000000000000000000000000000000000000..e0ab864bdada20bff0b364d3a09648df0368cf42 --- /dev/null -+++ CELO/packages/contracts-bedrock/snapshots/storageLayout/FeeCurrency.json -@@ -0,0 +1,37 @@ -+[ -+ { -+ "bytes": "32", -+ "label": "_balances", -+ "offset": 0, -+ "slot": "0", -+ "type": "mapping(address => uint256)" -+ }, -+ { -+ "bytes": "32", -+ "label": "_allowances", -+ "offset": 0, -+ "slot": "1", -+ "type": "mapping(address => mapping(address => uint256))" -+ }, -+ { -+ "bytes": "32", -+ "label": "_totalSupply", -+ "offset": 0, -+ "slot": "2", -+ "type": "uint256" -+ }, -+ { -+ "bytes": "32", -+ "label": "_name", -+ "offset": 0, -+ "slot": "3", -+ "type": "string" -+ }, -+ { -+ "bytes": "32", -+ "label": "_symbol", -+ "offset": 0, -+ "slot": "4", -+ "type": "string" -+ } -+] -\ No newline at end of file
++++ CELO/op-chain-ops/deployer/flags.go +@@ -0,0 +1,82 @@ ++package deployer ++ ++import ( ++ "os" ++ ++ op_service "github.com/ethereum-optimism/optimism/op-service" ++ oplog "github.com/ethereum-optimism/optimism/op-service/log" ++ "github.com/urfave/cli/v2" ++) ++ ++const ( ++ EnvVarPrefix = "DEPLOYER" ++ L1RPCURLFlagName = "l1-rpc-url" ++ L1ChainIDFlagName = "l1-chain-id" ++ L2ChainIDsFlagName = "l2-chain-ids" ++ WorkdirFlagName = "workdir" ++ OutdirFlagName = "outdir" ++ PrivateKeyFlagName = "private-key" ++) ++ ++var ( ++ L1RPCURLFlag = &cli.StringFlag{ ++ Name: L1RPCURLFlagName, ++ Usage: "RPC URL for the L1 chain. Can be set to 'genesis' for deployments " + ++ "that will be deployed at the launch of the L1.", ++ EnvVars: []string{ ++ "L1_RPC_URL", ++ }, ++ } ++ L1ChainIDFlag = &cli.Uint64Flag{ ++ Name: L1ChainIDFlagName, ++ Usage: "Chain ID of the L1 chain.", ++ EnvVars: prefixEnvVar("L1_CHAIN_ID"), ++ Value: 900, ++ } ++ L2ChainIDsFlag = &cli.StringFlag{ ++ Name: L2ChainIDsFlagName, ++ Usage: "Comma-separated list of L2 chain IDs to deploy.", ++ EnvVars: prefixEnvVar("L2_CHAIN_IDS"), ++ } ++ WorkdirFlag = &cli.StringFlag{ ++ Name: WorkdirFlagName, ++ Usage: "Directory storing intent and stage. Defaults to the current directory.", ++ EnvVars: prefixEnvVar("WORKDIR"), ++ Value: cwd(), ++ Aliases: []string{ ++ OutdirFlagName, ++ }, ++ } ++ ++ PrivateKeyFlag = &cli.StringFlag{ ++ Name: PrivateKeyFlagName, ++ Usage: "Private key of the deployer account.", ++ EnvVars: prefixEnvVar("PRIVATE_KEY"), ++ } ++) ++ ++var GlobalFlags = append([]cli.Flag{}, oplog.CLIFlags(EnvVarPrefix)...) ++ ++var InitFlags = []cli.Flag{ ++ L1ChainIDFlag, ++ L2ChainIDsFlag, ++ WorkdirFlag, ++} ++ ++var ApplyFlags = []cli.Flag{ ++ L1RPCURLFlag, ++ WorkdirFlag, ++ PrivateKeyFlag, ++} ++ ++func prefixEnvVar(name string) []string { ++ return op_service.PrefixEnvVar(EnvVarPrefix, name) ++} ++ ++func cwd() string { ++ dir, err := os.Getwd() ++ if err != nil { ++ return "" ++ } ++ return dir ++}
@@ -8871,7 +50744,7 @@
@@ -8881,59 +50754,150 @@
-
+29
+
+122
-0
-
diff --git OP/packages/contracts-bedrock/snapshots/storageLayout/FeeCurrencyDirectory.json CELO/packages/contracts-bedrock/snapshots/storageLayout/FeeCurrencyDirectory.json +
diff --git OP/op-chain-ops/deployer/init.go CELO/op-chain-ops/deployer/init.go new file mode 100644 -index 0000000000000000000000000000000000000000..61ccdc5fb15116df778992284198adbb9aeaa26b +index 0000000000000000000000000000000000000000..bd79f980cdffb1bc29cc145bd0a4201adcfa6891 --- /dev/null -+++ CELO/packages/contracts-bedrock/snapshots/storageLayout/FeeCurrencyDirectory.json -@@ -0,0 +1,30 @@ -+[ -+ { -+ "bytes": "1", -+ "label": "initialized", -+ "offset": 0, -+ "slot": "0", -+ "type": "bool" -+ }, -+ { -+ "bytes": "20", -+ "label": "_owner", -+ "offset": 1, -+ "slot": "0", -+ "type": "address" -+ }, -+ { -+ "bytes": "32", -+ "label": "currencies", -+ "offset": 0, -+ "slot": "1", -+ "type": "mapping(address => struct IFeeCurrencyDirectory.CurrencyConfig)" -+ }, -+ { -+ "bytes": "32", -+ "label": "currencyList", -+ "offset": 0, -+ "slot": "2", -+ "type": "address[]" -+ } -+] -\ No newline at end of file
++++ CELO/op-chain-ops/deployer/init.go +@@ -0,0 +1,122 @@ ++package deployer ++ ++import ( ++ "fmt" ++ "path" ++ "strings" ++ ++ op_service "github.com/ethereum-optimism/optimism/op-service" ++ ++ "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/state" ++ "github.com/ethereum-optimism/optimism/op-chain-ops/devkeys" ++ "github.com/ethereum/go-ethereum/common" ++ "github.com/urfave/cli/v2" ++) ++ ++type InitConfig struct { ++ L1ChainID uint64 ++ Outdir string ++ L2ChainIDs []common.Hash ++} ++ ++func (c *InitConfig) Check() error { ++ if c.L1ChainID == 0 { ++ return fmt.Errorf("l1ChainID must be specified") ++ } ++ ++ if c.Outdir == "" { ++ return fmt.Errorf("outdir must be specified") ++ } ++ ++ if len(c.L2ChainIDs) == 0 { ++ return fmt.Errorf("must specify at least one L2 chain ID") ++ } ++ ++ return nil ++} ++ ++func InitCLI() func(ctx *cli.Context) error { ++ return func(ctx *cli.Context) error { ++ l1ChainID := ctx.Uint64(L1ChainIDFlagName) ++ outdir := ctx.String(OutdirFlagName) ++ ++ l2ChainIDsRaw := ctx.String(L2ChainIDsFlagName) ++ l2ChainIDsStr := strings.Split(l2ChainIDsRaw, ",") ++ l2ChainIDs := make([]common.Hash, 0, len(l2ChainIDsStr)) ++ for _, idStr := range l2ChainIDsStr { ++ id, err := op_service.Parse256BitChainID(idStr) ++ if err != nil { ++ return fmt.Errorf("invalid chain ID: %w", err) ++ } ++ l2ChainIDs = append(l2ChainIDs, id) ++ } ++ ++ return Init(InitConfig{ ++ L1ChainID: l1ChainID, ++ Outdir: outdir, ++ L2ChainIDs: l2ChainIDs, ++ }) ++ } ++} ++ ++func Init(cfg InitConfig) error { ++ if err := cfg.Check(); err != nil { ++ return fmt.Errorf("invalid config for init: %w", err) ++ } ++ ++ intent := &state.Intent{ ++ L1ChainID: cfg.L1ChainID, ++ UseFaultProofs: true, ++ FundDevAccounts: true, ++ ContractsRelease: "dev", ++ } ++ ++ l1ChainIDBig := intent.L1ChainIDBig() ++ ++ dk, err := devkeys.NewMnemonicDevKeys(devkeys.TestMnemonic) ++ if err != nil { ++ return fmt.Errorf("failed to create dev keys: %w", err) ++ } ++ ++ addrFor := func(key devkeys.Key) common.Address { ++ // The error below should never happen, so panic if it does. ++ addr, err := dk.Address(key) ++ if err != nil { ++ panic(err) ++ } ++ return addr ++ } ++ intent.SuperchainRoles = state.SuperchainRoles{ ++ ProxyAdminOwner: addrFor(devkeys.L1ProxyAdminOwnerRole.Key(l1ChainIDBig)), ++ ProtocolVersionsOwner: addrFor(devkeys.SuperchainProtocolVersionsOwner.Key(l1ChainIDBig)), ++ Guardian: addrFor(devkeys.SuperchainConfigGuardianKey.Key(l1ChainIDBig)), ++ } ++ ++ for _, l2ChainID := range cfg.L2ChainIDs { ++ l2ChainIDBig := l2ChainID.Big() ++ intent.Chains = append(intent.Chains, &state.ChainIntent{ ++ ID: l2ChainID, ++ Roles: state.ChainRoles{ ++ ProxyAdminOwner: addrFor(devkeys.L2ProxyAdminOwnerRole.Key(l2ChainIDBig)), ++ SystemConfigOwner: addrFor(devkeys.SystemConfigOwner.Key(l2ChainIDBig)), ++ GovernanceTokenOwner: addrFor(devkeys.L2ProxyAdminOwnerRole.Key(l2ChainIDBig)), ++ UnsafeBlockSigner: addrFor(devkeys.SequencerP2PRole.Key(l2ChainIDBig)), ++ Batcher: addrFor(devkeys.BatcherRole.Key(l2ChainIDBig)), ++ Proposer: addrFor(devkeys.ProposerRole.Key(l2ChainIDBig)), ++ Challenger: addrFor(devkeys.ChallengerRole.Key(l2ChainIDBig)), ++ }, ++ }) ++ } ++ ++ st := &state.State{ ++ Version: 1, ++ } ++ ++ if err := intent.WriteToFile(path.Join(cfg.Outdir, "intent.toml")); err != nil { ++ return fmt.Errorf("failed to write intent to file: %w", err) ++ } ++ if err := st.WriteToFile(path.Join(cfg.Outdir, "state.json")); err != nil { ++ return fmt.Errorf("failed to write state to file: %w", err) ++ } ++ return nil ++}
@@ -8948,7 +50912,7 @@
@@ -8958,101 +50922,111 @@
-
+71
+
+83
-0
-
diff --git OP/packages/contracts-bedrock/snapshots/storageLayout/FeeHandler.json CELO/packages/contracts-bedrock/snapshots/storageLayout/FeeHandler.json +
diff --git OP/op-chain-ops/deployer/inspect/flags.go CELO/op-chain-ops/deployer/inspect/flags.go new file mode 100644 -index 0000000000000000000000000000000000000000..468bb7dc389218cc2a62ad57d94c340b31fa5a30 +index 0000000000000000000000000000000000000000..601e28ba85a5efe91c9221ae35a8438d4a708526 --- /dev/null -+++ CELO/packages/contracts-bedrock/snapshots/storageLayout/FeeHandler.json -@@ -0,0 +1,72 @@ -+[ -+ { -+ "bytes": "20", -+ "label": "_owner", -+ "offset": 0, -+ "slot": "0", -+ "type": "address" -+ }, -+ { -+ "bytes": "1", -+ "label": "initialized", -+ "offset": 20, -+ "slot": "0", -+ "type": "bool" -+ }, -+ { -+ "bytes": "20", -+ "label": "registry", -+ "offset": 0, -+ "slot": "1", -+ "type": "contract ICeloRegistry" -+ }, -+ { -+ "bytes": "32", -+ "label": "_status", -+ "offset": 0, -+ "slot": "2", -+ "type": "uint256" -+ }, -+ { -+ "bytes": "32", -+ "label": "lastLimitDay", -+ "offset": 0, -+ "slot": "3", -+ "type": "uint256" -+ }, -+ { -+ "bytes": "32", -+ "label": "burnFraction", -+ "offset": 0, -+ "slot": "4", -+ "type": "struct FixidityLib.Fraction" -+ }, -+ { -+ "bytes": "20", -+ "label": "feeBeneficiary", -+ "offset": 0, -+ "slot": "5", -+ "type": "address" -+ }, -+ { -+ "bytes": "32", -+ "label": "celoToBeBurned", -+ "offset": 0, -+ "slot": "6", -+ "type": "uint256" -+ }, -+ { -+ "bytes": "32", -+ "label": "tokenStates", -+ "offset": 0, -+ "slot": "7", -+ "type": "mapping(address => struct FeeHandler.TokenState)" -+ }, -+ { -+ "bytes": "64", -+ "label": "activeTokens", -+ "offset": 0, -+ "slot": "8", -+ "type": "struct EnumerableSet.AddressSet" -+ } -+] -\ No newline at end of file
++++ CELO/op-chain-ops/deployer/inspect/flags.go +@@ -0,0 +1,83 @@ ++package inspect ++ ++import ( ++ "fmt" ++ ++ op_service "github.com/ethereum-optimism/optimism/op-service" ++ ++ "github.com/ethereum-optimism/optimism/op-chain-ops/deployer" ++ "github.com/ethereum/go-ethereum/common" ++ "github.com/urfave/cli/v2" ++) ++ ++const ( ++ OutfileFlagName = "outfile" ++) ++ ++var ( ++ FlagOutfile = &cli.StringFlag{ ++ Name: OutfileFlagName, ++ Usage: "output file. set to - to use stdout", ++ Value: "-", ++ } ++) ++ ++var Flags = []cli.Flag{ ++ deployer.WorkdirFlag, ++ FlagOutfile, ++} ++ ++var Commands = []*cli.Command{ ++ { ++ Name: "genesis", ++ Usage: "outputs the genesis for an L2 chain", ++ Args: true, ++ ArgsUsage: "<chain-id>", ++ Action: GenesisCLI, ++ Flags: Flags, ++ }, ++ { ++ Name: "rollup", ++ Usage: "outputs the rollup config for an L2 chain", ++ Args: true, ++ ArgsUsage: "<chain-id>", ++ Action: RollupCLI, ++ Flags: Flags, ++ }, ++} ++ ++type cliConfig struct { ++ Workdir string ++ Outfile string ++ ChainID common.Hash ++} ++ ++func readConfig(cliCtx *cli.Context) (cliConfig, error) { ++ var cfg cliConfig ++ ++ outfile := cliCtx.String(OutfileFlagName) ++ if outfile == "" { ++ return cfg, fmt.Errorf("outfile flag is required") ++ } ++ ++ workdir := cliCtx.String(deployer.WorkdirFlagName) ++ if workdir == "" { ++ return cfg, fmt.Errorf("workdir flag is required") ++ } ++ ++ chainIDStr := cliCtx.Args().First() ++ if chainIDStr == "" { ++ return cfg, fmt.Errorf("chain-id argument is required") ++ } ++ ++ chainID, err := op_service.Parse256BitChainID(chainIDStr) ++ if err != nil { ++ return cfg, fmt.Errorf("failed to parse chain ID: %w", err) ++ } ++ ++ return cliConfig{ ++ Workdir: cliCtx.String(deployer.WorkdirFlagName), ++ Outfile: cliCtx.String(OutfileFlagName), ++ ChainID: chainID, ++ }, nil ++}
@@ -9067,7 +51041,7 @@
@@ -9077,45 +51051,120 @@
-
+15
+
+92
-0
-
diff --git OP/packages/contracts-bedrock/snapshots/storageLayout/Freezable.json CELO/packages/contracts-bedrock/snapshots/storageLayout/Freezable.json +
diff --git OP/op-chain-ops/deployer/inspect/genesis.go CELO/op-chain-ops/deployer/inspect/genesis.go new file mode 100644 -index 0000000000000000000000000000000000000000..fb89bbc7e1ab3904137e39358de306a828c60dac +index 0000000000000000000000000000000000000000..4c2fbad010929b543f2df3e1af12343c1194ec6e --- /dev/null -+++ CELO/packages/contracts-bedrock/snapshots/storageLayout/Freezable.json -@@ -0,0 +1,16 @@ -+[ -+ { -+ "bytes": "20", -+ "label": "_owner", -+ "offset": 0, -+ "slot": "0", -+ "type": "address" -+ }, -+ { -+ "bytes": "20", -+ "label": "registry", -+ "offset": 0, -+ "slot": "1", -+ "type": "contract ICeloRegistry" -+ } -+] -\ No newline at end of file
++++ CELO/op-chain-ops/deployer/inspect/genesis.go +@@ -0,0 +1,92 @@ ++package inspect ++ ++import ( ++ "fmt" ++ ++ "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/pipeline" ++ "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/state" ++ "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" ++ "github.com/ethereum-optimism/optimism/op-node/rollup" ++ "github.com/ethereum/go-ethereum/core" ++ ++ "github.com/ethereum-optimism/optimism/op-service/ioutil" ++ "github.com/ethereum-optimism/optimism/op-service/jsonutil" ++ "github.com/ethereum/go-ethereum/common" ++ "github.com/urfave/cli/v2" ++) ++ ++func GenesisCLI(cliCtx *cli.Context) error { ++ cfg, err := readConfig(cliCtx) ++ if err != nil { ++ return err ++ } ++ ++ env := &pipeline.Env{Workdir: cfg.Workdir} ++ globalState, err := env.ReadState() ++ if err != nil { ++ return fmt.Errorf("failed to read intent: %w", err) ++ } ++ ++ l2Genesis, _, err := GenesisAndRollup(globalState, cfg.ChainID) ++ if err != nil { ++ return fmt.Errorf("failed to generate genesis block: %w", err) ++ } ++ ++ if err := jsonutil.WriteJSON(l2Genesis, ioutil.ToStdOutOrFileOrNoop(cfg.Outfile, 0o666)); err != nil { ++ return fmt.Errorf("failed to write genesis: %w", err) ++ } ++ ++ return nil ++} ++ ++func GenesisAndRollup(globalState *state.State, chainID common.Hash) (*core.Genesis, *rollup.Config, error) { ++ if globalState.AppliedIntent == nil { ++ return nil, nil, fmt.Errorf("chain state is not applied - run op-deployer apply") ++ } ++ ++ chainIntent, err := globalState.AppliedIntent.Chain(chainID) ++ if err != nil { ++ return nil, nil, fmt.Errorf("failed to get applied chain intent: %w", err) ++ } ++ ++ chainState, err := globalState.Chain(chainID) ++ if err != nil { ++ return nil, nil, fmt.Errorf("failed to get chain ID %s: %w", chainID.String(), err) ++ } ++ ++ l2Allocs, err := chainState.UnmarshalAllocs() ++ if err != nil { ++ return nil, nil, fmt.Errorf("failed to unmarshal genesis: %w", err) ++ } ++ ++ config, err := state.CombineDeployConfig( ++ globalState.AppliedIntent, ++ chainIntent, ++ globalState, ++ chainState, ++ ) ++ if err != nil { ++ return nil, nil, fmt.Errorf("failed to combine L2 init config: %w", err) ++ } ++ ++ l2GenesisBuilt, err := genesis.BuildL2Genesis(&config, l2Allocs, chainState.StartBlock) ++ if err != nil { ++ return nil, nil, fmt.Errorf("failed to build L2 genesis: %w", err) ++ } ++ l2GenesisBlock := l2GenesisBuilt.ToBlock() ++ ++ rollupConfig, err := config.RollupConfig( ++ chainState.StartBlock, ++ l2GenesisBlock.Hash(), ++ l2GenesisBlock.Number().Uint64(), ++ ) ++ if err != nil { ++ return nil, nil, fmt.Errorf("failed to build rollup config: %w", err) ++ } ++ ++ if err := rollupConfig.Check(); err != nil { ++ return nil, nil, fmt.Errorf("generated rollup config does not pass validation: %w", err) ++ } ++ ++ return l2GenesisBuilt, rollupConfig, nil ++}
@@ -9130,7 +51179,7 @@
@@ -9140,66 +51189,62 @@
-
+36
+
+34
-0
-
diff --git OP/packages/contracts-bedrock/snapshots/storageLayout/GoldToken.json CELO/packages/contracts-bedrock/snapshots/storageLayout/GoldToken.json +
diff --git OP/op-chain-ops/deployer/inspect/rollup.go CELO/op-chain-ops/deployer/inspect/rollup.go new file mode 100644 -index 0000000000000000000000000000000000000000..67b349856d86cdaab5dd67f9e9e413210d44ce63 +index 0000000000000000000000000000000000000000..60cbf4f5c46c5082d5bb63fe5be1e092a1951930 --- /dev/null -+++ CELO/packages/contracts-bedrock/snapshots/storageLayout/GoldToken.json -@@ -0,0 +1,37 @@ -+[ -+ { -+ "bytes": "1", -+ "label": "initialized", -+ "offset": 0, -+ "slot": "0", -+ "type": "bool" -+ }, -+ { -+ "bytes": "20", -+ "label": "_owner", -+ "offset": 1, -+ "slot": "0", -+ "type": "address" -+ }, -+ { -+ "bytes": "20", -+ "label": "registry", -+ "offset": 0, -+ "slot": "1", -+ "type": "contract ICeloRegistry" -+ }, -+ { -+ "bytes": "32", -+ "label": "totalSupply_", -+ "offset": 0, -+ "slot": "2", -+ "type": "uint256" -+ }, -+ { -+ "bytes": "32", -+ "label": "allowed", -+ "offset": 0, -+ "slot": "3", -+ "type": "mapping(address => mapping(address => uint256))" -+ } -+] -\ No newline at end of file
++++ CELO/op-chain-ops/deployer/inspect/rollup.go +@@ -0,0 +1,34 @@ ++package inspect ++ ++import ( ++ "fmt" ++ ++ "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/pipeline" ++ "github.com/ethereum-optimism/optimism/op-service/ioutil" ++ "github.com/ethereum-optimism/optimism/op-service/jsonutil" ++ "github.com/urfave/cli/v2" ++) ++ ++func RollupCLI(cliCtx *cli.Context) error { ++ cfg, err := readConfig(cliCtx) ++ if err != nil { ++ return err ++ } ++ ++ env := &pipeline.Env{Workdir: cfg.Workdir} ++ globalState, err := env.ReadState() ++ if err != nil { ++ return fmt.Errorf("failed to read intent: %w", err) ++ } ++ ++ _, rollupConfig, err := GenesisAndRollup(globalState, cfg.ChainID) ++ if err != nil { ++ return fmt.Errorf("failed to generate rollup config: %w", err) ++ } ++ ++ if err := jsonutil.WriteJSON(rollupConfig, ioutil.ToStdOutOrFileOrNoop(cfg.Outfile, 0o666)); err != nil { ++ return fmt.Errorf("failed to write rollup config: %w", err) ++ } ++ ++ return nil ++}
@@ -9214,7 +51259,7 @@
@@ -9224,38 +51269,292 @@
-
+8
+
+264
-0
-
diff --git OP/packages/contracts-bedrock/snapshots/storageLayout/Initializable.json CELO/packages/contracts-bedrock/snapshots/storageLayout/Initializable.json +
diff --git OP/op-chain-ops/deployer/integration_test/apply_test.go CELO/op-chain-ops/deployer/integration_test/apply_test.go new file mode 100644 -index 0000000000000000000000000000000000000000..b29972a4de8eb134c79b8e19e36619de89bfeb4b +index 0000000000000000000000000000000000000000..ad22651fa36edd2733bd636a5e06fbc59c815144 --- /dev/null -+++ CELO/packages/contracts-bedrock/snapshots/storageLayout/Initializable.json -@@ -0,0 +1,9 @@ -+[ -+ { -+ "bytes": "1", -+ "label": "initialized", -+ "offset": 0, -+ "slot": "0", -+ "type": "bool" -+ } -+] -\ No newline at end of file
++++ CELO/op-chain-ops/deployer/integration_test/apply_test.go +@@ -0,0 +1,264 @@ ++package integration_test ++ ++import ( ++ "context" ++ "fmt" ++ "log/slog" ++ "math/big" ++ "net/url" ++ "path" ++ "runtime" ++ "testing" ++ ++ "github.com/ethereum-optimism/optimism/op-chain-ops/deployer" ++ "github.com/holiman/uint256" ++ ++ "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/pipeline" ++ "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/state" ++ "github.com/ethereum-optimism/optimism/op-chain-ops/devkeys" ++ opcrypto "github.com/ethereum-optimism/optimism/op-service/crypto" ++ "github.com/ethereum-optimism/optimism/op-service/testlog" ++ "github.com/ethereum-optimism/optimism/op-service/testutils/kurtosisutil" ++ "github.com/ethereum/go-ethereum/common" ++ "github.com/ethereum/go-ethereum/ethclient" ++ "github.com/stretchr/testify/require" ++) ++ ++const TestParams = ` ++participants: ++ - el_type: geth ++ el_extra_params: ++ - "--gcmode=archive" ++ cl_type: lighthouse ++network_params: ++ prefunded_accounts: '{ "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266": { "balance": "1000000ETH" } }' ++ additional_preloaded_contracts: '{ ++ "0x4e59b44847b379578588920cA78FbF26c0B4956C": { ++ balance: "0ETH", ++ code: "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf3", ++ storage: {}, ++ nonce: 0, ++ secretKey: "0x" ++ } ++ }' ++ network_id: "77799777" ++ seconds_per_slot: 3 ++ genesis_delay: 0 ++` ++ ++type deployerKey struct{} ++ ++func (d *deployerKey) HDPath() string { ++ return "m/44'/60'/0'/0/0" ++} ++ ++func (d *deployerKey) String() string { ++ return "deployer-key" ++} ++ ++func TestEndToEndApply(t *testing.T) { ++ kurtosisutil.Test(t) ++ ++ lgr := testlog.Logger(t, slog.LevelDebug) ++ ++ ctx, cancel := context.WithCancel(context.Background()) ++ defer cancel() ++ ++ _, testFilename, _, ok := runtime.Caller(0) ++ require.Truef(t, ok, "failed to get test filename") ++ monorepoDir := path.Join(path.Dir(testFilename), "..", "..", "..") ++ artifactsDir := path.Join(monorepoDir, "packages", "contracts-bedrock", "forge-artifacts") ++ ++ enclaveCtx := kurtosisutil.StartEnclave(t, ctx, lgr, "github.com/ethpandaops/ethereum-package", TestParams) ++ ++ service, err := enclaveCtx.GetServiceContext("el-1-geth-lighthouse") ++ require.NoError(t, err) ++ ++ ip := service.GetMaybePublicIPAddress() ++ ports := service.GetPublicPorts() ++ rpcURL := fmt.Sprintf("http://%s:%d", ip, ports["rpc"].GetNumber()) ++ l1Client, err := ethclient.Dial(rpcURL) ++ require.NoError(t, err) ++ ++ artifactsURL, err := url.Parse(fmt.Sprintf("file://%s", artifactsDir)) ++ require.NoError(t, err) ++ ++ depKey := new(deployerKey) ++ l1ChainID := big.NewInt(77799777) ++ dk, err := devkeys.NewMnemonicDevKeys(devkeys.TestMnemonic) ++ require.NoError(t, err) ++ pk, err := dk.Secret(depKey) ++ require.NoError(t, err) ++ signer := opcrypto.SignerFnFromBind(opcrypto.PrivateKeySignerFn(pk, l1ChainID)) ++ ++ id := uint256.NewInt(1) ++ ++ deployerAddr, err := dk.Address(depKey) ++ require.NoError(t, err) ++ ++ env := &pipeline.Env{ ++ Workdir: t.TempDir(), ++ L1Client: l1Client, ++ Signer: signer, ++ Deployer: deployerAddr, ++ Logger: lgr, ++ } ++ ++ t.Run("initial chain", func(t *testing.T) { ++ intent, st := makeIntent(t, l1ChainID, artifactsURL, dk, id) ++ ++ require.NoError(t, deployer.ApplyPipeline( ++ ctx, ++ env, ++ intent, ++ st, ++ )) ++ ++ addrs := []struct { ++ name string ++ addr common.Address ++ }{ ++ {"SuperchainProxyAdmin", st.SuperchainDeployment.ProxyAdminAddress}, ++ {"SuperchainConfigProxy", st.SuperchainDeployment.SuperchainConfigProxyAddress}, ++ {"SuperchainConfigImpl", st.SuperchainDeployment.SuperchainConfigImplAddress}, ++ {"ProtocolVersionsProxy", st.SuperchainDeployment.ProtocolVersionsProxyAddress}, ++ {"ProtocolVersionsImpl", st.SuperchainDeployment.ProtocolVersionsImplAddress}, ++ {"OpcmProxy", st.ImplementationsDeployment.OpcmProxyAddress}, ++ {"DelayedWETHImpl", st.ImplementationsDeployment.DelayedWETHImplAddress}, ++ {"OptimismPortalImpl", st.ImplementationsDeployment.OptimismPortalImplAddress}, ++ {"PreimageOracleSingleton", st.ImplementationsDeployment.PreimageOracleSingletonAddress}, ++ {"MipsSingleton", st.ImplementationsDeployment.MipsSingletonAddress}, ++ {"SystemConfigImpl", st.ImplementationsDeployment.SystemConfigImplAddress}, ++ {"L1CrossDomainMessengerImpl", st.ImplementationsDeployment.L1CrossDomainMessengerImplAddress}, ++ {"L1ERC721BridgeImpl", st.ImplementationsDeployment.L1ERC721BridgeImplAddress}, ++ {"L1StandardBridgeImpl", st.ImplementationsDeployment.L1StandardBridgeImplAddress}, ++ {"OptimismMintableERC20FactoryImpl", st.ImplementationsDeployment.OptimismMintableERC20FactoryImplAddress}, ++ {"DisputeGameFactoryImpl", st.ImplementationsDeployment.DisputeGameFactoryImplAddress}, ++ } ++ for _, addr := range addrs { ++ t.Run(addr.name, func(t *testing.T) { ++ code, err := l1Client.CodeAt(ctx, addr.addr, nil) ++ require.NoError(t, err) ++ require.NotEmpty(t, code, "contracts %s at %s has no code", addr.name, addr.addr) ++ }) ++ } ++ ++ validateOPChainDeployment(t, ctx, l1Client, st) ++ }) ++ ++ t.Run("subsequent chain", func(t *testing.T) { ++ newID := uint256.NewInt(2) ++ intent, st := makeIntent(t, l1ChainID, artifactsURL, dk, newID) ++ env.Workdir = t.TempDir() ++ ++ require.NoError(t, deployer.ApplyPipeline( ++ ctx, ++ env, ++ intent, ++ st, ++ )) ++ ++ addrs := []struct { ++ name string ++ addr common.Address ++ }{ ++ {"SuperchainConfigProxy", st.SuperchainDeployment.SuperchainConfigProxyAddress}, ++ {"ProtocolVersionsProxy", st.SuperchainDeployment.ProtocolVersionsProxyAddress}, ++ {"OpcmProxy", st.ImplementationsDeployment.OpcmProxyAddress}, ++ } ++ for _, addr := range addrs { ++ t.Run(addr.name, func(t *testing.T) { ++ code, err := l1Client.CodeAt(ctx, addr.addr, nil) ++ require.NoError(t, err) ++ require.NotEmpty(t, code, "contracts %s at %s has no code", addr.name, addr.addr) ++ }) ++ } ++ ++ validateOPChainDeployment(t, ctx, l1Client, st) ++ }) ++} ++ ++func makeIntent( ++ t *testing.T, ++ l1ChainID *big.Int, ++ artifactsURL *url.URL, ++ dk *devkeys.MnemonicDevKeys, ++ l2ChainID *uint256.Int, ++) (*state.Intent, *state.State) { ++ addrFor := func(key devkeys.Key) common.Address { ++ addr, err := dk.Address(key) ++ require.NoError(t, err) ++ return addr ++ } ++ ++ intent := &state.Intent{ ++ L1ChainID: l1ChainID.Uint64(), ++ SuperchainRoles: state.SuperchainRoles{ ++ ProxyAdminOwner: addrFor(devkeys.L1ProxyAdminOwnerRole.Key(l1ChainID)), ++ ProtocolVersionsOwner: addrFor(devkeys.SuperchainDeployerKey.Key(l1ChainID)), ++ Guardian: addrFor(devkeys.SuperchainConfigGuardianKey.Key(l1ChainID)), ++ }, ++ UseFaultProofs: true, ++ FundDevAccounts: true, ++ ContractArtifactsURL: (*state.ArtifactsURL)(artifactsURL), ++ ContractsRelease: "dev", ++ Chains: []*state.ChainIntent{ ++ { ++ ID: l2ChainID.Bytes32(), ++ Roles: state.ChainRoles{ ++ ProxyAdminOwner: addrFor(devkeys.L2ProxyAdminOwnerRole.Key(l1ChainID)), ++ SystemConfigOwner: addrFor(devkeys.SystemConfigOwner.Key(l1ChainID)), ++ GovernanceTokenOwner: addrFor(devkeys.L2ProxyAdminOwnerRole.Key(l1ChainID)), ++ UnsafeBlockSigner: addrFor(devkeys.SequencerP2PRole.Key(l1ChainID)), ++ Batcher: addrFor(devkeys.BatcherRole.Key(l1ChainID)), ++ Proposer: addrFor(devkeys.ProposerRole.Key(l1ChainID)), ++ Challenger: addrFor(devkeys.ChallengerRole.Key(l1ChainID)), ++ }, ++ }, ++ }, ++ } ++ st := &state.State{ ++ Version: 1, ++ } ++ return intent, st ++} ++ ++func validateOPChainDeployment(t *testing.T, ctx context.Context, l1Client *ethclient.Client, st *state.State) { ++ for _, chainState := range st.Chains { ++ chainAddrs := []struct { ++ name string ++ addr common.Address ++ }{ ++ {"ProxyAdminAddress", chainState.ProxyAdminAddress}, ++ {"AddressManagerAddress", chainState.AddressManagerAddress}, ++ {"L1ERC721BridgeProxyAddress", chainState.L1ERC721BridgeProxyAddress}, ++ {"SystemConfigProxyAddress", chainState.SystemConfigProxyAddress}, ++ {"OptimismMintableERC20FactoryProxyAddress", chainState.OptimismMintableERC20FactoryProxyAddress}, ++ {"L1StandardBridgeProxyAddress", chainState.L1StandardBridgeProxyAddress}, ++ {"L1CrossDomainMessengerProxyAddress", chainState.L1CrossDomainMessengerProxyAddress}, ++ {"OptimismPortalProxyAddress", chainState.OptimismPortalProxyAddress}, ++ {"DisputeGameFactoryProxyAddress", chainState.DisputeGameFactoryProxyAddress}, ++ {"AnchorStateRegistryProxyAddress", chainState.AnchorStateRegistryProxyAddress}, ++ {"AnchorStateRegistryImplAddress", chainState.AnchorStateRegistryImplAddress}, ++ {"FaultDisputeGameAddress", chainState.FaultDisputeGameAddress}, ++ {"PermissionedDisputeGameAddress", chainState.PermissionedDisputeGameAddress}, ++ {"DelayedWETHPermissionedGameProxyAddress", chainState.DelayedWETHPermissionedGameProxyAddress}, ++ {"DelayedWETHPermissionlessGameProxyAddress", chainState.DelayedWETHPermissionlessGameProxyAddress}, ++ } ++ for _, addr := range chainAddrs { ++ // TODO Delete this `if`` block once FaultDisputeGameAddress is deployed. ++ if addr.name == "FaultDisputeGameAddress" { ++ continue ++ } ++ t.Run(addr.name, func(t *testing.T) { ++ code, err := l1Client.CodeAt(ctx, addr.addr, nil) ++ require.NoError(t, err) ++ require.NotEmpty(t, code, "contracts %s at %s for chain %s has no code", addr.name, addr.addr, chainState.ID) ++ }) ++ } ++ ++ t.Run("l2 genesis", func(t *testing.T) { ++ require.Greater(t, len(chainState.Allocs), 0) ++ }) ++ } ++}
@@ -9270,7 +51569,7 @@
@@ -9280,59 +51579,111 @@
-
+29
+
+83
-0
-
diff --git OP/packages/contracts-bedrock/snapshots/storageLayout/MentoFeeHandlerSeller.json CELO/packages/contracts-bedrock/snapshots/storageLayout/MentoFeeHandlerSeller.json +
diff --git OP/op-chain-ops/deployer/opcm/contract.go CELO/op-chain-ops/deployer/opcm/contract.go new file mode 100644 -index 0000000000000000000000000000000000000000..a66c44056e6d0350f83d4ee520bafeda4d5c2a58 +index 0000000000000000000000000000000000000000..c81222aafe888cf45d871a4d4c8af3f83948298d --- /dev/null -+++ CELO/packages/contracts-bedrock/snapshots/storageLayout/MentoFeeHandlerSeller.json -@@ -0,0 +1,30 @@ -+[ -+ { -+ "bytes": "20", -+ "label": "_owner", -+ "offset": 0, -+ "slot": "0", -+ "type": "address" -+ }, -+ { -+ "bytes": "1", -+ "label": "initialized", -+ "offset": 20, -+ "slot": "0", -+ "type": "bool" -+ }, -+ { -+ "bytes": "20", -+ "label": "registry", -+ "offset": 0, -+ "slot": "1", -+ "type": "contract ICeloRegistry" -+ }, -+ { -+ "bytes": "32", -+ "label": "minimumReports", -+ "offset": 0, -+ "slot": "2", -+ "type": "mapping(address => uint256)" -+ } -+] -\ No newline at end of file
++++ CELO/op-chain-ops/deployer/opcm/contract.go +@@ -0,0 +1,83 @@ ++package opcm ++ ++import ( ++ "bytes" ++ "context" ++ "fmt" ++ ++ "github.com/ethereum/go-ethereum" ++ "github.com/ethereum/go-ethereum/accounts/abi" ++ "github.com/ethereum/go-ethereum/common" ++ "github.com/ethereum/go-ethereum/ethclient" ++) ++ ++type Contract struct { ++ addr common.Address ++ client *ethclient.Client ++} ++ ++func NewContract(addr common.Address, client *ethclient.Client) *Contract { ++ return &Contract{addr: addr, client: client} ++} ++ ++func (c *Contract) SuperchainConfig(ctx context.Context) (common.Address, error) { ++ return c.getAddress(ctx, "superchainConfig") ++} ++ ++func (c *Contract) ProtocolVersions(ctx context.Context) (common.Address, error) { ++ return c.getAddress(ctx, "protocolVersions") ++} ++ ++func (c *Contract) getAddress(ctx context.Context, name string) (common.Address, error) { ++ method := abi.NewMethod( ++ name, ++ name, ++ abi.Function, ++ "view", ++ true, ++ false, ++ abi.Arguments{}, ++ abi.Arguments{ ++ abi.Argument{ ++ Name: "address", ++ Type: mustType("address"), ++ Indexed: false, ++ }, ++ }, ++ ) ++ ++ calldata, err := method.Inputs.Pack() ++ if err != nil { ++ return common.Address{}, fmt.Errorf("failed to pack inputs: %w", err) ++ } ++ ++ msg := ethereum.CallMsg{ ++ To: &c.addr, ++ Data: append(bytes.Clone(method.ID), calldata...), ++ } ++ result, err := c.client.CallContract(ctx, msg, nil) ++ if err != nil { ++ return common.Address{}, fmt.Errorf("failed to call contract: %w", err) ++ } ++ ++ out, err := method.Outputs.Unpack(result) ++ if err != nil { ++ return common.Address{}, fmt.Errorf("failed to unpack result: %w", err) ++ } ++ if len(out) != 1 { ++ return common.Address{}, fmt.Errorf("unexpected output length: %d", len(out)) ++ } ++ addr, ok := out[0].(common.Address) ++ if !ok { ++ return common.Address{}, fmt.Errorf("unexpected type: %T", out[0]) ++ } ++ return addr, nil ++} ++ ++func mustType(t string) abi.Type { ++ typ, err := abi.NewType(t, "", nil) ++ if err != nil { ++ panic(err) ++ } ++ return typ ++}
@@ -9347,7 +51698,7 @@
@@ -9357,59 +51708,137 @@
-
+29
+
+109
-0
-
diff --git OP/packages/contracts-bedrock/snapshots/storageLayout/MockSortedOracles.json CELO/packages/contracts-bedrock/snapshots/storageLayout/MockSortedOracles.json +
diff --git OP/op-chain-ops/deployer/opcm/implementations.go CELO/op-chain-ops/deployer/opcm/implementations.go new file mode 100644 -index 0000000000000000000000000000000000000000..c44ef116af9505417a194688daf746a4c58cdcff +index 0000000000000000000000000000000000000000..fec30d94cbd555cf3473bfb127bb97fcb99cd061 --- /dev/null -+++ CELO/packages/contracts-bedrock/snapshots/storageLayout/MockSortedOracles.json -@@ -0,0 +1,30 @@ -+[ -+ { -+ "bytes": "32", -+ "label": "numerators", -+ "offset": 0, -+ "slot": "0", -+ "type": "mapping(address => uint256)" -+ }, -+ { -+ "bytes": "32", -+ "label": "medianTimestamp", -+ "offset": 0, -+ "slot": "1", -+ "type": "mapping(address => uint256)" -+ }, -+ { -+ "bytes": "32", -+ "label": "numRates", -+ "offset": 0, -+ "slot": "2", -+ "type": "mapping(address => uint256)" -+ }, -+ { -+ "bytes": "32", -+ "label": "expired", -+ "offset": 0, -+ "slot": "3", -+ "type": "mapping(address => bool)" -+ } -+] -\ No newline at end of file
++++ CELO/op-chain-ops/deployer/opcm/implementations.go +@@ -0,0 +1,109 @@ ++package opcm ++ ++import ( ++ "fmt" ++ "math/big" ++ ++ "github.com/ethereum/go-ethereum/common" ++ ++ "github.com/ethereum-optimism/optimism/op-chain-ops/script" ++) ++ ++type DeployImplementationsInput struct { ++ Salt common.Hash ++ WithdrawalDelaySeconds *big.Int ++ MinProposalSizeBytes *big.Int ++ ChallengePeriodSeconds *big.Int ++ ProofMaturityDelaySeconds *big.Int ++ DisputeGameFinalityDelaySeconds *big.Int ++ // Release version to set OPCM implementations for, of the format `op-contracts/vX.Y.Z`. ++ Release string ++ SuperchainConfigProxy common.Address ++ ProtocolVersionsProxy common.Address ++ UseInterop bool // if true, deploy Interop implementations ++ ++ SuperchainProxyAdmin common.Address ++ StandardVersionsToml string // contents of 'standard-versions.toml' file ++} ++ ++func (input *DeployImplementationsInput) InputSet() bool { ++ return true ++} ++ ++type DeployImplementationsOutput struct { ++ OpcmProxy common.Address ++ OpcmImpl common.Address ++ DelayedWETHImpl common.Address ++ OptimismPortalImpl common.Address ++ PreimageOracleSingleton common.Address ++ MipsSingleton common.Address ++ SystemConfigImpl common.Address ++ L1CrossDomainMessengerImpl common.Address ++ L1ERC721BridgeImpl common.Address ++ L1StandardBridgeImpl common.Address ++ OptimismMintableERC20FactoryImpl common.Address ++ DisputeGameFactoryImpl common.Address ++} ++ ++func (output *DeployImplementationsOutput) CheckOutput(input common.Address) error { ++ return nil ++} ++ ++type DeployImplementationsScript struct { ++ Run func(input, output common.Address) error ++} ++ ++func DeployImplementations( ++ host *script.Host, ++ input DeployImplementationsInput, ++) (DeployImplementationsOutput, error) { ++ var output DeployImplementationsOutput ++ inputAddr := host.NewScriptAddress() ++ outputAddr := host.NewScriptAddress() ++ ++ cleanupInput, err := script.WithPrecompileAtAddress[*DeployImplementationsInput](host, inputAddr, &input) ++ if err != nil { ++ return output, fmt.Errorf("failed to insert DeployImplementationsInput precompile: %w", err) ++ } ++ defer cleanupInput() ++ ++ cleanupOutput, err := script.WithPrecompileAtAddress[*DeployImplementationsOutput](host, outputAddr, &output, ++ script.WithFieldSetter[*DeployImplementationsOutput]) ++ if err != nil { ++ return output, fmt.Errorf("failed to insert DeployImplementationsOutput precompile: %w", err) ++ } ++ defer cleanupOutput() ++ ++ implContract := "DeployImplementations" ++ if input.UseInterop { ++ implContract = "DeployImplementationsInterop" ++ } ++ deployScript, cleanupDeploy, err := script.WithScript[DeployImplementationsScript](host, "DeployImplementations.s.sol", implContract) ++ if err != nil { ++ return output, fmt.Errorf("failed to load %s script: %w", implContract, err) ++ } ++ defer cleanupDeploy() ++ ++ opcmContract := "OPContractsManager" ++ if input.UseInterop { ++ opcmContract = "OPContractsManagerInterop" ++ } ++ if err := host.RememberOnLabel("OPContractsManager", opcmContract+".sol", opcmContract); err != nil { ++ return output, fmt.Errorf("failed to link OPContractsManager label: %w", err) ++ } ++ ++ // So we can see in detail where the SystemConfig interop initializer fails ++ sysConfig := "SystemConfig" ++ if input.UseInterop { ++ sysConfig = "SystemConfigInterop" ++ } ++ if err := host.RememberOnLabel("SystemConfigImpl", sysConfig+".sol", sysConfig); err != nil { ++ return output, fmt.Errorf("failed to link SystemConfig label: %w", err) ++ } ++ ++ if err := deployScript.Run(inputAddr, outputAddr); err != nil { ++ return output, fmt.Errorf("failed to run %s script: %w", implContract, err) ++ } ++ ++ return output, nil ++}
@@ -9424,7 +51853,7 @@
@@ -9434,101 +51863,83 @@
-
+71
+
+55
-0
-
diff --git OP/packages/contracts-bedrock/snapshots/storageLayout/SortedOracles.json CELO/packages/contracts-bedrock/snapshots/storageLayout/SortedOracles.json +
diff --git OP/op-chain-ops/deployer/opcm/l2genesis.go CELO/op-chain-ops/deployer/opcm/l2genesis.go new file mode 100644 -index 0000000000000000000000000000000000000000..e1e5e1736aff6530fc2e9dbeeecc4a4c9a316365 +index 0000000000000000000000000000000000000000..8b6e123dad3fcc82450fd6dfea07dcfa615bcd4d --- /dev/null -+++ CELO/packages/contracts-bedrock/snapshots/storageLayout/SortedOracles.json -@@ -0,0 +1,72 @@ -+[ -+ { -+ "bytes": "20", -+ "label": "_owner", -+ "offset": 0, -+ "slot": "0", -+ "type": "address" -+ }, -+ { -+ "bytes": "1", -+ "label": "initialized", -+ "offset": 20, -+ "slot": "0", -+ "type": "bool" -+ }, -+ { -+ "bytes": "32", -+ "label": "rates", -+ "offset": 0, -+ "slot": "1", -+ "type": "mapping(address => struct SortedLinkedListWithMedian.List)" -+ }, -+ { -+ "bytes": "32", -+ "label": "timestamps", -+ "offset": 0, -+ "slot": "2", -+ "type": "mapping(address => struct SortedLinkedListWithMedian.List)" -+ }, -+ { -+ "bytes": "32", -+ "label": "isOracle", -+ "offset": 0, -+ "slot": "3", -+ "type": "mapping(address => mapping(address => bool))" -+ }, -+ { -+ "bytes": "32", -+ "label": "oracles", -+ "offset": 0, -+ "slot": "4", -+ "type": "mapping(address => address[])" -+ }, -+ { -+ "bytes": "32", -+ "label": "reportExpirySeconds", -+ "offset": 0, -+ "slot": "5", -+ "type": "uint256" -+ }, -+ { -+ "bytes": "32", -+ "label": "tokenReportExpirySeconds", -+ "offset": 0, -+ "slot": "6", -+ "type": "mapping(address => uint256)" -+ }, -+ { -+ "bytes": "20", -+ "label": "breakerBox", -+ "offset": 0, -+ "slot": "7", -+ "type": "contract IBreakerBox" -+ }, -+ { -+ "bytes": "32", -+ "label": "equivalentTokens", -+ "offset": 0, -+ "slot": "8", -+ "type": "mapping(address => struct SortedOracles.EquivalentToken)" -+ } -+] -\ No newline at end of file
++++ CELO/op-chain-ops/deployer/opcm/l2genesis.go +@@ -0,0 +1,55 @@ ++package opcm ++ ++import ( ++ "fmt" ++ ++ "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" ++ "github.com/ethereum-optimism/optimism/op-chain-ops/script" ++ "github.com/ethereum/go-ethereum/common" ++) ++ ++var ( ++ // address(uint160(uint256(keccak256(abi.encode("optimism.deployconfig"))))) - not a simple hash, due to ABI encode ++ deployConfigAddr = common.HexToAddress("0x9568d36E291c2C4c34fa5593fcE73715abEf6F9c") ++) ++ ++type L1Deployments struct { ++ L1CrossDomainMessengerProxy common.Address ++ L1StandardBridgeProxy common.Address ++ L1ERC721BridgeProxy common.Address ++} ++ ++type L2GenesisInput struct { ++ L1Deployments L1Deployments ++ L2Config genesis.L2InitializationConfig ++} ++ ++type L2GenesisScript struct { ++ RunWithEnv func() error ++} ++ ++func L2Genesis(l2Host *script.Host, input *L2GenesisInput) error { ++ l2Host.SetEnvVar("L2GENESIS_L1CrossDomainMessengerProxy", input.L1Deployments.L1CrossDomainMessengerProxy.String()) ++ l2Host.SetEnvVar("L2GENESIS_L1StandardBridgeProxy", input.L1Deployments.L1StandardBridgeProxy.String()) ++ l2Host.SetEnvVar("L2GENESIS_L1ERC721BridgeProxy", input.L1Deployments.L1ERC721BridgeProxy.String()) ++ ++ deployConfig := &genesis.DeployConfig{ ++ L2InitializationConfig: input.L2Config, ++ } ++ cleanupDeployConfig, err := script.WithPrecompileAtAddress[*genesis.DeployConfig](l2Host, deployConfigAddr, deployConfig, script.WithFieldsOnly[*genesis.DeployConfig]) ++ if err != nil { ++ return fmt.Errorf("failed to insert DeployConfig precompile: %w", err) ++ } ++ defer cleanupDeployConfig() ++ ++ l2GenesisScript, cleanupL2Genesis, err := script.WithScript[L2GenesisScript](l2Host, "L2Genesis.s.sol", "L2Genesis") ++ if err != nil { ++ return fmt.Errorf("failed to load L2Genesis script: %w", err) ++ } ++ defer cleanupL2Genesis() ++ ++ if err := l2GenesisScript.RunWithEnv(); err != nil { ++ return fmt.Errorf("failed to run L2 genesis script: %w", err) ++ } ++ return nil ++}
@@ -9543,7 +51954,7 @@
@@ -9553,171 +51964,333 @@
-
+141
+
+305
-0
-
diff --git OP/packages/contracts-bedrock/snapshots/storageLayout/StableTokenV2.json CELO/packages/contracts-bedrock/snapshots/storageLayout/StableTokenV2.json +
diff --git OP/op-chain-ops/deployer/opcm/opchain.go CELO/op-chain-ops/deployer/opcm/opchain.go new file mode 100644 -index 0000000000000000000000000000000000000000..eea3cafe6e9025cb532486b1e9ff84f4246310ec +index 0000000000000000000000000000000000000000..c204c1a57ec3d967fd367976b641a0cb92929332 --- /dev/null -+++ CELO/packages/contracts-bedrock/snapshots/storageLayout/StableTokenV2.json -@@ -0,0 +1,142 @@ ++++ CELO/op-chain-ops/deployer/opcm/opchain.go +@@ -0,0 +1,305 @@ ++package opcm ++ ++import ( ++ "context" ++ "fmt" ++ "math/big" ++ "strings" ++ ++ "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/broadcaster" ++ "github.com/ethereum-optimism/optimism/op-chain-ops/foundry" ++ "github.com/ethereum-optimism/optimism/op-chain-ops/script" ++ "github.com/ethereum/go-ethereum/accounts/abi" ++ "github.com/ethereum/go-ethereum/common" ++ "github.com/ethereum/go-ethereum/common/hexutil" ++ "github.com/ethereum/go-ethereum/ethclient" ++ "github.com/holiman/uint256" ++) ++ ++// PermissionedGameStartingAnchorRoots is a root of bytes32(hex"dead") for the permissioned game at block 0, ++// and no root for the permissionless game. ++var PermissionedGameStartingAnchorRoots = []byte{ ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xde, 0xad, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++} ++ ++type DeployOPChainInput struct { ++ OpChainProxyAdminOwner common.Address ++ SystemConfigOwner common.Address ++ Batcher common.Address ++ UnsafeBlockSigner common.Address ++ Proposer common.Address ++ Challenger common.Address ++ ++ BasefeeScalar uint32 ++ BlobBaseFeeScalar uint32 ++ L2ChainId *big.Int ++ OpcmProxy common.Address ++} ++ ++func (input *DeployOPChainInput) InputSet() bool { ++ return true ++} ++ ++func (input *DeployOPChainInput) StartingAnchorRoots() []byte { ++ return PermissionedGameStartingAnchorRoots ++} ++ ++type DeployOPChainOutput struct { ++ OpChainProxyAdmin common.Address ++ AddressManager common.Address ++ L1ERC721BridgeProxy common.Address ++ SystemConfigProxy common.Address ++ OptimismMintableERC20FactoryProxy common.Address ++ L1StandardBridgeProxy common.Address ++ L1CrossDomainMessengerProxy common.Address ++ // Fault proof contracts below. ++ OptimismPortalProxy common.Address ++ DisputeGameFactoryProxy common.Address ++ AnchorStateRegistryProxy common.Address ++ AnchorStateRegistryImpl common.Address ++ FaultDisputeGame common.Address ++ PermissionedDisputeGame common.Address ++ DelayedWETHPermissionedGameProxy common.Address ++ DelayedWETHPermissionlessGameProxy common.Address ++} ++ ++func (output *DeployOPChainOutput) CheckOutput(input common.Address) error { ++ return nil ++} ++ ++type DeployOPChainScript struct { ++ Run func(input, output common.Address) error ++} ++ ++func DeployOPChain(host *script.Host, input DeployOPChainInput) (DeployOPChainOutput, error) { ++ var dco DeployOPChainOutput ++ inputAddr := host.NewScriptAddress() ++ outputAddr := host.NewScriptAddress() ++ ++ cleanupInput, err := script.WithPrecompileAtAddress[*DeployOPChainInput](host, inputAddr, &input) ++ if err != nil { ++ return dco, fmt.Errorf("failed to insert DeployOPChainInput precompile: %w", err) ++ } ++ defer cleanupInput() ++ host.Label(inputAddr, "DeployOPChainInput") ++ ++ cleanupOutput, err := script.WithPrecompileAtAddress[*DeployOPChainOutput](host, outputAddr, &dco, ++ script.WithFieldSetter[*DeployOPChainOutput]) ++ if err != nil { ++ return dco, fmt.Errorf("failed to insert DeployOPChainOutput precompile: %w", err) ++ } ++ defer cleanupOutput() ++ host.Label(outputAddr, "DeployOPChainOutput") ++ ++ deployScript, cleanupDeploy, err := script.WithScript[DeployOPChainScript](host, "DeployOPChain.s.sol", "DeployOPChain") ++ if err != nil { ++ return dco, fmt.Errorf("failed to load DeployOPChain script: %w", err) ++ } ++ defer cleanupDeploy() ++ ++ if err := deployScript.Run(inputAddr, outputAddr); err != nil { ++ return dco, fmt.Errorf("failed to run DeployOPChain script: %w", err) ++ } ++ ++ return dco, nil ++} ++ ++// opcmRoles is an internal struct used to pass the roles to OPSM. See opcmDeployInput for more info. ++type opcmRoles struct { ++ OpChainProxyAdminOwner common.Address ++ SystemConfigOwner common.Address ++ Batcher common.Address ++ UnsafeBlockSigner common.Address ++ Proposer common.Address ++ Challenger common.Address ++} ++ ++// opcmDeployInput is the input struct for the deploy method of the OPStackManager contract. We ++// define a separate struct here to match what the OPSM contract expects. ++type opcmDeployInput struct { ++ Roles opcmRoles ++ BasefeeScalar uint32 ++ BlobBasefeeScalar uint32 ++ L2ChainId *big.Int ++ StartingAnchorRoots []byte ++} ++ ++// decodeOutputABIJSON defines an ABI for a fake method called "decodeOutput" that returns the ++// DeployOutput struct. This allows the code in the deployer to decode directly into a struct ++// using Geth's ABI library. ++const decodeOutputABIJSON = ` +[ + { -+ "bytes": "1", -+ "label": "_initialized", -+ "offset": 0, -+ "slot": "0", -+ "type": "uint8" -+ }, -+ { -+ "bytes": "1", -+ "label": "_initializing", -+ "offset": 1, -+ "slot": "0", -+ "type": "bool" -+ }, -+ { -+ "bytes": "1600", -+ "label": "__gap", -+ "offset": 0, -+ "slot": "1", -+ "type": "uint256[50]" -+ }, -+ { -+ "bytes": "32", -+ "label": "_balances", -+ "offset": 0, -+ "slot": "51", -+ "type": "mapping(address => uint256)" -+ }, -+ { -+ "bytes": "32", -+ "label": "_allowances", -+ "offset": 0, -+ "slot": "52", -+ "type": "mapping(address => mapping(address => uint256))" -+ }, -+ { -+ "bytes": "32", -+ "label": "_totalSupply", -+ "offset": 0, -+ "slot": "53", -+ "type": "uint256" -+ }, -+ { -+ "bytes": "32", -+ "label": "_name", -+ "offset": 0, -+ "slot": "54", -+ "type": "string" -+ }, -+ { -+ "bytes": "32", -+ "label": "_symbol", -+ "offset": 0, -+ "slot": "55", -+ "type": "string" -+ }, -+ { -+ "bytes": "1440", -+ "label": "__gap", -+ "offset": 0, -+ "slot": "56", -+ "type": "uint256[45]" -+ }, -+ { -+ "bytes": "32", -+ "label": "_HASHED_NAME", -+ "offset": 0, -+ "slot": "101", -+ "type": "bytes32" -+ }, -+ { -+ "bytes": "32", -+ "label": "_HASHED_VERSION", -+ "offset": 0, -+ "slot": "102", -+ "type": "bytes32" -+ }, -+ { -+ "bytes": "1600", -+ "label": "__gap", -+ "offset": 0, -+ "slot": "103", -+ "type": "uint256[50]" -+ }, -+ { -+ "bytes": "32", -+ "label": "_nonces", -+ "offset": 0, -+ "slot": "153", -+ "type": "mapping(address => struct CountersUpgradeable.Counter)" -+ }, -+ { -+ "bytes": "32", -+ "label": "_PERMIT_TYPEHASH_DEPRECATED_SLOT", -+ "offset": 0, -+ "slot": "154", -+ "type": "bytes32" -+ }, -+ { -+ "bytes": "1568", -+ "label": "__gap", -+ "offset": 0, -+ "slot": "155", -+ "type": "uint256[49]" -+ }, -+ { -+ "bytes": "20", -+ "label": "_owner", -+ "offset": 0, -+ "slot": "204", -+ "type": "address" -+ }, -+ { -+ "bytes": "1568", -+ "label": "__gap", -+ "offset": 0, -+ "slot": "205", -+ "type": "uint256[49]" -+ }, -+ { -+ "bytes": "20", -+ "label": "validators", -+ "offset": 0, -+ "slot": "254", -+ "type": "address" -+ }, -+ { -+ "bytes": "20", -+ "label": "broker", -+ "offset": 0, -+ "slot": "255", -+ "type": "address" -+ }, -+ { -+ "bytes": "20", -+ "label": "exchange", -+ "offset": 0, -+ "slot": "256", -+ "type": "address" ++ "type": "function", ++ "name": "decodeOutput", ++ "inputs": [], ++ "outputs": [ ++ { ++ "name": "output", ++ "indexed": false, ++ "type": "tuple", ++ "components": [ ++ { ++ "name": "opChainProxyAdmin", ++ "type": "address" ++ }, ++ { ++ "name": "addressManager", ++ "type": "address" ++ }, ++ { ++ "name": "l1ERC721BridgeProxy", ++ "type": "address" ++ }, ++ { ++ "name": "systemConfigProxy", ++ "type": "address" ++ }, ++ { ++ "name": "optimismMintableERC20FactoryProxy", ++ "type": "address" ++ }, ++ { ++ "name": "l1StandardBridgeProxy", ++ "type": "address" ++ }, ++ { ++ "name": "l1CrossDomainMessengerProxy", ++ "type": "address" ++ }, ++ { ++ "name": "optimismPortalProxy", ++ "type": "address" ++ }, ++ { ++ "name": "disputeGameFactoryProxy", ++ "type": "address" ++ }, ++ { ++ "name": "anchorStateRegistryProxy", ++ "type": "address" ++ }, ++ { ++ "name": "anchorStateRegistryImpl", ++ "type": "address" ++ }, ++ { ++ "name": "faultDisputeGame", ++ "type": "address", ++ "internalType": "contract FaultDisputeGame" ++ }, ++ { ++ "name": "permissionedDisputeGame", ++ "type": "address" ++ }, ++ { ++ "name": "delayedWETHPermissionedGameProxy", ++ "type": "address" ++ }, ++ { ++ "name": "delayedWETHPermissionlessGameProxy", ++ "type": "address" ++ } ++ ] ++ } ++ ] + } +] -\ No newline at end of file
++` ++ ++var decodeOutputABI abi.ABI ++ ++// DeployOPChainRaw deploys an OP Chain using a raw call to a pre-deployed OPSM contract. ++func DeployOPChainRaw( ++ ctx context.Context, ++ l1 *ethclient.Client, ++ bcast broadcaster.Broadcaster, ++ deployer common.Address, ++ artifacts foundry.StatDirFs, ++ input DeployOPChainInput, ++) (DeployOPChainOutput, error) { ++ var out DeployOPChainOutput ++ ++ artifactsFS := &foundry.ArtifactsFS{FS: artifacts} ++ opcmArtifacts, err := artifactsFS.ReadArtifact("OPContractsManager.sol", "OPContractsManager") ++ if err != nil { ++ return out, fmt.Errorf("failed to read OPStackManager artifact: %w", err) ++ } ++ ++ opcmABI := opcmArtifacts.ABI ++ calldata, err := opcmABI.Pack("deploy", opcmDeployInput{ ++ Roles: opcmRoles{ ++ OpChainProxyAdminOwner: input.OpChainProxyAdminOwner, ++ SystemConfigOwner: input.SystemConfigOwner, ++ Batcher: input.Batcher, ++ UnsafeBlockSigner: input.UnsafeBlockSigner, ++ Proposer: input.Proposer, ++ Challenger: input.Challenger, ++ }, ++ BasefeeScalar: input.BasefeeScalar, ++ BlobBasefeeScalar: input.BlobBaseFeeScalar, ++ L2ChainId: input.L2ChainId, ++ StartingAnchorRoots: input.StartingAnchorRoots(), ++ }) ++ if err != nil { ++ return out, fmt.Errorf("failed to pack deploy input: %w", err) ++ } ++ ++ nonce, err := l1.NonceAt(ctx, deployer, nil) ++ if err != nil { ++ return out, fmt.Errorf("failed to read nonce: %w", err) ++ } ++ ++ bcast.Hook(script.Broadcast{ ++ From: deployer, ++ To: input.OpcmProxy, ++ Input: calldata, ++ Value: (*hexutil.U256)(uint256.NewInt(0)), ++ // use hardcoded 19MM gas for now since this is roughly what we've seen this deployment cost. ++ GasUsed: 19_000_000, ++ Type: script.BroadcastCall, ++ Nonce: nonce, ++ }) ++ ++ results, err := bcast.Broadcast(ctx) ++ if err != nil { ++ return out, fmt.Errorf("failed to broadcast OP chain deployment: %w", err) ++ } ++ ++ deployedEvent := opcmABI.Events["Deployed"] ++ res := results[0] ++ ++ for _, log := range res.Receipt.Logs { ++ if log.Topics[0] != deployedEvent.ID { ++ continue ++ } ++ ++ type EventData struct { ++ DeployOutput []byte ++ } ++ var data EventData ++ if err := opcmABI.UnpackIntoInterface(&data, "Deployed", log.Data); err != nil { ++ return out, fmt.Errorf("failed to unpack Deployed event: %w", err) ++ } ++ ++ type OutputData struct { ++ Output DeployOPChainOutput ++ } ++ var outData OutputData ++ if err := decodeOutputABI.UnpackIntoInterface(&outData, "decodeOutput", data.DeployOutput); err != nil { ++ return out, fmt.Errorf("failed to unpack DeployOutput: %w", err) ++ } ++ ++ return outData.Output, nil ++ } ++ ++ return out, fmt.Errorf("failed to find Deployed event") ++} ++ ++func init() { ++ var err error ++ decodeOutputABI, err = abi.JSON(strings.NewReader(decodeOutputABIJSON)) ++ if err != nil { ++ panic(fmt.Sprintf("failed to parse decodeOutput ABI: %v", err)) ++ } ++}
@@ -9732,7 +52305,7 @@
@@ -9742,66 +52315,75 @@
-
+36
+
+47
-0
-
diff --git OP/packages/contracts-bedrock/snapshots/storageLayout/UniswapFeeHandlerSeller.json CELO/packages/contracts-bedrock/snapshots/storageLayout/UniswapFeeHandlerSeller.json +
diff --git OP/op-chain-ops/deployer/opcm/standard-versions.toml CELO/op-chain-ops/deployer/opcm/standard-versions.toml new file mode 100644 -index 0000000000000000000000000000000000000000..3688a3204dec12dbace7b35435f8d85cb1c9acb3 +index 0000000000000000000000000000000000000000..cb4d336a7336463ef8baabd8479599f272a74f1f --- /dev/null -+++ CELO/packages/contracts-bedrock/snapshots/storageLayout/UniswapFeeHandlerSeller.json -@@ -0,0 +1,37 @@ -+[ -+ { -+ "bytes": "20", -+ "label": "_owner", -+ "offset": 0, -+ "slot": "0", -+ "type": "address" -+ }, -+ { -+ "bytes": "1", -+ "label": "initialized", -+ "offset": 20, -+ "slot": "0", -+ "type": "bool" -+ }, -+ { -+ "bytes": "20", -+ "label": "registry", -+ "offset": 0, -+ "slot": "1", -+ "type": "contract ICeloRegistry" -+ }, -+ { -+ "bytes": "32", -+ "label": "minimumReports", -+ "offset": 0, -+ "slot": "2", -+ "type": "mapping(address => uint256)" -+ }, -+ { -+ "bytes": "32", -+ "label": "routerAddresses", -+ "offset": 0, -+ "slot": "3", -+ "type": "mapping(address => struct EnumerableSet.AddressSet)" -+ } -+] -\ No newline at end of file
++++ CELO/op-chain-ops/deployer/opcm/standard-versions.toml +@@ -0,0 +1,47 @@ ++standard_release = "op-contracts/v1.6.0" ++ ++[releases] ++ ++# Contracts which are ++# * unproxied singletons: specify a standard "address" ++# * proxied : specify a standard "implementation_address" ++# * neither : specify neither a standard "address" nor "implementation_address" ++ ++# Fault Proofs https://github.com/ethereum-optimism/optimism/releases/tag/op-contracts%2Fv1.6.0 ++[releases."op-contracts/v1.6.0"] ++optimism_portal = { version = "3.10.0", implementation_address = "0xe2F826324b2faf99E513D16D266c3F80aE87832B" } ++system_config = { version = "2.2.0", implementation_address = "0xF56D96B2535B932656d3c04Ebf51baBff241D886" } ++anchor_state_registry = { version = "2.0.0" } ++delayed_weth = { version = "1.1.0", implementation_address = "0x71e966Ae981d1ce531a7b6d23DC0f27B38409087" } ++dispute_game_factory = { version = "1.0.0", implementation_address = "0xc641A33cab81C559F2bd4b21EA34C290E2440C2B" } ++fault_dispute_game = { version = "1.3.0" } ++permissioned_dispute_game = { version = "1.3.0" } ++mips = { version = "1.1.0", address = "0x16e83cE5Ce29BF90AD9Da06D2fE6a15d5f344ce4" } ++preimage_oracle = { version = "1.1.2", address = "0x9c065e11870B891D214Bc2Da7EF1f9DDFA1BE277" } ++l1_cross_domain_messenger = { version = "2.3.0", implementation_address = "0xD3494713A5cfaD3F5359379DfA074E2Ac8C6Fd65" } ++l1_erc721_bridge = { version = "2.1.0", implementation_address = "0xAE2AF01232a6c4a4d3012C5eC5b1b35059caF10d" } ++l1_standard_bridge = { version = "2.1.0", implementation_address = "0x64B5a5Ed26DCb17370Ff4d33a8D503f0fbD06CfF" } ++# l2_output_oracle -- This contract not used in fault proofs ++optimism_mintable_erc20_factory = { version = "1.9.0", implementation_address = "0xE01efbeb1089D1d1dB9c6c8b135C934C0734c846" } ++ ++# Fault Proofs https://github.com/ethereum-optimism/optimism/releases/tag/op-contracts%2Fv1.4.0 ++[releases."op-contracts/v1.4.0"] ++optimism_portal = { version = "3.10.0", implementation_address = "0xe2F826324b2faf99E513D16D266c3F80aE87832B" } ++system_config = { version = "2.2.0", implementation_address = "0xF56D96B2535B932656d3c04Ebf51baBff241D886" } ++anchor_state_registry = { version = "1.0.0" } ++delayed_weth = { version = "1.0.0", implementation_address = "0x97988d5624F1ba266E1da305117BCf20713bee08" } ++dispute_game_factory = { version = "1.0.0", implementation_address = "0xc641A33cab81C559F2bd4b21EA34C290E2440C2B" } ++fault_dispute_game = { version = "1.2.0" } ++permissioned_dispute_game = { version = "1.2.0" } ++mips = { version = "1.0.1", address = "0x0f8EdFbDdD3c0256A80AD8C0F2560B1807873C9c" } ++preimage_oracle = { version = "1.0.0", address = "0xD326E10B8186e90F4E2adc5c13a2d0C137ee8b34" } ++ ++# MCP https://github.com/ethereum-optimism/optimism/releases/tag/op-contracts%2Fv1.3.0 ++[releases."op-contracts/v1.3.0"] ++l1_cross_domain_messenger = { version = "2.3.0", implementation_address = "0xD3494713A5cfaD3F5359379DfA074E2Ac8C6Fd65" } ++l1_erc721_bridge = { version = "2.1.0", implementation_address = "0xAE2AF01232a6c4a4d3012C5eC5b1b35059caF10d" } ++l1_standard_bridge = { version = "2.1.0", implementation_address = "0x64B5a5Ed26DCb17370Ff4d33a8D503f0fbD06CfF" } ++l2_output_oracle = { version = "1.8.0", implementation_address = "0xF243BEd163251380e78068d317ae10f26042B292" } ++optimism_mintable_erc20_factory = { version = "1.9.0", implementation_address = "0xE01efbeb1089D1d1dB9c6c8b135C934C0734c846" } ++optimism_portal = { version = "2.5.0", implementation_address = "0x2D778797049FE9259d947D1ED8e5442226dFB589" } ++system_config = { version = "1.12.0", implementation_address = "0xba2492e52F45651B60B8B38d4Ea5E2390C64Ffb1" }
@@ -9816,7 +52398,7 @@
@@ -9826,45 +52408,36 @@
-
+15
+
+8
-0
-
diff --git OP/packages/contracts-bedrock/snapshots/storageLayout/UsingRegistry.json CELO/packages/contracts-bedrock/snapshots/storageLayout/UsingRegistry.json +
diff --git OP/op-chain-ops/deployer/opcm/standard.go CELO/op-chain-ops/deployer/opcm/standard.go new file mode 100644 -index 0000000000000000000000000000000000000000..fb89bbc7e1ab3904137e39358de306a828c60dac +index 0000000000000000000000000000000000000000..9f182ca4685c90549e278b10d497a3ac2e403b83 --- /dev/null -+++ CELO/packages/contracts-bedrock/snapshots/storageLayout/UsingRegistry.json -@@ -0,0 +1,16 @@ -+[ -+ { -+ "bytes": "20", -+ "label": "_owner", -+ "offset": 0, -+ "slot": "0", -+ "type": "address" -+ }, -+ { -+ "bytes": "20", -+ "label": "registry", -+ "offset": 0, -+ "slot": "1", -+ "type": "contract ICeloRegistry" -+ } -+] -\ No newline at end of file
++++ CELO/op-chain-ops/deployer/opcm/standard.go +@@ -0,0 +1,8 @@ ++package opcm ++ ++import "embed" ++ ++//go:embed standard-versions.toml ++var StandardVersionsData string ++ ++var _ embed.FS
@@ -9879,7 +52452,7 @@
@@ -9889,63 +52462,107 @@
-
+45
+
+89
-0
-
diff --git OP/packages/contracts-bedrock/src/celo/AbstractFeeCurrency.sol CELO/packages/contracts-bedrock/src/celo/AbstractFeeCurrency.sol +
diff --git OP/op-chain-ops/deployer/opcm/superchain.go CELO/op-chain-ops/deployer/opcm/superchain.go new file mode 100644 -index 0000000000000000000000000000000000000000..f67beaaf59a55ff6fc4022443b1179459a8bacbf +index 0000000000000000000000000000000000000000..4f648bbfa8a36fcbe955f809f338ebc7d5226eb0 --- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/AbstractFeeCurrency.sol -@@ -0,0 +1,45 @@ -+// SPDX-License-Identifier: MIT -+pragma solidity ^0.8.15; ++++ CELO/op-chain-ops/deployer/opcm/superchain.go +@@ -0,0 +1,89 @@ ++package opcm + -+import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; ++import ( ++ "fmt" ++ "math/big" + -+abstract contract AbstractFeeCurrency is ERC20 { -+ modifier onlyVm() { -+ require(msg.sender == address(0), "Only VM can call"); -+ _; -+ } ++ "github.com/ethereum-optimism/optimism/op-chain-ops/foundry" ++ "github.com/ethereum-optimism/optimism/op-chain-ops/script" ++ opcrypto "github.com/ethereum-optimism/optimism/op-service/crypto" ++ "github.com/ethereum/go-ethereum/common" ++ "github.com/ethereum/go-ethereum/ethclient" ++ "github.com/ethereum/go-ethereum/log" ++ "github.com/ethereum/go-ethereum/params" ++) + -+ function debitGasFees(address from, uint256 value) external onlyVm { -+ _burn(from, value); -+ } ++type DeploySuperchainInput struct { ++ SuperchainProxyAdminOwner common.Address `toml:"superchainProxyAdminOwner"` ++ ProtocolVersionsOwner common.Address `toml:"protocolVersionsOwner"` ++ Guardian common.Address `toml:"guardian"` ++ Paused bool `toml:"paused"` ++ RequiredProtocolVersion params.ProtocolVersion `toml:"requiredProtocolVersion"` ++ RecommendedProtocolVersion params.ProtocolVersion `toml:"recommendedProtocolVersion"` ++} + -+ // New function signature, will be used when all fee currencies have migrated -+ function creditGasFees(address[] calldata recipients, uint256[] calldata amounts) public onlyVm { -+ require(recipients.length == amounts.length, "Recipients and amounts must be the same length."); ++func (dsi *DeploySuperchainInput) InputSet() bool { ++ return true ++} + -+ for (uint256 i = 0; i < recipients.length; i++) { -+ _mint(recipients[i], amounts[i]); -+ } -+ } ++type DeploySuperchainOutput struct { ++ SuperchainProxyAdmin common.Address ++ SuperchainConfigImpl common.Address ++ SuperchainConfigProxy common.Address ++ ProtocolVersionsImpl common.Address ++ ProtocolVersionsProxy common.Address ++} + -+ // Old function signature for backwards compatibility -+ function creditGasFees( -+ address from, -+ address feeRecipient, -+ address, // gatewayFeeRecipient, unused -+ address communityFund, -+ uint256 refund, -+ uint256 tipTxFee, -+ uint256, // gatewayFee, unused -+ uint256 baseTxFee -+ ) -+ public -+ onlyVm -+ { -+ // Calling the new creditGasFees would make sense here, but that is not -+ // possible due to its calldata arguments. -+ _mint(from, refund); -+ _mint(feeRecipient, tipTxFee); -+ _mint(communityFund, baseTxFee); -+ } ++func (output *DeploySuperchainOutput) CheckOutput(input common.Address) error { ++ return nil ++} ++ ++type DeploySuperchainScript struct { ++ Run func(in common.Address, out common.Address) error ++} ++ ++type DeploySuperchainOpts struct { ++ ChainID *big.Int ++ ArtifactsFS foundry.StatDirFs ++ Deployer common.Address ++ Signer opcrypto.SignerFn ++ Input DeploySuperchainInput ++ Client *ethclient.Client ++ Logger log.Logger ++} ++ ++func DeploySuperchain(h *script.Host, input DeploySuperchainInput) (DeploySuperchainOutput, error) { ++ var dso DeploySuperchainOutput ++ ++ inputAddr := h.NewScriptAddress() ++ outputAddr := h.NewScriptAddress() ++ ++ cleanupInput, err := script.WithPrecompileAtAddress[*DeploySuperchainInput](h, inputAddr, &input) ++ if err != nil { ++ return dso, fmt.Errorf("failed to insert DeploySuperchainInput precompile: %w", err) ++ } ++ defer cleanupInput() ++ ++ cleanupOutput, err := script.WithPrecompileAtAddress[*DeploySuperchainOutput]( ++ h, ++ outputAddr, ++ &dso, ++ script.WithFieldSetter[*DeploySuperchainOutput], ++ ) ++ if err != nil { ++ return dso, fmt.Errorf("failed to insert DeploySuperchainOutput precompile: %w", err) ++ } ++ defer cleanupOutput() ++ ++ deployScript, cleanupDeploy, err := script.WithScript[DeploySuperchainScript](h, "DeploySuperchain.s.sol", "DeploySuperchain") ++ if err != nil { ++ return dso, fmt.Errorf("failed to load DeploySuperchain script: %w", err) ++ } ++ defer cleanupDeploy() ++ ++ if err := deployScript.Run(inputAddr, outputAddr); err != nil { ++ return dso, fmt.Errorf("failed to run DeploySuperchain script: %w", err) ++ } ++ ++ return dso, nil +}
@@ -9953,9 +52570,9 @@
@@ -9970,7 +52587,7 @@
@@ -9980,27 +52597,156 @@
-
+9
+
+138
-0
-
diff --git OP/packages/contracts-bedrock/src/celo/CalledByVm.sol CELO/packages/contracts-bedrock/src/celo/CalledByVm.sol +
diff --git OP/op-chain-ops/deployer/pipeline/downloader.go CELO/op-chain-ops/deployer/pipeline/downloader.go new file mode 100644 -index 0000000000000000000000000000000000000000..c3f6efe12072ef8c87e213f9c29b0789c26cff0f +index 0000000000000000000000000000000000000000..8932792f822ffbebb6977299c8bc3a37e13d9c48 --- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/CalledByVm.sol -@@ -0,0 +1,9 @@ -+// SPDX-License-Identifier: LGPL-3.0-only -+pragma solidity ^0.8.15; ++++ CELO/op-chain-ops/deployer/pipeline/downloader.go +@@ -0,0 +1,138 @@ ++package pipeline + -+contract CalledByVm { -+ modifier onlyVm() { -+ require(msg.sender == address(0), "Only VM can call"); -+ _; -+ } ++import ( ++ "archive/tar" ++ "bufio" ++ "compress/gzip" ++ "context" ++ "errors" ++ "fmt" ++ "io" ++ "net/http" ++ "net/url" ++ "os" ++ "path" ++ "strings" ++ "time" ++ ++ "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/state" ++ "github.com/ethereum-optimism/optimism/op-chain-ops/foundry" ++) ++ ++var ErrUnsupportedArtifactsScheme = errors.New("unsupported artifacts URL scheme") ++ ++type DownloadProgressor func(current, total int64) ++ ++type CleanupFunc func() error ++ ++var noopCleanup = func() error { return nil } ++ ++func DownloadArtifacts(ctx context.Context, artifactsURL *state.ArtifactsURL, progress DownloadProgressor) (foundry.StatDirFs, CleanupFunc, error) { ++ switch artifactsURL.Scheme { ++ case "http", "https": ++ req, err := http.NewRequestWithContext(ctx, http.MethodGet, (*url.URL)(artifactsURL).String(), nil) ++ if err != nil { ++ return nil, nil, fmt.Errorf("failed to create request: %w", err) ++ } ++ ++ resp, err := http.DefaultClient.Do(req) ++ if err != nil { ++ return nil, nil, fmt.Errorf("failed to download artifacts: %w", err) ++ } ++ defer resp.Body.Close() ++ ++ if resp.StatusCode != http.StatusOK { ++ return nil, nil, fmt.Errorf("failed to download artifacts: invalid status code %s", resp.Status) ++ } ++ ++ tmpDir, err := os.MkdirTemp("", "op-deployer-artifacts-*") ++ if err != nil { ++ return nil, nil, fmt.Errorf("failed to create temp dir: %w", err) ++ } ++ ++ pr := &progressReader{ ++ r: resp.Body, ++ progress: progress, ++ total: resp.ContentLength, ++ } ++ ++ gr, err := gzip.NewReader(pr) ++ if err != nil { ++ return nil, nil, fmt.Errorf("failed to create gzip reader: %w", err) ++ } ++ defer gr.Close() ++ ++ tr := tar.NewReader(gr) ++ if err := untar(tmpDir, tr); err != nil { ++ return nil, nil, fmt.Errorf("failed to untar: %w", err) ++ } ++ ++ fs := os.DirFS(path.Join(tmpDir, "forge-artifacts")) ++ cleanup := func() error { ++ return os.RemoveAll(tmpDir) ++ } ++ return fs.(foundry.StatDirFs), cleanup, nil ++ case "file": ++ fs := os.DirFS(artifactsURL.Path) ++ return fs.(foundry.StatDirFs), noopCleanup, nil ++ default: ++ return nil, nil, ErrUnsupportedArtifactsScheme ++ } ++} ++ ++type progressReader struct { ++ r io.Reader ++ progress DownloadProgressor ++ curr int64 ++ total int64 ++ lastPrint time.Time ++} ++ ++func (pr *progressReader) Read(p []byte) (int, error) { ++ ++ n, err := pr.r.Read(p) ++ pr.curr += int64(n) ++ if pr.progress != nil && time.Since(pr.lastPrint) > 1*time.Second { ++ pr.progress(pr.curr, pr.total) ++ pr.lastPrint = time.Now() ++ } ++ return n, err ++} ++ ++func untar(dir string, tr *tar.Reader) error { ++ for { ++ hdr, err := tr.Next() ++ if err == io.EOF { ++ return nil ++ } ++ if err != nil { ++ return fmt.Errorf("failed to read tar header: %w", err) ++ } ++ ++ cleanedName := path.Clean(hdr.Name) ++ if strings.Contains(cleanedName, "..") { ++ return fmt.Errorf("invalid file path: %s", hdr.Name) ++ } ++ dst := path.Join(dir, cleanedName) ++ if hdr.FileInfo().IsDir() { ++ if err := os.MkdirAll(dst, 0o755); err != nil { ++ return fmt.Errorf("failed to create directory: %w", err) ++ } ++ continue ++ } ++ ++ f, err := os.Create(dst) ++ buf := bufio.NewWriter(f) ++ if err != nil { ++ return fmt.Errorf("failed to create file: %w", err) ++ } ++ if _, err := io.Copy(buf, tr); err != nil { ++ _ = f.Close() ++ return fmt.Errorf("failed to write file: %w", err) ++ } ++ if err := buf.Flush(); err != nil { ++ return fmt.Errorf("failed to flush buffer: %w", err) ++ } ++ _ = f.Close() ++ } +}
@@ -10008,9 +52754,9 @@
@@ -10025,7 +52771,7 @@
@@ -10035,55 +52781,60 @@
-
+37
+
+42
-0
-
diff --git OP/packages/contracts-bedrock/src/celo/CeloPredeploys.sol CELO/packages/contracts-bedrock/src/celo/CeloPredeploys.sol +
diff --git OP/op-chain-ops/deployer/pipeline/downloader_test.go CELO/op-chain-ops/deployer/pipeline/downloader_test.go new file mode 100644 -index 0000000000000000000000000000000000000000..8c34e606808b68139b9ee3e7242d1476bf2d2f9e +index 0000000000000000000000000000000000000000..277409461a41ef3d4366e3019843295bc0b64996 --- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/CeloPredeploys.sol -@@ -0,0 +1,37 @@ -+// SPDX-License-Identifier: MIT -+pragma solidity ^0.8.0; ++++ CELO/op-chain-ops/deployer/pipeline/downloader_test.go +@@ -0,0 +1,42 @@ ++package pipeline + -+import { console2 as console } from "forge-std/console2.sol"; ++import ( ++ "context" ++ "io" ++ "net/http" ++ "net/http/httptest" ++ "net/url" ++ "os" ++ "testing" + -+/// @title CeloPredeploys -+/// @notice Contains constant addresses for protocol contracts that are pre-deployed to the L2 system. -+library CeloPredeploys { -+ address internal constant CELO_REGISTRY = 0x000000000000000000000000000000000000ce10; -+ address internal constant GOLD_TOKEN = 0x471EcE3750Da237f93B8E339c536989b8978a438; -+ address internal constant FEE_HANDLER = 0xcD437749E43A154C07F3553504c68fBfD56B8778; -+ address internal constant MENTO_FEE_HANDLER_SELLER = 0x4eFa274B7e33476C961065000D58ee09F7921A74; -+ address internal constant UNISWAP_FEE_HANDLER_SELLER = 0xD3aeE28548Dbb65DF03981f0dC0713BfCBd10a97; -+ address internal constant SORTED_ORACLES = 0xefB84935239dAcdecF7c5bA76d8dE40b077B7b33; -+ address internal constant ADDRESS_SORTED_LINKED_LIST_WITH_MEDIAN = 0xED477A99035d0c1e11369F1D7A4e587893cc002B; -+ address internal constant FEE_CURRENCY = 0x4200000000000000000000000000000000001022; -+ address internal constant FEE_CURRENCY_DIRECTORY = 0x4200000000000000000000000000000000001024; -+ address internal constant cUSD = 0x765DE816845861e75A25fCA122bb6898B8B1282a; ++ "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/state" ++ "github.com/stretchr/testify/require" ++) + -+ /// @notice Returns the name of the predeploy at the given address. -+ function getName(address _addr) internal pure returns (string memory out_) { -+ // require(isPredeployNamespace(_addr), "Predeploys: address must be a predeploy"); ++func TestDownloadArtifacts(t *testing.T) { ++ f, err := os.OpenFile("testdata/artifacts.tar.gz", os.O_RDONLY, 0o644) ++ require.NoError(t, err) ++ defer f.Close() + -+ if (_addr == CELO_REGISTRY) return "CeloRegistry"; -+ if (_addr == GOLD_TOKEN) return "GoldToken"; -+ if (_addr == FEE_HANDLER) return "FeeHandler"; -+ if (_addr == MENTO_FEE_HANDLER_SELLER) return "MentoFeeHandlerSeller"; -+ if (_addr == UNISWAP_FEE_HANDLER_SELLER) return "UniswapFeeHandlerSeller"; -+ if (_addr == SORTED_ORACLES) return "SortedOracles"; -+ if (_addr == ADDRESS_SORTED_LINKED_LIST_WITH_MEDIAN) return "AddressSortedLinkedListWithMedian"; -+ if (_addr == FEE_CURRENCY) return "FeeCurrency"; -+ if (_addr == FEE_CURRENCY_DIRECTORY) return "FeeCurrencyDirectory"; -+ if (_addr == cUSD) return "cUSD"; ++ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ++ w.WriteHeader(http.StatusOK) ++ _, err := io.Copy(w, f) ++ require.NoError(t, err) ++ })) ++ defer ts.Close() + -+ revert("Predeploys: unnamed predeploy"); -+ } ++ ctx := context.Background() ++ artifactsURL, err := url.Parse(ts.URL) ++ require.NoError(t, err) ++ ++ fs, cleanup, err := DownloadArtifacts(ctx, (*state.ArtifactsURL)(artifactsURL), nil) ++ require.NoError(t, err) ++ require.NotNil(t, fs) ++ defer func() { ++ require.NoError(t, cleanup()) ++ }() ++ ++ info, err := fs.Stat("WETH98.sol/WETH98.json") ++ require.NoError(t, err) ++ require.Greater(t, info.Size(), int64(0)) +}
@@ -10091,9 +52842,9 @@
@@ -10108,7 +52859,7 @@
@@ -10118,113 +52869,200 @@
-
+95
+
+49
-0
-
diff --git OP/packages/contracts-bedrock/src/celo/CeloRegistry.sol CELO/packages/contracts-bedrock/src/celo/CeloRegistry.sol +
diff --git OP/op-chain-ops/deployer/pipeline/env.go CELO/op-chain-ops/deployer/pipeline/env.go new file mode 100644 -index 0000000000000000000000000000000000000000..7da4cfb35ddfef5c49183c7c3523f658e071aa33 +index 0000000000000000000000000000000000000000..d0778122d27a165dc4c5fd8c507dc6c2f2df63ea --- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/CeloRegistry.sol -@@ -0,0 +1,95 @@ -+// SPDX-License-Identifier: MIT -+pragma solidity ^0.8.15; ++++ CELO/op-chain-ops/deployer/pipeline/env.go +@@ -0,0 +1,49 @@ ++package pipeline + -+import "../../lib/openzeppelin-contracts/contracts/access/Ownable.sol"; ++import ( ++ "context" ++ "fmt" ++ "path" + -+import "./interfaces/ICeloRegistry.sol"; -+import "./Initializable.sol"; ++ "github.com/ethereum-optimism/optimism/op-chain-ops/foundry" + -+/** -+ * @title Routes identifiers to addresses. -+ */ -+contract CeloRegistry is ICeloRegistry, Ownable, Initializable { -+ mapping(bytes32 => address) public registry; ++ "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/state" ++ opcrypto "github.com/ethereum-optimism/optimism/op-service/crypto" ++ "github.com/ethereum-optimism/optimism/op-service/jsonutil" ++ "github.com/ethereum/go-ethereum/common" ++ "github.com/ethereum/go-ethereum/ethclient" ++ "github.com/ethereum/go-ethereum/log" ++) + -+ event RegistryUpdated(string identifier, bytes32 indexed identifierHash, address indexed addr); ++type Env struct { ++ Workdir string ++ L1Client *ethclient.Client ++ Signer opcrypto.SignerFn ++ Deployer common.Address ++ Logger log.Logger ++} + -+ /** -+ * @notice Sets initialized == true on implementation contracts -+ * @param test Set to true to skip implementation initialization -+ */ -+ constructor(bool test) Initializable(test) { } ++func (e *Env) ReadIntent() (*state.Intent, error) { ++ intentPath := path.Join(e.Workdir, "intent.toml") ++ intent, err := jsonutil.LoadTOML[state.Intent](intentPath) ++ if err != nil { ++ return nil, fmt.Errorf("failed to read intent file: %w", err) ++ } ++ return intent, nil ++} + -+ /** -+ * @notice Used in place of the constructor to allow the contract to be upgradable via proxy. -+ */ -+ function initialize() external initializer { -+ _transferOwnership(msg.sender); -+ } ++func (e *Env) ReadState() (*state.State, error) { ++ statePath := path.Join(e.Workdir, "state.json") ++ st, err := jsonutil.LoadJSON[state.State](statePath) ++ if err != nil { ++ return nil, fmt.Errorf("failed to read state file: %w", err) ++ } ++ return st, nil ++} + -+ /** -+ * @notice Associates the given address with the given identifier. -+ * @param identifier Identifier of contract whose address we want to set. -+ * @param addr Address of contract. -+ */ -+ function setAddressFor(string calldata identifier, address addr) external onlyOwner { -+ bytes32 identifierHash = keccak256(abi.encodePacked(identifier)); -+ registry[identifierHash] = addr; -+ emit RegistryUpdated(identifier, identifierHash, addr); -+ } ++func (e *Env) WriteState(st *state.State) error { ++ statePath := path.Join(e.Workdir, "state.json") ++ return st.WriteToFile(statePath) ++} + -+ /** -+ * @notice Gets address associated with the given identifierHash. -+ * @param identifierHash Identifier hash of contract whose address we want to look up. -+ * @dev Throws if address not set. -+ */ -+ function getAddressForOrDie(bytes32 identifierHash) external view returns (address) { -+ require(registry[identifierHash] != address(0), "identifier has no registry entry"); -+ return registry[identifierHash]; -+ } ++type Stage func(ctx context.Context, env *Env, artifactsFS foundry.StatDirFs, intent *state.Intent, state2 *state.State) error
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+87
+
-0
+ +
+ +
+
+
diff --git OP/op-chain-ops/deployer/pipeline/host.go CELO/op-chain-ops/deployer/pipeline/host.go +new file mode 100644 +index 0000000000000000000000000000000000000000..71bc9e29e05c3bd25279ffefd47eea89c22f9b45 +--- /dev/null ++++ CELO/op-chain-ops/deployer/pipeline/host.go +@@ -0,0 +1,87 @@ ++package pipeline + -+ /** -+ * @notice Gets address associated with the given identifierHash. -+ * @param identifierHash Identifier hash of contract whose address we want to look up. -+ */ -+ function getAddressFor(bytes32 identifierHash) external view returns (address) { -+ return registry[identifierHash]; -+ } ++import ( ++ "context" ++ "fmt" ++ "math/big" + -+ /** -+ * @notice Gets address associated with the given identifier. -+ * @param identifier Identifier of contract whose address we want to look up. -+ * @dev Throws if address not set. -+ */ -+ function getAddressForStringOrDie(string calldata identifier) external view returns (address) { -+ bytes32 identifierHash = keccak256(abi.encodePacked(identifier)); -+ require(registry[identifierHash] != address(0), "identifier has no registry entry"); -+ return registry[identifierHash]; -+ } ++ "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/broadcaster" ++ "github.com/ethereum-optimism/optimism/op-chain-ops/foundry" ++ "github.com/ethereum-optimism/optimism/op-chain-ops/script" ++ opcrypto "github.com/ethereum-optimism/optimism/op-service/crypto" ++ "github.com/ethereum/go-ethereum/common" ++ "github.com/ethereum/go-ethereum/ethclient" ++ "github.com/ethereum/go-ethereum/log" ++) + -+ /** -+ * @notice Gets address associated with the given identifier. -+ * @param identifier Identifier of contract whose address we want to look up. -+ */ -+ function getAddressForString(string calldata identifier) external view returns (address) { -+ bytes32 identifierHash = keccak256(abi.encodePacked(identifier)); -+ return registry[identifierHash]; -+ } ++type BroadcasterFactory func(opts CallScriptBroadcastOpts) (broadcaster.Broadcaster, error) + -+ /** -+ * @notice Iterates over provided array of identifiers, getting the address for each. -+ * Returns true if `sender` matches the address of one of the provided identifiers. -+ * @param identifierHashes Array of hashes of approved identifiers. -+ * @param sender Address in question to verify membership. -+ * @return True if `sender` corresponds to the address of any of `identifiers` -+ * registry entries. -+ */ -+ function isOneOf(bytes32[] calldata identifierHashes, address sender) external view returns (bool) { -+ for (uint256 i = 0; i < identifierHashes.length; i++) { -+ if (registry[identifierHashes[i]] == sender) { -+ return true; -+ } -+ } -+ return false; -+ } ++func KeyedBroadcaster(opts CallScriptBroadcastOpts) (broadcaster.Broadcaster, error) { ++ return broadcaster.NewKeyedBroadcaster(broadcaster.KeyedBroadcasterOpts{ ++ Logger: opts.Logger, ++ ChainID: opts.L1ChainID, ++ Client: opts.Client, ++ Signer: opts.Signer, ++ From: opts.Deployer, ++ }) ++} ++ ++func DiscardBroadcaster(opts CallScriptBroadcastOpts) (broadcaster.Broadcaster, error) { ++ return broadcaster.DiscardBroadcaster(), nil ++} ++ ++type CallScriptBroadcastOpts struct { ++ L1ChainID *big.Int ++ Logger log.Logger ++ ArtifactsFS foundry.StatDirFs ++ Deployer common.Address ++ Signer opcrypto.SignerFn ++ Client *ethclient.Client ++ Handler func(host *script.Host) error ++ Broadcaster BroadcasterFactory ++} ++ ++func CallScriptBroadcast( ++ ctx context.Context, ++ opts CallScriptBroadcastOpts, ++) error { ++ bcaster, err := opts.Broadcaster(opts) ++ if err != nil { ++ return fmt.Errorf("failed to create broadcaster: %w", err) ++ } ++ ++ scriptCtx := script.DefaultContext ++ scriptCtx.Sender = opts.Deployer ++ scriptCtx.Origin = opts.Deployer ++ artifacts := &foundry.ArtifactsFS{FS: opts.ArtifactsFS} ++ h := script.NewHost( ++ opts.Logger, ++ artifacts, ++ nil, ++ scriptCtx, ++ script.WithBroadcastHook(bcaster.Hook), ++ script.WithIsolatedBroadcasts(), ++ script.WithCreate2Deployer(), ++ ) ++ ++ if err := h.EnableCheats(); err != nil { ++ return fmt.Errorf("failed to enable cheats: %w", err) ++ } ++ ++ nonce, err := opts.Client.NonceAt(ctx, opts.Deployer, nil) ++ if err != nil { ++ return fmt.Errorf("failed to fetch nonce: %w", err) ++ } ++ h.SetNonce(opts.Deployer, nonce) ++ ++ err = opts.Handler(h) ++ if err != nil { ++ return fmt.Errorf("failed to run handler: %w", err) ++ } ++ ++ if _, err := bcaster.Broadcast(ctx); err != nil { ++ return fmt.Errorf("failed to broadcast: %w", err) ++ } ++ ++ return nil +}
@@ -10232,9 +53070,9 @@
@@ -10249,7 +53087,7 @@
@@ -10259,33 +53097,113 @@
-
+15
+
+95
-0
-
diff --git OP/packages/contracts-bedrock/src/celo/CeloTokenL1.sol CELO/packages/contracts-bedrock/src/celo/CeloTokenL1.sol +
diff --git OP/op-chain-ops/deployer/pipeline/implementations.go CELO/op-chain-ops/deployer/pipeline/implementations.go new file mode 100644 -index 0000000000000000000000000000000000000000..8ef3fb5abd9bbf8355d72e95867827c7cb2d257e +index 0000000000000000000000000000000000000000..5c5a1e99287cc8c5bb2d866908ba8bd0f0ab8100 --- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/CeloTokenL1.sol -@@ -0,0 +1,15 @@ -+// SPDX-License-Identifier: MIT -+pragma solidity ^0.8.0; ++++ CELO/op-chain-ops/deployer/pipeline/implementations.go +@@ -0,0 +1,95 @@ ++package pipeline + -+import { ERC20Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol"; ++import ( ++ "context" ++ "fmt" ++ "math/big" + -+string constant NAME = "Celo native asset"; -+string constant SYMBOL = "CELO"; -+uint256 constant TOTAL_MARKET_CAP = 1000000000e18; // 1 billion CELO ++ "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/opcm" ++ "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/state" ++ "github.com/ethereum-optimism/optimism/op-chain-ops/foundry" ++ "github.com/ethereum-optimism/optimism/op-chain-ops/script" ++) + -+contract CeloTokenL1 is ERC20Upgradeable { -+ function initialize(address portalProxyAddress) public initializer { -+ __ERC20_init(NAME, SYMBOL); -+ _mint(portalProxyAddress, TOTAL_MARKET_CAP); -+ } ++func DeployImplementations(ctx context.Context, env *Env, artifactsFS foundry.StatDirFs, intent *state.Intent, st *state.State) error { ++ lgr := env.Logger.New("stage", "deploy-implementations") ++ ++ if !shouldDeployImplementations(intent, st) { ++ lgr.Info("implementations deployment not needed") ++ return nil ++ } ++ ++ lgr.Info("deploying implementations") ++ ++ var dump *foundry.ForgeAllocs ++ var dio opcm.DeployImplementationsOutput ++ var err error ++ err = CallScriptBroadcast( ++ ctx, ++ CallScriptBroadcastOpts{ ++ L1ChainID: big.NewInt(int64(intent.L1ChainID)), ++ Logger: lgr, ++ ArtifactsFS: artifactsFS, ++ Deployer: env.Deployer, ++ Signer: env.Signer, ++ Client: env.L1Client, ++ Broadcaster: KeyedBroadcaster, ++ Handler: func(host *script.Host) error { ++ host.SetEnvVar("IMPL_SALT", st.Create2Salt.Hex()[2:]) ++ host.ImportState(st.SuperchainDeployment.StateDump) ++ dio, err = opcm.DeployImplementations( ++ host, ++ opcm.DeployImplementationsInput{ ++ Salt: st.Create2Salt, ++ WithdrawalDelaySeconds: big.NewInt(604800), ++ MinProposalSizeBytes: big.NewInt(126000), ++ ChallengePeriodSeconds: big.NewInt(86400), ++ ProofMaturityDelaySeconds: big.NewInt(604800), ++ DisputeGameFinalityDelaySeconds: big.NewInt(302400), ++ Release: intent.ContractsRelease, ++ SuperchainConfigProxy: st.SuperchainDeployment.SuperchainConfigProxyAddress, ++ ProtocolVersionsProxy: st.SuperchainDeployment.ProtocolVersionsProxyAddress, ++ SuperchainProxyAdmin: st.SuperchainDeployment.ProxyAdminAddress, ++ StandardVersionsToml: opcm.StandardVersionsData, ++ UseInterop: false, ++ }, ++ ) ++ if err != nil { ++ return fmt.Errorf("error deploying implementations: %w", err) ++ } ++ dump, err = host.StateDump() ++ if err != nil { ++ return fmt.Errorf("error dumping state: %w", err) ++ } ++ return nil ++ }, ++ }, ++ ) ++ if err != nil { ++ return fmt.Errorf("error deploying implementations: %w", err) ++ } ++ ++ st.ImplementationsDeployment = &state.ImplementationsDeployment{ ++ OpcmProxyAddress: dio.OpcmProxy, ++ DelayedWETHImplAddress: dio.DelayedWETHImpl, ++ OptimismPortalImplAddress: dio.OptimismPortalImpl, ++ PreimageOracleSingletonAddress: dio.PreimageOracleSingleton, ++ MipsSingletonAddress: dio.MipsSingleton, ++ SystemConfigImplAddress: dio.SystemConfigImpl, ++ L1CrossDomainMessengerImplAddress: dio.L1CrossDomainMessengerImpl, ++ L1ERC721BridgeImplAddress: dio.L1ERC721BridgeImpl, ++ L1StandardBridgeImplAddress: dio.L1StandardBridgeImpl, ++ OptimismMintableERC20FactoryImplAddress: dio.OptimismMintableERC20FactoryImpl, ++ DisputeGameFactoryImplAddress: dio.DisputeGameFactoryImpl, ++ StateDump: dump, ++ } ++ if err := env.WriteState(st); err != nil { ++ return err ++ } ++ ++ return nil ++} ++ ++func shouldDeployImplementations(intent *state.Intent, st *state.State) bool { ++ return st.ImplementationsDeployment == nil +}
@@ -10293,9 +53211,9 @@
@@ -10310,7 +53228,7 @@
@@ -10320,109 +53238,138 @@
-
+91
+
+120
-0
-
diff --git OP/packages/contracts-bedrock/src/celo/FeeCurrencyDirectory.sol CELO/packages/contracts-bedrock/src/celo/FeeCurrencyDirectory.sol +
diff --git OP/op-chain-ops/deployer/pipeline/init.go CELO/op-chain-ops/deployer/pipeline/init.go new file mode 100644 -index 0000000000000000000000000000000000000000..21fc7ff3181a15e8d87b7f3ab89f713870197d48 +index 0000000000000000000000000000000000000000..a680c7fdb48f84ee751a2fcfd72b5476213f5e71 --- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/FeeCurrencyDirectory.sol -@@ -0,0 +1,91 @@ -+// SPDX-License-Identifier: MIT -+pragma solidity ^0.8.0; ++++ CELO/op-chain-ops/deployer/pipeline/init.go +@@ -0,0 +1,120 @@ ++package pipeline + -+import "./Initializable.sol"; -+import "./interfaces/IOracle.sol"; -+import "./interfaces/IFeeCurrencyDirectory.sol"; -+import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; ++import ( ++ "context" ++ "crypto/rand" ++ "fmt" + -+contract FeeCurrencyDirectory is IFeeCurrencyDirectory, Initializable, Ownable { -+ mapping(address => CurrencyConfig) public currencies; -+ address[] private currencyList; ++ "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/opcm" ++ "github.com/ethereum-optimism/optimism/op-chain-ops/foundry" + -+ constructor(bool test) Initializable(test) { } ++ "github.com/ethereum-optimism/optimism/op-chain-ops/script" + -+ /** -+ * @notice Initializes the contract with the owner set. -+ */ -+ function initialize() public initializer { -+ _transferOwnership(msg.sender); -+ } ++ "github.com/ethereum/go-ethereum/common" + -+ /** -+ * @notice Sets the currency configuration for a token. -+ * @dev This action can only be performed by the contract owner. -+ * @param token The token address. -+ * @param oracle The oracle address for price fetching. -+ * @param intrinsicGas The intrinsic gas value for transactions. -+ */ -+ function setCurrencyConfig(address token, address oracle, uint256 intrinsicGas) external onlyOwner { -+ require(oracle != address(0), "Oracle address cannot be zero"); -+ require(intrinsicGas > 0, "Intrinsic gas cannot be zero"); -+ require(currencies[token].oracle == address(0), "Currency already in the directory"); ++ "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/state" ++) + -+ currencies[token] = CurrencyConfig({ oracle: oracle, intrinsicGas: intrinsicGas }); -+ currencyList.push(token); -+ } ++func IsSupportedStateVersion(version int) bool { ++ return version == 1 ++} + -+ /** -+ * @notice Removes a token from the directory. -+ * @dev This action can only be performed by the contract owner. -+ * @param token The token address to remove. -+ * @param index The index in the list of directory currencies. -+ */ -+ function removeCurrencies(address token, uint256 index) external onlyOwner { -+ require(index < currencyList.length, "Index out of bounds"); -+ require(currencyList[index] == token, "Index does not match token"); ++func Init(ctx context.Context, env *Env, artifactsFS foundry.StatDirFs, intent *state.Intent, st *state.State) error { ++ lgr := env.Logger.New("stage", "init") ++ lgr.Info("initializing pipeline") + -+ delete currencies[token]; -+ currencyList[index] = currencyList[currencyList.length - 1]; -+ currencyList.pop(); -+ } ++ // Ensure the state version is supported. ++ if !IsSupportedStateVersion(st.Version) { ++ return fmt.Errorf("unsupported state version: %d", st.Version) ++ } + -+ /** -+ * @notice Returns the list of all currency addresses. -+ * @return An array of addresses. -+ */ -+ function getCurrencies() public view returns (address[] memory) { -+ return currencyList; -+ } ++ if st.Create2Salt == (common.Hash{}) { ++ _, err := rand.Read(st.Create2Salt[:]) ++ if err != nil { ++ return fmt.Errorf("failed to generate CREATE2 salt: %w", err) ++ } ++ } + -+ /** -+ * @notice Returns the configuration for a currency. -+ * @param token The address of the token. -+ * @return Currency configuration of the token. -+ */ -+ function getCurrencyConfig(address token) public view returns (CurrencyConfig memory) { -+ return currencies[token]; -+ } ++ if intent.OPCMAddress != (common.Address{}) { ++ env.Logger.Info("using provided OPCM address, populating state", "address", intent.OPCMAddress.Hex()) + -+ /** -+ * @notice Retrieves exchange rate between token and CELO. -+ * @param token The token address whose price is to be fetched. -+ * @return numerator The exchange rate numerator. -+ * @return denominator The exchange rate denominator. -+ */ -+ function getExchangeRate(address token) public view returns (uint256 numerator, uint256 denominator) { -+ require(currencies[token].oracle != address(0), "Currency not in the directory"); -+ (numerator, denominator) = IOracle(currencies[token].oracle).getExchangeRate(token); -+ } ++ if intent.ContractsRelease == "dev" { ++ env.Logger.Warn("using dev release with existing OPCM, this field will be ignored") ++ } + -+ /** -+ * @notice Returns the storage, major, minor, and patch version of the contract. -+ * @return Storage version of the contract. -+ * @return Major version of the contract. -+ * @return Minor version of the contract. -+ * @return Patch version of the contract. -+ */ -+ function getVersionNumber() external pure returns (uint256, uint256, uint256, uint256) { -+ return (1, 1, 0, 0); -+ } ++ opcmContract := opcm.NewContract(intent.OPCMAddress, env.L1Client) ++ protocolVersions, err := opcmContract.ProtocolVersions(ctx) ++ if err != nil { ++ return fmt.Errorf("error getting protocol versions address: %w", err) ++ } ++ superchainConfig, err := opcmContract.SuperchainConfig(ctx) ++ if err != nil { ++ return fmt.Errorf("error getting superchain config address: %w", err) ++ } ++ env.Logger.Debug( ++ "populating protocol versions and superchain config addresses", ++ "protocolVersions", protocolVersions.Hex(), ++ "superchainConfig", superchainConfig.Hex(), ++ ) ++ ++ // The below fields are the only ones required to perform an OP Chain ++ // deployment via an existing OPCM contract. All the others are used ++ // for deploying the OPCM itself, which isn't necessary in this case. ++ st.SuperchainDeployment = &state.SuperchainDeployment{ ++ ProtocolVersionsProxyAddress: protocolVersions, ++ SuperchainConfigProxyAddress: superchainConfig, ++ } ++ st.ImplementationsDeployment = &state.ImplementationsDeployment{ ++ OpcmProxyAddress: intent.OPCMAddress, ++ } ++ } ++ ++ // If the state has never been applied, we don't need to perform ++ // any additional checks. ++ if st.AppliedIntent == nil { ++ return nil ++ } ++ ++ // If the state has been applied, we need to check if any immutable ++ // fields have changed. ++ if st.AppliedIntent.L1ChainID != intent.L1ChainID { ++ return immutableErr("L1ChainID", st.AppliedIntent.L1ChainID, intent.L1ChainID) ++ } ++ ++ if st.AppliedIntent.UseFaultProofs != intent.UseFaultProofs { ++ return immutableErr("useFaultProofs", st.AppliedIntent.UseFaultProofs, intent.UseFaultProofs) ++ } ++ ++ if st.AppliedIntent.UseAltDA != intent.UseAltDA { ++ return immutableErr("useAltDA", st.AppliedIntent.UseAltDA, intent.UseAltDA) ++ } ++ ++ if st.AppliedIntent.FundDevAccounts != intent.FundDevAccounts { ++ return immutableErr("fundDevAccounts", st.AppliedIntent.FundDevAccounts, intent.FundDevAccounts) ++ } ++ ++ l1ChainID, err := env.L1Client.ChainID(ctx) ++ if err != nil { ++ return fmt.Errorf("failed to get L1 chain ID: %w", err) ++ } ++ ++ if l1ChainID.Cmp(intent.L1ChainIDBig()) != 0 { ++ return fmt.Errorf("L1 chain ID mismatch: got %d, expected %d", l1ChainID, intent.L1ChainID) ++ } ++ ++ deployerCode, err := env.L1Client.CodeAt(ctx, script.DeterministicDeployerAddress, nil) ++ if err != nil { ++ return fmt.Errorf("failed to get deployer code: %w", err) ++ } ++ if len(deployerCode) == 0 { ++ return fmt.Errorf("deterministic deployer is not deployed on this chain - please deploy it first") ++ } ++ ++ // TODO: validate individual ++ ++ return nil ++} ++ ++func immutableErr(field string, was, is any) error { ++ return fmt.Errorf("%s is immutable: was %v, is %v", field, was, is) +}
@@ -10430,9 +53377,9 @@
@@ -10447,7 +53394,7 @@
@@ -10457,561 +53404,848 @@
-
+543
+
+97
-0
-
diff --git OP/packages/contracts-bedrock/src/celo/FeeHandler.sol CELO/packages/contracts-bedrock/src/celo/FeeHandler.sol +
diff --git OP/op-chain-ops/deployer/pipeline/l2genesis.go CELO/op-chain-ops/deployer/pipeline/l2genesis.go new file mode 100644 -index 0000000000000000000000000000000000000000..00a1b0bde4fcb4af98c1cd85c71b2d45802d950c +index 0000000000000000000000000000000000000000..25aa316c78a504dbd44023c60f8043fb4c2004b7 --- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/FeeHandler.sol -@@ -0,0 +1,543 @@ -+// SPDX-License-Identifier: MIT -+pragma solidity ^0.8.15; -+ -+import "../../lib/openzeppelin-contracts/contracts/utils/math/Math.sol"; -+import "../../lib/openzeppelin-contracts/contracts/access/Ownable.sol"; -+import "../../lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol"; -+import "../../lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; -+ -+import "./UsingRegistry.sol"; -+import "./common/Freezable.sol"; -+import "./common/FixidityLib.sol"; -+import "./common/Initializable.sol"; -+ -+import "./common/interfaces/IFeeHandler.sol"; -+import "./common/interfaces/IFeeHandlerSeller.sol"; -+ -+// TODO move to IStableToken when it adds method getExchangeRegistryId -+import "./interfaces/IStableTokenMento.sol"; -+import "./common/interfaces/ICeloVersionedContract.sol"; -+import "./common/interfaces/ICeloToken.sol"; -+import "./stability/interfaces/ISortedOracles.sol"; -+ -+// Using the minimal required signatures in the interfaces so more contracts could be compatible -+import { ReentrancyGuard } from "@openzeppelin/contracts/security/ReentrancyGuard.sol"; -+ -+// An implementation of FeeHandler as described in CIP-52 -+// See https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0052.md -+contract FeeHandler is -+ Ownable, -+ Initializable, -+ UsingRegistry, -+ ICeloVersionedContract, -+ Freezable, -+ IFeeHandler, -+ ReentrancyGuard -+{ -+ using FixidityLib for FixidityLib.Fraction; -+ using EnumerableSet for EnumerableSet.AddressSet; -+ -+ uint256 public constant FIXED1_UINT = 1000000000000000000000000; // TODO move to FIX and add check -+ -+ // Min units that can be burned -+ uint256 public constant MIN_BURN = 200; -+ -+ // last day the daily limits were updated -+ uint256 public lastLimitDay; -+ -+ FixidityLib.Fraction public burnFraction; // 80% -+ -+ address public feeBeneficiary; -+ -+ uint256 public celoToBeBurned; -+ -+ // This mapping can not be public because it contains a FixidityLib.Fraction -+ // and that'd be only supported with experimental features in this -+ // compiler version -+ mapping(address => TokenState) private tokenStates; -+ -+ struct TokenState { -+ address handler; -+ FixidityLib.Fraction maxSlippage; -+ // Max amounts that can be burned in a day for a token -+ uint256 dailySellLimit; -+ // Max amounts that can be burned today for a token -+ uint256 currentDaySellLimit; -+ uint256 toDistribute; -+ // Historical amounts burned by this contract -+ uint256 pastBurn; -+ } -+ -+ EnumerableSet.AddressSet private activeTokens; -+ -+ event SoldAndBurnedToken(address token, uint256 value); -+ event DailyLimitSet(address tokenAddress, uint256 newLimit); -+ event DailyLimitHit(address token, uint256 burning); -+ event MaxSlippageSet(address token, uint256 maxSlippage); -+ event DailySellLimitUpdated(uint256 amount); -+ event FeeBeneficiarySet(address newBeneficiary); -+ event BurnFractionSet(uint256 fraction); -+ event TokenAdded(address tokenAddress, address handlerAddress); -+ event TokenRemoved(address tokenAddress); -+ -+ /** -+ * @notice Sets initialized == true on implementation contracts. -+ * @param test Set to true to skip implementation initialisation. -+ */ -+ constructor(bool test) Initializable(test) { } ++++ CELO/op-chain-ops/deployer/pipeline/l2genesis.go +@@ -0,0 +1,97 @@ ++package pipeline + -+ /** -+ * @notice Used in place of the constructor to allow the contract to be upgradable via proxy. -+ */ -+ function initialize( -+ address _registryAddress, -+ address newFeeBeneficiary, -+ uint256 newBurnFraction, -+ address[] calldata tokens, -+ address[] calldata handlers, -+ uint256[] calldata newLimits, -+ uint256[] calldata newMaxSlippages -+ ) -+ external -+ initializer -+ { -+ require(tokens.length == handlers.length, "handlers length should match tokens length"); -+ require(tokens.length == newLimits.length, "limits length should match tokens length"); -+ require(tokens.length == newMaxSlippages.length, "maxSlippage length should match tokens length"); ++import ( ++ "bytes" ++ "compress/gzip" ++ "context" ++ "encoding/json" ++ "fmt" ++ "math/big" + -+ _transferOwnership(msg.sender); -+ setRegistry(_registryAddress); -+ _setFeeBeneficiary(newFeeBeneficiary); -+ _setBurnFraction(newBurnFraction); ++ "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/opcm" ++ "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/state" ++ "github.com/ethereum-optimism/optimism/op-chain-ops/foundry" ++ "github.com/ethereum-optimism/optimism/op-chain-ops/script" ++ "github.com/ethereum/go-ethereum/common" ++) + -+ for (uint256 i = 0; i < tokens.length; i++) { -+ _addToken(tokens[i], handlers[i]); -+ _setDailySellLimit(tokens[i], newLimits[i]); -+ _setMaxSplippage(tokens[i], newMaxSlippages[i]); -+ } -+ } ++func GenerateL2Genesis(ctx context.Context, env *Env, artifactsFS foundry.StatDirFs, intent *state.Intent, st *state.State, chainID common.Hash) error { ++ lgr := env.Logger.New("stage", "generate-l2-genesis") + -+ // Without this the contract cant receive Celo as native transfer -+ receive() external payable { } ++ lgr.Info("generating L2 genesis", "id", chainID.Hex()) + -+ /** -+ * @dev Returns the handler address for the specified token. -+ * @param tokenAddress The address of the token for which to return the handler. -+ * @return The address of the handler contract for the specified token. -+ */ -+ function getTokenHandler(address tokenAddress) external view returns (address) { -+ return tokenStates[tokenAddress].handler; -+ } ++ thisIntent, err := intent.Chain(chainID) ++ if err != nil { ++ return fmt.Errorf("failed to get chain intent: %w", err) ++ } + -+ /** -+ * @dev Returns a boolean indicating whether the specified token is active or not. -+ * @param tokenAddress The address of the token for which to retrieve the active status. -+ * @return A boolean representing the active status of the specified token. -+ */ -+ function getTokenActive(address tokenAddress) external view returns (bool) { -+ return activeTokens.contains(tokenAddress); -+ } ++ thisChainState, err := st.Chain(chainID) ++ if err != nil { ++ return fmt.Errorf("failed to get chain state: %w", err) ++ } + -+ /** -+ * @dev Returns the maximum slippage percentage for the specified token. -+ * @param tokenAddress The address of the token for which to retrieve the maximum -+ * slippage percentage. -+ * @return The maximum slippage percentage as a uint256 value. -+ */ -+ function getTokenMaxSlippage(address tokenAddress) external view returns (uint256) { -+ return FixidityLib.unwrap(tokenStates[tokenAddress].maxSlippage); -+ } ++ initCfg, err := state.CombineDeployConfig(intent, thisIntent, st, thisChainState) ++ if err != nil { ++ return fmt.Errorf("failed to combine L2 init config: %w", err) ++ } + -+ /** -+ * @dev Returns the daily burn limit for the specified token. -+ * @param tokenAddress The address of the token for which to retrieve the daily burn limit. -+ * @return The daily burn limit as a uint256 value. -+ */ -+ function getTokenDailySellLimit(address tokenAddress) external view returns (uint256) { -+ return tokenStates[tokenAddress].dailySellLimit; -+ } ++ var dump *foundry.ForgeAllocs ++ err = CallScriptBroadcast( ++ ctx, ++ CallScriptBroadcastOpts{ ++ L1ChainID: big.NewInt(int64(intent.L1ChainID)), ++ Logger: lgr, ++ ArtifactsFS: artifactsFS, ++ Deployer: env.Deployer, ++ Signer: env.Signer, ++ Client: env.L1Client, ++ Broadcaster: DiscardBroadcaster, ++ Handler: func(host *script.Host) error { ++ err := opcm.L2Genesis(host, &opcm.L2GenesisInput{ ++ L1Deployments: opcm.L1Deployments{ ++ L1CrossDomainMessengerProxy: thisChainState.L1CrossDomainMessengerProxyAddress, ++ L1StandardBridgeProxy: thisChainState.L1StandardBridgeProxyAddress, ++ L1ERC721BridgeProxy: thisChainState.L1ERC721BridgeProxyAddress, ++ }, ++ L2Config: initCfg.L2InitializationConfig, ++ }) ++ if err != nil { ++ return fmt.Errorf("failed to call L2Genesis script: %w", err) ++ } + -+ /** -+ * @dev Returns the current daily sell limit for the specified token. -+ * @param tokenAddress The address of the token for which to retrieve the current daily limit. -+ * @return The current daily limit as a uint256 value. -+ */ -+ function getTokenCurrentDaySellLimit(address tokenAddress) external view returns (uint256) { -+ return tokenStates[tokenAddress].currentDaySellLimit; -+ } ++ host.Wipe(env.Deployer) + -+ /** -+ * @dev Returns the amount of tokens available to distribute for the specified token. -+ * @param tokenAddress The address of the token for which to retrieve the amount of -+ * tokens available to distribute. -+ * @return The amount of tokens available to distribute as a uint256 value. -+ */ -+ function getTokenToDistribute(address tokenAddress) external view returns (uint256) { -+ return tokenStates[tokenAddress].toDistribute; -+ } ++ dump, err = host.StateDump() ++ if err != nil { ++ return fmt.Errorf("failed to dump state: %w", err) ++ } + -+ function getActiveTokens() public view returns (address[] memory) { -+ return activeTokens.values(); -+ } ++ return nil ++ }, ++ }, ++ ) ++ if err != nil { ++ return fmt.Errorf("failed to call L2Genesis script: %w", err) ++ } + -+ /** -+ * @dev Sets the fee beneficiary address to the specified address. -+ * @param beneficiary The address to set as the fee beneficiary. -+ */ -+ function setFeeBeneficiary(address beneficiary) external onlyOwner { -+ return _setFeeBeneficiary(beneficiary); -+ } ++ var buf bytes.Buffer ++ gw := gzip.NewWriter(&buf) ++ if err := json.NewEncoder(gw).Encode(dump); err != nil { ++ return fmt.Errorf("failed to encode state dump: %w", err) ++ } ++ if err := gw.Close(); err != nil { ++ return fmt.Errorf("failed to close gzip writer: %w", err) ++ } ++ thisChainState.Allocs = buf.Bytes() ++ startHeader, err := env.L1Client.HeaderByNumber(ctx, nil) ++ if err != nil { ++ return fmt.Errorf("failed to get start block: %w", err) ++ } ++ thisChainState.StartBlock = startHeader + -+ function _setFeeBeneficiary(address beneficiary) private { -+ feeBeneficiary = beneficiary; -+ emit FeeBeneficiarySet(beneficiary); -+ } ++ if err := env.WriteState(st); err != nil { ++ return fmt.Errorf("failed to write state: %w", err) ++ } + -+ /** -+ * @dev Sets the burn fraction to the specified value. -+ * @param fraction The value to set as the burn fraction. -+ */ -+ function setBurnFraction(uint256 fraction) external onlyOwner { -+ return _setBurnFraction(fraction); -+ } ++ return nil ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+130
+
-0
+ +
+ +
+
+
diff --git OP/op-chain-ops/deployer/pipeline/opchain.go CELO/op-chain-ops/deployer/pipeline/opchain.go +new file mode 100644 +index 0000000000000000000000000000000000000000..27919fb8b1357e89294876e189725c4370b8cfec +--- /dev/null ++++ CELO/op-chain-ops/deployer/pipeline/opchain.go +@@ -0,0 +1,130 @@ ++package pipeline + -+ function _setBurnFraction(uint256 newFraction) private { -+ FixidityLib.Fraction memory fraction = FixidityLib.wrap(newFraction); -+ require(FixidityLib.lte(fraction, FixidityLib.fixed1()), "Burn fraction must be less than or equal to 1"); -+ burnFraction = fraction; -+ emit BurnFractionSet(newFraction); -+ } ++import ( ++ "context" ++ "fmt" ++ "math/big" + -+ /** -+ * @dev Sets the burn fraction to the specified value. Token has to have a handler set. -+ * @param tokenAddress The address of the token to sell -+ */ -+ function sell(address tokenAddress) external { -+ return _sell(tokenAddress); -+ } ++ "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/broadcaster" + -+ /** -+ * @dev Adds a new token to the contract with the specified token and handler addresses. -+ * @param tokenAddress The address of the token to add. -+ * @param handlerAddress The address of the handler contract for the specified token. -+ */ -+ function addToken(address tokenAddress, address handlerAddress) external onlyOwner { -+ _addToken(tokenAddress, handlerAddress); -+ } ++ "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/opcm" ++ "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/state" ++ "github.com/ethereum-optimism/optimism/op-chain-ops/foundry" ++ "github.com/ethereum-optimism/optimism/op-chain-ops/script" ++ "github.com/ethereum/go-ethereum/common" ++) + -+ function _addToken(address tokenAddress, address handlerAddress) private { -+ require(handlerAddress != address(0), "Can't set handler to zero"); -+ TokenState storage tokenState = tokenStates[tokenAddress]; -+ tokenState.handler = handlerAddress; ++func DeployOPChain(ctx context.Context, env *Env, artifactsFS foundry.StatDirFs, intent *state.Intent, st *state.State, chainID common.Hash) error { ++ lgr := env.Logger.New("stage", "deploy-opchain") + -+ activeTokens.add(tokenAddress); -+ emit TokenAdded(tokenAddress, handlerAddress); -+ } ++ if !shouldDeployOPChain(intent, st, chainID) { ++ lgr.Info("opchain deployment not needed") ++ return nil ++ } + -+ /** -+ * @notice Allows the owner to activate a specified token. -+ * @param tokenAddress The address of the token to be activated. -+ */ -+ function activateToken(address tokenAddress) external onlyOwner { -+ _activateToken(tokenAddress); -+ } ++ lgr.Info("deploying OP chain", "id", chainID.Hex()) + -+ function _activateToken(address tokenAddress) private { -+ TokenState storage tokenState = tokenStates[tokenAddress]; -+ require( -+ tokenState.handler != address(0) || tokenAddress == registry.getAddressForOrDie(GOLD_TOKEN_REGISTRY_ID), -+ "Handler has to be set to activate token" -+ ); -+ activeTokens.add(tokenAddress); -+ } ++ thisIntent, err := intent.Chain(chainID) ++ if err != nil { ++ return fmt.Errorf("failed to get chain intent: %w", err) ++ } + -+ /** -+ * @dev Deactivates the specified token by marking it as inactive. -+ * @param tokenAddress The address of the token to deactivate. -+ */ -+ function deactivateToken(address tokenAddress) external onlyOwner { -+ _deactivateToken(tokenAddress); -+ } ++ input := opcm.DeployOPChainInput{ ++ OpChainProxyAdminOwner: thisIntent.Roles.ProxyAdminOwner, ++ SystemConfigOwner: thisIntent.Roles.SystemConfigOwner, ++ Batcher: thisIntent.Roles.Batcher, ++ UnsafeBlockSigner: thisIntent.Roles.UnsafeBlockSigner, ++ Proposer: thisIntent.Roles.Proposer, ++ Challenger: thisIntent.Roles.Challenger, ++ BasefeeScalar: 1368, ++ BlobBaseFeeScalar: 801949, ++ L2ChainId: chainID.Big(), ++ OpcmProxy: st.ImplementationsDeployment.OpcmProxyAddress, ++ } + -+ function _deactivateToken(address tokenAddress) private { -+ activeTokens.remove(tokenAddress); -+ } ++ var dco opcm.DeployOPChainOutput ++ if intent.OPCMAddress == (common.Address{}) { ++ err = CallScriptBroadcast( ++ ctx, ++ CallScriptBroadcastOpts{ ++ L1ChainID: big.NewInt(int64(intent.L1ChainID)), ++ Logger: lgr, ++ ArtifactsFS: artifactsFS, ++ Deployer: env.Deployer, ++ Signer: env.Signer, ++ Client: env.L1Client, ++ Broadcaster: KeyedBroadcaster, ++ Handler: func(host *script.Host) error { ++ host.ImportState(st.ImplementationsDeployment.StateDump) ++ ++ dco, err = opcm.DeployOPChain( ++ host, ++ input, ++ ) ++ return err ++ }, ++ }, ++ ) ++ if err != nil { ++ return fmt.Errorf("error deploying OP chain: %w", err) ++ } ++ } else { ++ lgr.Info("deploying using existing OPCM", "address", intent.OPCMAddress.Hex()) ++ ++ bcaster, err := broadcaster.NewKeyedBroadcaster(broadcaster.KeyedBroadcasterOpts{ ++ Logger: lgr, ++ ChainID: big.NewInt(int64(intent.L1ChainID)), ++ Client: env.L1Client, ++ Signer: env.Signer, ++ From: env.Deployer, ++ }) ++ if err != nil { ++ return fmt.Errorf("failed to create broadcaster: %w", err) ++ } ++ dco, err = opcm.DeployOPChainRaw( ++ ctx, ++ env.L1Client, ++ bcaster, ++ env.Deployer, ++ artifactsFS, ++ input, ++ ) ++ if err != nil { ++ return fmt.Errorf("error deploying OP chain: %w", err) ++ } ++ } + -+ /** -+ * @notice Allows the owner to set a handler contract for a specified token. -+ * @param tokenAddress The address of the token to set the handler for. -+ * @param handlerAddress The address of the handler contract to be set. -+ */ -+ function setHandler(address tokenAddress, address handlerAddress) external onlyOwner { -+ _setHandler(tokenAddress, handlerAddress); -+ } ++ st.Chains = append(st.Chains, &state.ChainState{ ++ ID: chainID, ++ ProxyAdminAddress: dco.OpChainProxyAdmin, ++ AddressManagerAddress: dco.AddressManager, ++ L1ERC721BridgeProxyAddress: dco.L1ERC721BridgeProxy, ++ SystemConfigProxyAddress: dco.SystemConfigProxy, ++ OptimismMintableERC20FactoryProxyAddress: dco.OptimismMintableERC20FactoryProxy, ++ L1StandardBridgeProxyAddress: dco.L1StandardBridgeProxy, ++ L1CrossDomainMessengerProxyAddress: dco.L1CrossDomainMessengerProxy, ++ OptimismPortalProxyAddress: dco.OptimismPortalProxy, ++ DisputeGameFactoryProxyAddress: dco.DisputeGameFactoryProxy, ++ AnchorStateRegistryProxyAddress: dco.AnchorStateRegistryProxy, ++ AnchorStateRegistryImplAddress: dco.AnchorStateRegistryImpl, ++ FaultDisputeGameAddress: dco.FaultDisputeGame, ++ PermissionedDisputeGameAddress: dco.PermissionedDisputeGame, ++ DelayedWETHPermissionedGameProxyAddress: dco.DelayedWETHPermissionedGameProxy, ++ DelayedWETHPermissionlessGameProxyAddress: dco.DelayedWETHPermissionlessGameProxy, ++ }) ++ if err := env.WriteState(st); err != nil { ++ return err ++ } + -+ function _setHandler(address tokenAddress, address handlerAddress) private { -+ require(handlerAddress != address(0), "Can't set handler to zero, use deactivateToken"); -+ TokenState storage tokenState = tokenStates[tokenAddress]; -+ tokenState.handler = handlerAddress; -+ } ++ return nil ++} + -+ function removeToken(address tokenAddress) external onlyOwner { -+ _removeToken(tokenAddress); -+ } ++func shouldDeployOPChain(intent *state.Intent, st *state.State, chainID common.Hash) bool { ++ for _, chain := range st.Chains { ++ if chain.ID == chainID { ++ return false ++ } ++ } + -+ function _removeToken(address tokenAddress) private { -+ _deactivateToken(tokenAddress); -+ TokenState storage tokenState = tokenStates[tokenAddress]; -+ tokenState.handler = address(0); -+ emit TokenRemoved(tokenAddress); -+ } ++ return true ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+83
+
-0
+ +
+ +
+
+
diff --git OP/op-chain-ops/deployer/pipeline/superchain.go CELO/op-chain-ops/deployer/pipeline/superchain.go +new file mode 100644 +index 0000000000000000000000000000000000000000..13737475c916bdb12754c4d11e40187ed0d3099c +--- /dev/null ++++ CELO/op-chain-ops/deployer/pipeline/superchain.go +@@ -0,0 +1,83 @@ ++package pipeline + -+ function _sell(address tokenAddress) private onlyWhenNotFrozen nonReentrant { -+ IERC20 token = IERC20(tokenAddress); ++import ( ++ "context" ++ "fmt" ++ "math/big" + -+ TokenState storage tokenState = tokenStates[tokenAddress]; -+ require(tokenState.handler != address(0), "Handler has to be set to sell token"); -+ require(FixidityLib.unwrap(tokenState.maxSlippage) != 0, "Max slippage has to be set to sell token"); -+ FixidityLib.Fraction memory balanceToProcess = -+ FixidityLib.newFixed(token.balanceOf(address(this)) - tokenState.toDistribute); ++ "github.com/ethereum-optimism/optimism/op-chain-ops/script" + -+ uint256 balanceToBurn = (burnFraction.multiply(balanceToProcess).fromFixed()); ++ "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/opcm" ++ "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/state" ++ "github.com/ethereum-optimism/optimism/op-chain-ops/foundry" ++ "github.com/ethereum-optimism/optimism/op-node/rollup" ++) + -+ tokenState.toDistribute = tokenState.toDistribute + balanceToProcess.fromFixed() - balanceToBurn; ++func DeploySuperchain(ctx context.Context, env *Env, artifactsFS foundry.StatDirFs, intent *state.Intent, st *state.State) error { ++ lgr := env.Logger.New("stage", "deploy-superchain") + -+ // small numbers cause rounding errors and zero case should be skipped -+ if (balanceToBurn < MIN_BURN) { -+ return; -+ } ++ if !shouldDeploySuperchain(intent, st) { ++ lgr.Info("superchain deployment not needed") ++ return nil ++ } + -+ if (dailySellLimitHit(tokenAddress, balanceToBurn)) { -+ // in case the limit is hit, burn the max possible -+ balanceToBurn = tokenState.currentDaySellLimit; -+ emit DailyLimitHit(tokenAddress, balanceToBurn); -+ } ++ lgr.Info("deploying superchain") + -+ token.transfer(tokenState.handler, balanceToBurn); -+ IFeeHandlerSeller handler = IFeeHandlerSeller(tokenState.handler); ++ var dump *foundry.ForgeAllocs ++ var dso opcm.DeploySuperchainOutput ++ var err error ++ err = CallScriptBroadcast( ++ ctx, ++ CallScriptBroadcastOpts{ ++ L1ChainID: big.NewInt(int64(intent.L1ChainID)), ++ Logger: lgr, ++ ArtifactsFS: artifactsFS, ++ Deployer: env.Deployer, ++ Signer: env.Signer, ++ Client: env.L1Client, ++ Broadcaster: KeyedBroadcaster, ++ Handler: func(host *script.Host) error { ++ dso, err = opcm.DeploySuperchain( ++ host, ++ opcm.DeploySuperchainInput{ ++ SuperchainProxyAdminOwner: intent.SuperchainRoles.ProxyAdminOwner, ++ ProtocolVersionsOwner: intent.SuperchainRoles.ProtocolVersionsOwner, ++ Guardian: intent.SuperchainRoles.Guardian, ++ Paused: false, ++ RequiredProtocolVersion: rollup.OPStackSupport, ++ RecommendedProtocolVersion: rollup.OPStackSupport, ++ }, ++ ) ++ if err != nil { ++ return fmt.Errorf("failed to deploy superchain: %w", err) ++ } ++ dump, err = host.StateDump() ++ if err != nil { ++ return fmt.Errorf("error dumping state: %w", err) ++ } ++ return nil ++ }, ++ }, ++ ) ++ if err != nil { ++ return fmt.Errorf("error deploying superchain: %w", err) ++ } + -+ uint256 celoReceived = handler.sell( -+ tokenAddress, -+ registry.getAddressForOrDie(GOLD_TOKEN_REGISTRY_ID), -+ balanceToBurn, -+ FixidityLib.unwrap(tokenState.maxSlippage) -+ ); ++ st.SuperchainDeployment = &state.SuperchainDeployment{ ++ ProxyAdminAddress: dso.SuperchainProxyAdmin, ++ SuperchainConfigProxyAddress: dso.SuperchainConfigProxy, ++ SuperchainConfigImplAddress: dso.SuperchainConfigImpl, ++ ProtocolVersionsProxyAddress: dso.ProtocolVersionsProxy, ++ ProtocolVersionsImplAddress: dso.ProtocolVersionsImpl, ++ StateDump: dump, ++ } ++ if err := env.WriteState(st); err != nil { ++ return err ++ } + -+ celoToBeBurned = celoToBeBurned + celoReceived; -+ tokenState.pastBurn = tokenState.pastBurn + balanceToBurn; -+ updateLimits(tokenAddress, balanceToBurn); ++ return nil ++} + -+ emit SoldAndBurnedToken(tokenAddress, balanceToBurn); -+ } ++func shouldDeploySuperchain(intent *state.Intent, st *state.State) bool { ++ return st.SuperchainDeployment == nil ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+18
+
-0
+ +
+ +
+
+
diff --git OP/op-chain-ops/deployer/state/artifacts_url.go CELO/op-chain-ops/deployer/state/artifacts_url.go +new file mode 100644 +index 0000000000000000000000000000000000000000..5ea576d79eecb4ecea9a74d7e076f185c8579478 +--- /dev/null ++++ CELO/op-chain-ops/deployer/state/artifacts_url.go +@@ -0,0 +1,18 @@ ++package state + -+ /** -+ * @dev Distributes the available tokens for the specified token address to the fee beneficiary. -+ * @param tokenAddress The address of the token for which to distribute the available tokens. -+ */ -+ function distribute(address tokenAddress) external { -+ return _distribute(tokenAddress); -+ } ++import "net/url" + -+ function _distribute(address tokenAddress) private onlyWhenNotFrozen nonReentrant { -+ require(feeBeneficiary != address(0), "Can't distribute to the zero address"); -+ IERC20 token = IERC20(tokenAddress); -+ uint256 tokenBalance = token.balanceOf(address(this)); ++type ArtifactsURL url.URL + -+ TokenState storage tokenState = tokenStates[tokenAddress]; -+ require( -+ tokenState.handler != address(0) || tokenAddress == registry.getAddressForOrDie(GOLD_TOKEN_REGISTRY_ID), -+ "Handler has to be set to sell token" -+ ); ++func (a *ArtifactsURL) MarshalText() ([]byte, error) { ++ return []byte((*url.URL)(a).String()), nil ++} + -+ // safty check to avoid a revert due balance -+ uint256 balanceToDistribute = Math.min(tokenBalance, tokenState.toDistribute); ++func (a *ArtifactsURL) UnmarshalText(text []byte) error { ++ u, err := url.Parse(string(text)) ++ if err != nil { ++ return err ++ } ++ *a = ArtifactsURL(*u) ++ return nil ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+30
+
-0
+ +
+ +
+
+
diff --git OP/op-chain-ops/deployer/state/base64.go CELO/op-chain-ops/deployer/state/base64.go +new file mode 100644 +index 0000000000000000000000000000000000000000..23e4379fe5fa9839030c9fe8b4e82760a264a2fa +--- /dev/null ++++ CELO/op-chain-ops/deployer/state/base64.go +@@ -0,0 +1,30 @@ ++package state + -+ if (balanceToDistribute == 0) { -+ // don't distribute with zero balance -+ return; -+ } ++import ( ++ "encoding/base64" ++ "encoding/json" ++) + -+ token.transfer(feeBeneficiary, balanceToDistribute); -+ tokenState.toDistribute = tokenState.toDistribute - balanceToDistribute; -+ } ++type Base64Bytes []byte + -+ /** -+ * @notice Returns the storage, major, minor, and patch version of the contract. -+ * @return Storage version of the contract. -+ * @return Major version of the contract. -+ * @return Minor version of the contract. -+ * @return Patch version of the contract. -+ */ -+ function getVersionNumber() external pure returns (uint256, uint256, uint256, uint256) { -+ return (1, 1, 0, 0); -+ } ++func (b Base64Bytes) MarshalJSON() ([]byte, error) { ++ if len(b) == 0 { ++ return []byte(`null`), nil ++ } + -+ /** -+ * @notice Allows owner to set max slippage for a token. -+ * @param token Address of the token to set. -+ * @param newMax New sllipage to set, as Fixidity fraction. -+ */ -+ function setMaxSplippage(address token, uint256 newMax) external onlyOwner { -+ _setMaxSplippage(token, newMax); -+ } ++ encoded := base64.StdEncoding.EncodeToString(b) ++ return []byte(`"` + encoded + `"`), nil ++} + -+ function _setMaxSplippage(address token, uint256 newMax) private { -+ TokenState storage tokenState = tokenStates[token]; -+ require(newMax != 0, "Cannot set max slippage to zero"); -+ tokenState.maxSlippage = FixidityLib.wrap(newMax); -+ require( -+ FixidityLib.lte(tokenState.maxSlippage, FixidityLib.fixed1()), "Splippage must be less than or equal to 1" -+ ); -+ emit MaxSlippageSet(token, newMax); -+ } ++func (b *Base64Bytes) UnmarshalJSON(data []byte) error { ++ var dataStr string ++ if err := json.Unmarshal(data, &dataStr); err != nil { ++ return err ++ } ++ decoded, err := base64.StdEncoding.DecodeString(dataStr) ++ if err != nil { ++ return err ++ } ++ *b = decoded ++ return nil ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+38
+
-0
+ +
+ +
+
+
diff --git OP/op-chain-ops/deployer/state/base64_test.go CELO/op-chain-ops/deployer/state/base64_test.go +new file mode 100644 +index 0000000000000000000000000000000000000000..abfa6654cee5d487e7f47380e4f542430d9d4557 +--- /dev/null ++++ CELO/op-chain-ops/deployer/state/base64_test.go +@@ -0,0 +1,38 @@ ++package state + -+ /** -+ * @notice Allows owner to set the daily burn limit for a token. -+ * @param token Address of the token to set. -+ * @param newLimit The new limit to set, in the token units. -+ */ -+ function setDailySellLimit(address token, uint256 newLimit) external onlyOwner { -+ _setDailySellLimit(token, newLimit); -+ } ++import ( ++ "testing" + -+ function _setDailySellLimit(address token, uint256 newLimit) private { -+ TokenState storage tokenState = tokenStates[token]; -+ tokenState.dailySellLimit = newLimit; -+ emit DailyLimitSet(token, newLimit); -+ } ++ "github.com/stretchr/testify/require" ++) + -+ /** -+ * @dev Burns CELO tokens according to burnFraction. -+ */ -+ function burnCelo() external { -+ return _burnCelo(); -+ } ++func TestBase64BytesMarshaling(t *testing.T) { ++ tests := []struct { ++ name string ++ in Base64Bytes ++ out string ++ }{ ++ { ++ name: "empty", ++ in: Base64Bytes{}, ++ out: "null", ++ }, ++ { ++ name: "non-empty", ++ in: Base64Bytes{0x01, 0x02, 0x03}, ++ out: `"AQID"`, ++ }, ++ } ++ for _, tt := range tests { ++ t.Run(tt.name, func(t *testing.T) { ++ data, err := tt.in.MarshalJSON() ++ require.NoError(t, err) ++ require.Equal(t, tt.out, string(data)) ++ ++ var b Base64Bytes ++ err = b.UnmarshalJSON(data) ++ require.NoError(t, err) ++ require.Equal(t, tt.in, b) ++ }) ++ } ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+158
+
-0
+ +
+ +
+
+
diff --git OP/op-chain-ops/deployer/state/deploy_config.go CELO/op-chain-ops/deployer/state/deploy_config.go +new file mode 100644 +index 0000000000000000000000000000000000000000..81801e5865cb187a149a5d7dda2584111ebb7b2f +--- /dev/null ++++ CELO/op-chain-ops/deployer/state/deploy_config.go +@@ -0,0 +1,158 @@ ++package state + -+ /** -+ * @dev Distributes the available tokens for all registered tokens to the feeBeneficiary. -+ */ -+ function distributeAll() external { -+ return _distributeAll(); -+ } ++import ( ++ "encoding/json" ++ "fmt" ++ "math/big" + -+ function _distributeAll() private { -+ for (uint256 i = 0; i < EnumerableSet.length(activeTokens); i++) { -+ address token = activeTokens.at(i); -+ _distribute(token); -+ } -+ // distribute Celo -+ _distribute(registry.getAddressForOrDie(GOLD_TOKEN_REGISTRY_ID)); -+ } ++ "github.com/ethereum/go-ethereum/common" ++ "github.com/ethereum/go-ethereum/crypto" + -+ /** -+ * @dev Distributes the available tokens for all registered tokens to the feeBeneficiary. -+ */ -+ function handleAll() external { -+ return _handleAll(); -+ } ++ "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" ++ "github.com/ethereum/go-ethereum/common/hexutil" ++) + -+ function _handleAll() private { -+ for (uint256 i = 0; i < EnumerableSet.length(activeTokens); i++) { -+ // calling _handle would trigger may burn Celo and distributions -+ // that can be just batched at the end -+ address token = activeTokens.at(i); -+ _sell(token); -+ } -+ _distributeAll(); // distributes Celo as well -+ _burnCelo(); -+ } ++var ( ++ l2GenesisBlockBaseFeePerGas = hexutil.Big(*(big.NewInt(1000000000))) + -+ /** -+ * @dev Distributes the the token for to the feeBeneficiary. -+ */ -+ function handle(address tokenAddress) external { -+ return _handle(tokenAddress); -+ } ++ vaultMinWithdrawalAmount = mustHexBigFromHex("0x8ac7230489e80000") ++) + -+ function _handle(address tokenAddress) private { -+ // Celo doesn't have to be exchanged for anything -+ if (tokenAddress != registry.getAddressForOrDie(GOLD_TOKEN_REGISTRY_ID)) { -+ _sell(tokenAddress); -+ } -+ _burnCelo(); -+ _distribute(tokenAddress); -+ _distribute(registry.getAddressForOrDie(GOLD_TOKEN_REGISTRY_ID)); -+ } ++func DefaultDeployConfig() genesis.DeployConfig { ++ return genesis.DeployConfig{ ++ L2InitializationConfig: genesis.L2InitializationConfig{ ++ L2GenesisBlockDeployConfig: genesis.L2GenesisBlockDeployConfig{ ++ L2GenesisBlockGasLimit: 30_000_000, ++ L2GenesisBlockBaseFeePerGas: &l2GenesisBlockBaseFeePerGas, ++ }, ++ L2VaultsDeployConfig: genesis.L2VaultsDeployConfig{ ++ BaseFeeVaultWithdrawalNetwork: "local", ++ L1FeeVaultWithdrawalNetwork: "local", ++ SequencerFeeVaultWithdrawalNetwork: "local", ++ SequencerFeeVaultMinimumWithdrawalAmount: vaultMinWithdrawalAmount, ++ BaseFeeVaultMinimumWithdrawalAmount: vaultMinWithdrawalAmount, ++ L1FeeVaultMinimumWithdrawalAmount: vaultMinWithdrawalAmount, ++ }, ++ GovernanceDeployConfig: genesis.GovernanceDeployConfig{ ++ EnableGovernance: true, ++ GovernanceTokenSymbol: "OP", ++ GovernanceTokenName: "Optimism", ++ }, ++ GasPriceOracleDeployConfig: genesis.GasPriceOracleDeployConfig{ ++ GasPriceOracleBaseFeeScalar: 1368, ++ GasPriceOracleBlobBaseFeeScalar: 810949, ++ }, ++ EIP1559DeployConfig: genesis.EIP1559DeployConfig{ ++ EIP1559Denominator: 50, ++ EIP1559DenominatorCanyon: 250, ++ EIP1559Elasticity: 6, ++ }, ++ UpgradeScheduleDeployConfig: genesis.UpgradeScheduleDeployConfig{ ++ L2GenesisRegolithTimeOffset: u64UtilPtr(0), ++ L2GenesisCanyonTimeOffset: u64UtilPtr(0), ++ L2GenesisDeltaTimeOffset: u64UtilPtr(0), ++ L2GenesisEcotoneTimeOffset: u64UtilPtr(0), ++ L2GenesisFjordTimeOffset: u64UtilPtr(0), ++ L2GenesisGraniteTimeOffset: u64UtilPtr(0), ++ UseInterop: false, ++ }, ++ L2CoreDeployConfig: genesis.L2CoreDeployConfig{ ++ L2BlockTime: 2, ++ FinalizationPeriodSeconds: 12, ++ MaxSequencerDrift: 600, ++ SequencerWindowSize: 3600, ++ ChannelTimeoutBedrock: 300, ++ SystemConfigStartBlock: 0, ++ }, ++ }, ++ } ++} + -+ /** -+ * @notice Burns all the Celo balance of this contract. -+ */ -+ function _burnCelo() private { -+ TokenState storage tokenState = tokenStates[registry.getAddressForOrDie(GOLD_TOKEN_REGISTRY_ID)]; -+ ICeloToken celo = ICeloToken(registry.getAddressForOrDie(GOLD_TOKEN_REGISTRY_ID)); ++func CombineDeployConfig(intent *Intent, chainIntent *ChainIntent, state *State, chainState *ChainState) (genesis.DeployConfig, error) { ++ cfg := DefaultDeployConfig() + -+ uint256 balanceOfCelo = address(this).balance; ++ var err error ++ if len(intent.GlobalDeployOverrides) > 0 { ++ cfg, err = mergeJSON(cfg, intent.GlobalDeployOverrides) ++ if err != nil { ++ return genesis.DeployConfig{}, fmt.Errorf("error merging global L2 overrides: %w", err) + -+ uint256 balanceToProcess = balanceOfCelo - tokenState.toDistribute - celoToBeBurned; -+ uint256 currentBalanceToBurn = FixidityLib.newFixed(balanceToProcess).multiply(burnFraction).fromFixed(); -+ uint256 totalBalanceToBurn = currentBalanceToBurn + celoToBeBurned; -+ celo.burn(totalBalanceToBurn); ++ } ++ } + -+ celoToBeBurned = 0; -+ tokenState.toDistribute = tokenState.toDistribute + balanceToProcess - currentBalanceToBurn; -+ } ++ if len(chainIntent.DeployOverrides) > 0 { ++ cfg, err = mergeJSON(cfg, chainIntent.DeployOverrides) ++ if err != nil { ++ return genesis.DeployConfig{}, fmt.Errorf("error merging chain L2 overrides: %w", err) ++ } ++ } + -+ /** -+ * @param token The address of the token to query. -+ * @return The amount burned for a token. -+ */ -+ function getPastBurnForToken(address token) external view returns (uint256) { -+ return tokenStates[token].pastBurn; -+ } ++ cfg.L2ChainID = chainState.ID.Big().Uint64() ++ cfg.L1DependenciesConfig = genesis.L1DependenciesConfig{ ++ L1StandardBridgeProxy: chainState.L1StandardBridgeProxyAddress, ++ L1CrossDomainMessengerProxy: chainState.L1CrossDomainMessengerProxyAddress, ++ L1ERC721BridgeProxy: chainState.L1ERC721BridgeProxyAddress, ++ SystemConfigProxy: chainState.SystemConfigProxyAddress, ++ OptimismPortalProxy: chainState.OptimismPortalProxyAddress, ++ ProtocolVersionsProxy: state.SuperchainDeployment.ProtocolVersionsProxyAddress, ++ } ++ cfg.OperatorDeployConfig = genesis.OperatorDeployConfig{ ++ BatchSenderAddress: chainIntent.Roles.Batcher, ++ P2PSequencerAddress: chainIntent.Roles.UnsafeBlockSigner, ++ } ++ cfg.BatchInboxAddress = calculateBatchInboxAddr(chainState.ID) ++ cfg.L1ChainID = intent.L1ChainID + -+ /** -+ * @param token The address of the token to query. -+ * @param amountToBurn The amount of the token to burn. -+ * @return Returns true if burning amountToBurn would exceed the daily limit. -+ */ -+ function dailySellLimitHit(address token, uint256 amountToBurn) public returns (bool) { -+ TokenState storage tokenState = tokenStates[token]; ++ return cfg, nil ++} + -+ if (tokenState.dailySellLimit == 0) { -+ // if no limit set, assume uncapped -+ return false; -+ } ++// mergeJSON merges the provided overrides into the input struct. Fields ++// must be JSON-serializable for this to work. Overrides are applied in ++// order of precedence - i.e., the last overrides will override keys from ++// all preceding overrides. ++func mergeJSON[T any](in T, overrides ...map[string]any) (T, error) { ++ var out T ++ inJSON, err := json.Marshal(in) ++ if err != nil { ++ return out, err ++ } + -+ uint256 currentDay = block.timestamp / 1 days; -+ // Pattern borrowed from Reserve.sol -+ if (currentDay > lastLimitDay) { -+ lastLimitDay = currentDay; -+ tokenState.currentDaySellLimit = tokenState.dailySellLimit; -+ } ++ var tmpMap map[string]interface{} ++ if err := json.Unmarshal(inJSON, &tmpMap); err != nil { ++ return out, err ++ } + -+ return amountToBurn >= tokenState.currentDaySellLimit; -+ } ++ for _, override := range overrides { ++ for k, v := range override { ++ tmpMap[k] = v ++ } ++ } + -+ /** -+ * @notice Updates the current day limit for a token. -+ * @param token The address of the token to query. -+ * @param amountBurned the amount of the token that was burned. -+ */ -+ function updateLimits(address token, uint256 amountBurned) private { -+ TokenState storage tokenState = tokenStates[token]; ++ inJSON, err = json.Marshal(tmpMap) ++ if err != nil { ++ return out, err ++ } + -+ if (tokenState.dailySellLimit == 0) { -+ // if no limit set, assume uncapped -+ return; -+ } -+ tokenState.currentDaySellLimit = tokenState.currentDaySellLimit - amountBurned; -+ emit DailySellLimitUpdated(amountBurned); -+ } ++ if err := json.Unmarshal(inJSON, &out); err != nil { ++ return out, err ++ } + -+ /** -+ * @notice Allows owner to transfer tokens of this contract. It's meant for governance to -+ * trigger use cases not contemplated in this contract. -+ * @param token The address of the token to transfer. -+ * @param recipient The address of the recipient to transfer the tokens to. -+ * @param value The amount of tokens to transfer. -+ * @return A boolean indicating whether the transfer was successful or not. -+ */ -+ function transfer(address token, address recipient, uint256 value) external onlyOwner returns (bool) { -+ return IERC20(token).transfer(recipient, value); -+ } ++ return out, nil ++} ++ ++func mustHexBigFromHex(hex string) *hexutil.Big { ++ num := hexutil.MustDecodeBig(hex) ++ hexBig := hexutil.Big(*num) ++ return &hexBig ++} ++ ++func u64UtilPtr(in uint64) *hexutil.Uint64 { ++ util := hexutil.Uint64(in) ++ return &util ++} ++ ++func calculateBatchInboxAddr(chainID common.Hash) common.Address { ++ var out common.Address ++ copy(out[1:], crypto.Keccak256(chainID[:])[:19]) ++ return out +}
@@ -11019,9 +54253,9 @@
@@ -11036,7 +54270,7 @@
@@ -11046,110 +54280,54 @@
-
+92
+
+36
-0
-
diff --git OP/packages/contracts-bedrock/src/celo/FeeHandlerSeller.sol CELO/packages/contracts-bedrock/src/celo/FeeHandlerSeller.sol +
diff --git OP/op-chain-ops/deployer/state/deploy_config_test.go CELO/op-chain-ops/deployer/state/deploy_config_test.go new file mode 100644 -index 0000000000000000000000000000000000000000..4d22125af4d647021d77e0ed4b59d09049dd6bac +index 0000000000000000000000000000000000000000..be431b5740cea6df34ff143c8198b6266f4d5b2f --- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/FeeHandlerSeller.sol -@@ -0,0 +1,92 @@ -+// SPDX-License-Identifier: LGPL-3.0-only -+pragma solidity ^0.8.15; -+ -+import "./common/FixidityLib.sol"; -+import "../../lib/openzeppelin-contracts/contracts/access/Ownable.sol"; -+import "../../lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; -+import "./UsingRegistry.sol"; -+import "./common/Initializable.sol"; -+ -+// Abstract class for a FeeHandlerSeller, as defined in CIP-52 -+// https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0052.md -+abstract contract FeeHandlerSeller is Ownable, Initializable, UsingRegistry { -+ using FixidityLib for FixidityLib.Fraction; -+ -+ // Address of the token -+ // Minimal number of reports in SortedOracles contract -+ mapping(address => uint256) public minimumReports; -+ -+ event MinimumReportsSet(address tokenAddress, uint256 minimumReports); -+ event TokenSold(address soldTokenAddress, address boughtTokenAddress, uint256 amount); -+ -+ constructor(bool testingDeployment) Initializable(testingDeployment) { } -+ -+ function initialize( -+ address _registryAddress, -+ address[] calldata tokenAddresses, -+ uint256[] calldata newMininumReports -+ ) -+ external -+ initializer -+ { -+ _transferOwnership(msg.sender); -+ setRegistry(_registryAddress); -+ -+ for (uint256 i = 0; i < tokenAddresses.length; i++) { -+ _setMinimumReports(tokenAddresses[i], newMininumReports[i]); -+ } -+ } -+ -+ /** -+ * @notice Allows owner to set the minimum number of reports required. -+ * @param newMininumReports The new update minimum number of reports required. -+ */ -+ function setMinimumReports(address tokenAddress, uint256 newMininumReports) public onlyOwner { -+ _setMinimumReports(tokenAddress, newMininumReports); -+ } -+ -+ function _setMinimumReports(address tokenAddress, uint256 newMininumReports) internal { -+ minimumReports[tokenAddress] = newMininumReports; -+ emit MinimumReportsSet(tokenAddress, newMininumReports); -+ } ++++ CELO/op-chain-ops/deployer/state/deploy_config_test.go +@@ -0,0 +1,36 @@ ++package state + -+ /** -+ * @dev Calculates the minimum amount of tokens that should be received for the specified -+ * amount with the given mid-price and maximum slippage. -+ * @param midPriceNumerator The numerator of the mid-price for the token pair. -+ * @param midPriceDenominator The denominator of the mid-price for the token pair. -+ * @param amount The amount of tokens to be exchanged. -+ * @param maxSlippage The maximum slippage percentage as a fraction of the mid-price. -+ * @return The minimum amount of tokens that should be received as a uint256 value. -+ */ -+ function calculateMinAmount( -+ uint256 midPriceNumerator, -+ uint256 midPriceDenominator, -+ uint256 amount, -+ uint256 maxSlippage // as fraction -+ ) -+ public -+ pure -+ returns (uint256) -+ { -+ FixidityLib.Fraction memory maxSlippageFraction = FixidityLib.wrap(maxSlippage); ++import ( ++ "testing" + -+ FixidityLib.Fraction memory price = FixidityLib.newFixedFraction(midPriceNumerator, midPriceDenominator); -+ FixidityLib.Fraction memory amountFraction = FixidityLib.newFixed(amount); -+ FixidityLib.Fraction memory totalAmount = price.multiply(amountFraction); ++ "github.com/stretchr/testify/require" ++) + -+ return totalAmount.subtract(price.multiply(maxSlippageFraction).multiply(amountFraction)).fromFixed(); -+ } ++func TestMergeJSON(t *testing.T) { ++ type testStruct struct { ++ A string `json:"a"` ++ B int `json:"b"` ++ C bool `json:"c"` ++ } + -+ /** -+ * @notice Allows owner to transfer tokens of this contract. It's meant for governance to -+ * trigger use cases not contemplated in this contract. -+ * @param token The address of the token to transfer. -+ * @param amount The amount of tokens to transfer. -+ * @param to The address of the recipient to transfer the tokens to. -+ * @return A boolean indicating whether the transfer was successful or not. -+ */ -+ function transfer(address token, uint256 amount, address to) external onlyOwner returns (bool) { -+ return IERC20(token).transfer(to, amount); -+ } ++ out, err := mergeJSON( ++ testStruct{ ++ "hello", ++ 42, ++ true, ++ }, ++ map[string]any{ ++ "a": "world", ++ "c": false, ++ }, ++ map[string]any{ ++ "d": "shouldn't show up", ++ }, ++ ) ++ require.NoError(t, err) ++ require.EqualValues(t, out, testStruct{ ++ "world", ++ 42, ++ false, ++ }) +}
@@ -11157,9 +54335,9 @@
@@ -11174,7 +54352,7 @@
@@ -11184,300 +54362,391 @@
-
+272
+
+146
-0
-
diff --git OP/packages/contracts-bedrock/src/celo/GoldToken.sol CELO/packages/contracts-bedrock/src/celo/GoldToken.sol +
diff --git OP/op-chain-ops/deployer/state/intent.go CELO/op-chain-ops/deployer/state/intent.go new file mode 100644 -index 0000000000000000000000000000000000000000..e7236678670a7bedf86f7769ef74888dc5f2488c +index 0000000000000000000000000000000000000000..755ad6bbba541fa62e40672096d3dfed6eac6985 --- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/GoldToken.sol -@@ -0,0 +1,272 @@ -+// SPDX-License-Identifier: MIT -+pragma solidity ^0.8.15; ++++ CELO/op-chain-ops/deployer/state/intent.go +@@ -0,0 +1,146 @@ ++package state + -+import "../../lib/openzeppelin-contracts/contracts/access/Ownable.sol"; -+import "../../lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; ++import ( ++ "fmt" ++ "math/big" ++ "strings" + -+import "./UsingRegistry.sol"; -+import "./CalledByVm.sol"; -+import "./Initializable.sol"; -+import "./interfaces/ICeloToken.sol"; -+import "./common/interfaces/ICeloVersionedContract.sol"; ++ "github.com/ethereum-optimism/optimism/op-service/ioutil" ++ "github.com/ethereum-optimism/optimism/op-service/jsonutil" ++ "github.com/ethereum/go-ethereum/common" ++) + -+contract GoldToken is Initializable, CalledByVm, UsingRegistry, IERC20, ICeloToken, ICeloVersionedContract { -+ // Address of the TRANSFER precompiled contract. -+ // solhint-disable state-visibility -+ address constant TRANSFER = address(0xff - 2); -+ string constant NAME = "Celo native asset"; -+ string constant SYMBOL = "CELO"; -+ uint8 constant DECIMALS = 18; -+ uint256 internal totalSupply_; -+ // solhint-enable state-visibility ++var emptyAddress common.Address + -+ mapping(address => mapping(address => uint256)) internal allowed; ++type Intent struct { ++ L1ChainID uint64 `json:"l1ChainID" toml:"l1ChainID"` + -+ // Burn address is 0xdEaD because truffle is having buggy behaviour with the zero address -+ address constant BURN_ADDRESS = address(0x000000000000000000000000000000000000dEaD); ++ SuperchainRoles SuperchainRoles `json:"superchainRoles" toml:"superchainRoles"` + -+ event TransferComment(string comment); ++ UseFaultProofs bool `json:"useFaultProofs" toml:"useFaultProofs"` + -+ /** -+ * @notice Sets initialized == true on implementation contracts -+ * @param test Set to true to skip implementation initialization -+ */ -+ constructor(bool test) Initializable(test) { } ++ UseAltDA bool `json:"useAltDA" toml:"useAltDA"` + -+ /** -+ * @notice Returns the storage, major, minor, and patch version of the contract. -+ * @return Storage version of the contract. -+ * @return Major version of the contract. -+ * @return Minor version of the contract. -+ * @return Patch version of the contract. -+ */ -+ function getVersionNumber() external pure returns (uint256, uint256, uint256, uint256) { -+ return (1, 1, 2, 0); -+ } ++ FundDevAccounts bool `json:"fundDevAccounts" toml:"fundDevAccounts"` + -+ /** -+ * @notice Used in place of the constructor to allow the contract to be upgradable via proxy. -+ * @param registryAddress Address of the Registry contract. -+ */ -+ function initialize(address registryAddress) external initializer { -+ totalSupply_ = 0; -+ _transferOwnership(msg.sender); -+ setRegistry(registryAddress); -+ } ++ ContractArtifactsURL *ArtifactsURL `json:"contractArtifactsURL" toml:"contractArtifactsURL"` + -+ /** -+ * @notice Transfers CELO from one address to another. -+ * @param to The address to transfer CELO to. -+ * @param value The amount of CELO to transfer. -+ * @return True if the transaction succeeds. -+ */ -+ // solhint-disable-next-line no-simple-event-func-name -+ function transfer(address to, uint256 value) external returns (bool) { -+ return _transferWithCheck(to, value); -+ } ++ ContractsRelease string `json:"contractsVersion" toml:"contractsVersion"` + -+ /** -+ * @notice Transfers CELO from one address to another with a comment. -+ * @param to The address to transfer CELO to. -+ * @param value The amount of CELO to transfer. -+ * @param comment The transfer comment -+ * @return True if the transaction succeeds. -+ */ -+ function transferWithComment(address to, uint256 value, string calldata comment) external returns (bool) { -+ bool succeeded = _transferWithCheck(to, value); -+ emit TransferComment(comment); -+ return succeeded; -+ } ++ OPCMAddress common.Address `json:"opcmAddress" toml:"opcmAddress"` + -+ /** -+ * @notice This function allows a user to burn a specific amount of tokens. -+ * Burning is implemented by sending tokens to the burn address. -+ * @param value: The amount of CELO to burn. -+ * @return True if burn was successful. -+ */ -+ function burn(uint256 value) external returns (bool) { -+ // not using transferWithCheck as the burn address can potentially be the zero address -+ return _transfer(BURN_ADDRESS, value); -+ } ++ Chains []*ChainIntent `json:"chains" toml:"chains"` + -+ /** -+ * @notice Approve a user to transfer CELO on behalf of another user. -+ * @param spender The address which is being approved to spend CELO. -+ * @param value The amount of CELO approved to the spender. -+ * @return True if the transaction succeeds. -+ */ -+ function approve(address spender, uint256 value) external returns (bool) { -+ require(spender != address(0), "cannot set allowance for 0"); -+ allowed[msg.sender][spender] = value; -+ emit Approval(msg.sender, spender, value); -+ return true; -+ } ++ GlobalDeployOverrides map[string]any `json:"globalDeployOverrides" toml:"globalDeployOverrides"` ++} + -+ /** -+ * @notice Increases the allowance of another user. -+ * @param spender The address which is being approved to spend CELO. -+ * @param value The increment of the amount of CELO approved to the spender. -+ * @return True if the transaction succeeds. -+ */ -+ function increaseAllowance(address spender, uint256 value) external returns (bool) { -+ require(spender != address(0), "cannot set allowance for 0"); -+ uint256 oldValue = allowed[msg.sender][spender]; -+ uint256 newValue = oldValue + value; -+ allowed[msg.sender][spender] = newValue; -+ emit Approval(msg.sender, spender, newValue); -+ return true; -+ } ++func (c *Intent) L1ChainIDBig() *big.Int { ++ return big.NewInt(int64(c.L1ChainID)) ++} + -+ /** -+ * @notice Decreases the allowance of another user. -+ * @param spender The address which is being approved to spend CELO. -+ * @param value The decrement of the amount of CELO approved to the spender. -+ * @return True if the transaction succeeds. -+ */ -+ function decreaseAllowance(address spender, uint256 value) external returns (bool) { -+ uint256 oldValue = allowed[msg.sender][spender]; -+ uint256 newValue = oldValue - value; -+ allowed[msg.sender][spender] = newValue; -+ emit Approval(msg.sender, spender, newValue); -+ return true; -+ } ++func (c *Intent) Check() error { ++ if c.L1ChainID == 0 { ++ return fmt.Errorf("l1ChainID must be set") ++ } + -+ /** -+ * @notice Transfers CELO from one address to another on behalf of a user. -+ * @param from The address to transfer CELO from. -+ * @param to The address to transfer CELO to. -+ * @param value The amount of CELO to transfer. -+ * @return True if the transaction succeeds. -+ */ -+ function transferFrom(address from, address to, uint256 value) external returns (bool) { -+ require(to != address(0), "transfer attempted to reserved address 0x0"); -+ require(value <= balanceOf(from), "transfer value exceeded balance of sender"); -+ require(value <= allowed[from][msg.sender], "transfer value exceeded sender's allowance for spender"); ++ if c.UseFaultProofs && c.UseAltDA { ++ return fmt.Errorf("cannot use both fault proofs and alt-DA") ++ } + -+ bool success; -+ (success,) = TRANSFER.call{ value: 0, gas: gasleft() }(abi.encode(from, to, value)); -+ require(success, "CELO transfer failed"); ++ if c.SuperchainRoles.ProxyAdminOwner == emptyAddress { ++ return fmt.Errorf("proxyAdminOwner must be set") ++ } + -+ allowed[from][msg.sender] = allowed[from][msg.sender] - value; -+ emit Transfer(from, to, value); -+ return true; -+ } ++ if c.SuperchainRoles.ProtocolVersionsOwner == emptyAddress { ++ c.SuperchainRoles.ProtocolVersionsOwner = c.SuperchainRoles.ProxyAdminOwner ++ } + -+ /** -+ * @notice Mints new CELO and gives it to 'to'. -+ * @param to The account for which to mint tokens. -+ * @param value The amount of CELO to mint. -+ */ -+ function mint(address to, uint256 value) external onlyVm returns (bool) { -+ if (value == 0) { -+ return true; -+ } ++ if c.SuperchainRoles.Guardian == emptyAddress { ++ c.SuperchainRoles.Guardian = c.SuperchainRoles.ProxyAdminOwner ++ } + -+ require(to != address(0), "mint attempted to reserved address 0x0"); -+ totalSupply_ = totalSupply_ + value; ++ if c.ContractArtifactsURL == nil { ++ return fmt.Errorf("contractArtifactsURL must be set") ++ } + -+ bool success; -+ (success,) = TRANSFER.call{ value: 0, gas: gasleft() }(abi.encode(address(0), to, value)); -+ require(success, "CELO transfer failed"); ++ if c.ContractsRelease != "dev" && !strings.HasPrefix(c.ContractsRelease, "op-contracts/") { ++ return fmt.Errorf("contractsVersion must be either the literal \"dev\" or start with \"op-contracts/\"") ++ } + -+ emit Transfer(address(0), to, value); -+ return true; -+ } ++ return nil ++} + -+ /** -+ * @return The name of the CELO token. -+ */ -+ function name() external pure returns (string memory) { -+ return NAME; -+ } ++func (c *Intent) Chain(id common.Hash) (*ChainIntent, error) { ++ for i := range c.Chains { ++ if c.Chains[i].ID == id { ++ return c.Chains[i], nil ++ } ++ } + -+ /** -+ * @return The symbol of the CELO token. -+ */ -+ function symbol() external pure returns (string memory) { -+ return SYMBOL; -+ } ++ return nil, fmt.Errorf("chain %d not found", id) ++} + -+ /** -+ * @return The number of decimal places to which CELO is divisible. -+ */ -+ function decimals() external pure returns (uint8) { -+ return DECIMALS; -+ } ++func (c *Intent) WriteToFile(path string) error { ++ return jsonutil.WriteTOML(c, ioutil.ToAtomicFile(path, 0o755)) ++} + -+ /** -+ * @return The total amount of CELO in existence, including what the burn address holds. -+ */ -+ function totalSupply() external view returns (uint256) { -+ return totalSupply_; -+ } ++type SuperchainRoles struct { ++ ProxyAdminOwner common.Address `json:"proxyAdminOwner" toml:"proxyAdminOwner"` + -+ /** -+ * @return The total amount of CELO in existence, not including what the burn address holds. -+ */ -+ function circulatingSupply() external view returns (uint256) { -+ return totalSupply_ - getBurnedAmount() - balanceOf(address(0)); -+ } ++ ProtocolVersionsOwner common.Address `json:"protocolVersionsOwner" toml:"protocolVersionsOwner"` + -+ /** -+ * @notice Gets the amount of owner's CELO allowed to be spent by spender. -+ * @param owner The owner of the CELO. -+ * @param spender The spender of the CELO. -+ * @return The amount of CELO owner is allowing spender to spend. -+ */ -+ function allowance(address owner, address spender) external view returns (uint256) { -+ return allowed[owner][spender]; -+ } ++ Guardian common.Address `json:"guardian" toml:"guardian"` ++} + -+ /** -+ * @notice Increases the variable for total amount of CELO in existence. -+ * @param amount The amount to increase counter by -+ */ -+ function increaseSupply(uint256 amount) external onlyVm { -+ totalSupply_ = totalSupply_ + amount; -+ } ++type ChainIntent struct { ++ ID common.Hash `json:"id" toml:"id"` + -+ /** -+ * @notice Gets the amount of CELO that has been burned. -+ * @return The total amount of Celo that has been sent to the burn address. -+ */ -+ function getBurnedAmount() public view returns (uint256) { -+ return balanceOf(BURN_ADDRESS); -+ } ++ Roles ChainRoles `json:"roles" toml:"roles"` + -+ /** -+ * @notice Gets the balance of the specified address. -+ * @param owner The address to query the balance of. -+ * @return The balance of the specified address. -+ */ -+ function balanceOf(address owner) public view returns (uint256) { -+ return owner.balance; -+ } ++ DeployOverrides map[string]any `json:"deployOverrides" toml:"deployOverrides"` ++} + -+ /** -+ * @notice internal CELO transfer from one address to another. -+ * @param to The address to transfer CELO to. -+ * @param value The amount of CELO to transfer. -+ * @return True if the transaction succeeds. -+ */ -+ function _transfer(address to, uint256 value) internal returns (bool) { -+ require(value <= balanceOf(msg.sender), "transfer value exceeded balance of sender"); ++type ChainRoles struct { ++ ProxyAdminOwner common.Address `json:"proxyAdminOwner" toml:"proxyAdminOwner"` + -+ bool success; -+ (success,) = TRANSFER.call{ value: 0, gas: gasleft() }(abi.encode(msg.sender, to, value)); -+ require(success, "CELO transfer failed"); -+ emit Transfer(msg.sender, to, value); -+ return true; -+ } ++ SystemConfigOwner common.Address `json:"systemConfigOwner" toml:"systemConfigOwner"` ++ ++ GovernanceTokenOwner common.Address `json:"governanceTokenOwner" toml:"governanceTokenOwner"` ++ ++ UnsafeBlockSigner common.Address `json:"unsafeBlockSigner" toml:"unsafeBlockSigner"` ++ ++ Batcher common.Address `json:"batcher" toml:"batcher"` ++ ++ Proposer common.Address `json:"proposer" toml:"proposer"` ++ ++ Challenger common.Address `json:"challenger" toml:"challenger"` ++} ++ ++func (c *ChainIntent) Check() error { ++ var emptyHash common.Hash ++ if c.ID == emptyHash { ++ return fmt.Errorf("id must be set") ++ } ++ ++ if c.Roles.ProxyAdminOwner == emptyAddress { ++ return fmt.Errorf("proxyAdminOwner must be set") ++ } ++ ++ if c.Roles.SystemConfigOwner == emptyAddress { ++ c.Roles.SystemConfigOwner = c.Roles.ProxyAdminOwner ++ } ++ ++ if c.Roles.GovernanceTokenOwner == emptyAddress { ++ c.Roles.GovernanceTokenOwner = c.Roles.ProxyAdminOwner ++ } ++ ++ if c.Roles.UnsafeBlockSigner == emptyAddress { ++ return fmt.Errorf("unsafeBlockSigner must be set") ++ } ++ ++ if c.Roles.Batcher == emptyAddress { ++ return fmt.Errorf("batcher must be set") ++ } ++ ++ return nil ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+119
+
-0
+ +
+ +
+
+
diff --git OP/op-chain-ops/deployer/state/state.go CELO/op-chain-ops/deployer/state/state.go +new file mode 100644 +index 0000000000000000000000000000000000000000..674e06d743a0e16223a2ce3be091c251273af873 +--- /dev/null ++++ CELO/op-chain-ops/deployer/state/state.go +@@ -0,0 +1,119 @@ ++package state ++ ++import ( ++ "bytes" ++ "compress/gzip" ++ "encoding/json" ++ "fmt" ++ ++ "github.com/ethereum/go-ethereum/core/types" ++ ++ "github.com/ethereum-optimism/optimism/op-chain-ops/foundry" ++ "github.com/ethereum-optimism/optimism/op-service/ioutil" ++ "github.com/ethereum-optimism/optimism/op-service/jsonutil" ++ "github.com/ethereum/go-ethereum/common" ++) ++ ++// State contains the data needed to recreate the deployment ++// as it progresses and once it is fully applied. ++type State struct { ++ // Version versions the state so we can update it later. ++ Version int `json:"version"` ++ ++ // Create2Salt is the salt used for CREATE2 deployments. ++ Create2Salt common.Hash `json:"create2Salt"` ++ ++ // AppliedIntent contains the chain intent that was last ++ // successfully applied. It is diffed against new intent ++ // in order to determine what deployment steps to take. ++ // This field is nil for new deployments. ++ AppliedIntent *Intent `json:"appliedIntent"` ++ ++ // SuperchainDeployment contains the addresses of the Superchain ++ // deployment. It only contains the proxies because the implementations ++ // can be looked up on chain. ++ SuperchainDeployment *SuperchainDeployment `json:"superchainDeployment"` ++ ++ // ImplementationsDeployment contains the addresses of the common implementation ++ // contracts required for the Superchain to function. ++ ImplementationsDeployment *ImplementationsDeployment `json:"implementationsDeployment"` ++ ++ // Chains contains data about L2 chain deployments. ++ Chains []*ChainState `json:"opChainDeployments"` ++} ++ ++func (s *State) WriteToFile(path string) error { ++ return jsonutil.WriteJSON(s, ioutil.ToAtomicFile(path, 0o755)) ++} ++ ++func (s *State) Chain(id common.Hash) (*ChainState, error) { ++ for _, chain := range s.Chains { ++ if chain.ID == id { ++ return chain, nil ++ } ++ } ++ return nil, fmt.Errorf("chain not found: %s", id.Hex()) ++} ++ ++type SuperchainDeployment struct { ++ ProxyAdminAddress common.Address `json:"proxyAdminAddress"` ++ SuperchainConfigProxyAddress common.Address `json:"superchainConfigProxyAddress"` ++ SuperchainConfigImplAddress common.Address `json:"superchainConfigImplAddress"` ++ ProtocolVersionsProxyAddress common.Address `json:"protocolVersionsProxyAddress"` ++ ProtocolVersionsImplAddress common.Address `json:"protocolVersionsImplAddress"` ++ StateDump *foundry.ForgeAllocs `json:"stateDump"` ++} ++ ++type ImplementationsDeployment struct { ++ OpcmProxyAddress common.Address `json:"opcmProxyAddress"` ++ DelayedWETHImplAddress common.Address `json:"delayedWETHImplAddress"` ++ OptimismPortalImplAddress common.Address `json:"optimismPortalImplAddress"` ++ PreimageOracleSingletonAddress common.Address `json:"preimageOracleSingletonAddress"` ++ MipsSingletonAddress common.Address `json:"mipsSingletonAddress"` ++ SystemConfigImplAddress common.Address `json:"systemConfigImplAddress"` ++ L1CrossDomainMessengerImplAddress common.Address `json:"l1CrossDomainMessengerImplAddress"` ++ L1ERC721BridgeImplAddress common.Address `json:"l1ERC721BridgeImplAddress"` ++ L1StandardBridgeImplAddress common.Address `json:"l1StandardBridgeImplAddress"` ++ OptimismMintableERC20FactoryImplAddress common.Address `json:"optimismMintableERC20FactoryImplAddress"` ++ DisputeGameFactoryImplAddress common.Address `json:"disputeGameFactoryImplAddress"` ++ StateDump *foundry.ForgeAllocs `json:"stateDump"` ++} ++ ++type ChainState struct { ++ ID common.Hash `json:"id"` ++ ++ ProxyAdminAddress common.Address `json:"proxyAdminAddress"` ++ AddressManagerAddress common.Address `json:"addressManagerAddress"` ++ L1ERC721BridgeProxyAddress common.Address `json:"l1ERC721BridgeProxyAddress"` ++ SystemConfigProxyAddress common.Address `json:"systemConfigProxyAddress"` ++ OptimismMintableERC20FactoryProxyAddress common.Address `json:"optimismMintableERC20FactoryProxyAddress"` ++ L1StandardBridgeProxyAddress common.Address `json:"l1StandardBridgeProxyAddress"` ++ L1CrossDomainMessengerProxyAddress common.Address `json:"l1CrossDomainMessengerProxyAddress"` ++ OptimismPortalProxyAddress common.Address `json:"optimismPortalProxyAddress"` ++ DisputeGameFactoryProxyAddress common.Address `json:"disputeGameFactoryProxyAddress"` ++ AnchorStateRegistryProxyAddress common.Address `json:"anchorStateRegistryProxyAddress"` ++ AnchorStateRegistryImplAddress common.Address `json:"anchorStateRegistryImplAddress"` ++ FaultDisputeGameAddress common.Address `json:"faultDisputeGameAddress"` ++ PermissionedDisputeGameAddress common.Address `json:"permissionedDisputeGameAddress"` ++ DelayedWETHPermissionedGameProxyAddress common.Address `json:"delayedWETHPermissionedGameProxyAddress"` ++ DelayedWETHPermissionlessGameProxyAddress common.Address `json:"delayedWETHPermissionlessGameProxyAddress"` ++ ++ Allocs Base64Bytes `json:"allocs"` ++ ++ StartBlock *types.Header `json:"startBlock"` ++} ++ ++func (c *ChainState) UnmarshalAllocs() (*foundry.ForgeAllocs, error) { ++ gr, err := gzip.NewReader(bytes.NewReader(c.Allocs)) ++ if err != nil { ++ return nil, fmt.Errorf("failed to create gzip reader: %w", err) ++ } ++ defer gr.Close() ++ ++ var allocs foundry.ForgeAllocs ++ if err := json.NewDecoder(gr).Decode(&allocs); err != nil { ++ return nil, fmt.Errorf("failed to decode allocs: %w", err) ++ } ++ ++ return &allocs, nil ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+6
+
-0
+ +
+ +
+
+
diff --git OP/op-chain-ops/deployer/version/version.go CELO/op-chain-ops/deployer/version/version.go +new file mode 100644 +index 0000000000000000000000000000000000000000..2456f656d45c15c1df43d737ad62344ff5d84081 +--- /dev/null ++++ CELO/op-chain-ops/deployer/version/version.go +@@ -0,0 +1,6 @@ ++package version + -+ /** -+ * @notice Internal CELO transfer from one address to another. -+ * @param to The address to transfer CELO to. Zero address will revert. -+ * @param value The amount of CELO to transfer. -+ * @return True if the transaction succeeds. -+ */ -+ function _transferWithCheck(address to, uint256 value) internal returns (bool) { -+ require(to != address(0), "transfer attempted to reserved address 0x0"); -+ return _transfer(to, value); -+ } -+}
++var ( ++ Version = "v0.0.0" ++ Meta = "dev" ++)
@@ -11486,13 +54755,13 @@
- (new) + OP
@@ -11502,46 +54771,101 @@
-
+18
-
-0
+
+26
+
-3
-
diff --git OP/packages/contracts-bedrock/src/celo/Initializable.sol CELO/packages/contracts-bedrock/src/celo/Initializable.sol -new file mode 100644 -index 0000000000000000000000000000000000000000..7929728eef4ed9063c81aea6f2a0a1758d4ef728 ---- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/Initializable.sol -@@ -0,0 +1,18 @@ -+// SPDX-License-Identifier: LGPL-3.0-only -+pragma solidity ^0.8.15; -+ -+contract Initializable { -+ bool public initialized; +
diff --git OP/op-chain-ops/devkeys/devkeys.go CELO/op-chain-ops/devkeys/devkeys.go +index b4fefe04e59807c9927396a29797966fa0f73077..d0526c8c1d3a400e9953ab6be6137fe2ce1a394d 100644 +--- OP/op-chain-ops/devkeys/devkeys.go ++++ CELO/op-chain-ops/devkeys/devkeys.go +@@ -49,28 +49,47 @@ return ChainUserKey{ChainID: chainID, Index: index} + } + } +  ++type Role interface { ++ Key(chainID *big.Int) Key ++} + -+ modifier initializer() { -+ require(!initialized, "contract already initialized"); -+ initialized = true; -+ _; -+ } + // SuperchainOperatorRole identifies an account used in the operations of superchain contracts + type SuperchainOperatorRole uint64 +  + const ( + // SuperchainDeployerKey is the deployer of the superchain contracts. + SuperchainDeployerKey SuperchainOperatorRole = 0 ++ // SuperchainProxyAdminOwner is the key that owns the superchain ProxyAdmin ++ SuperchainProxyAdminOwner SuperchainOperatorRole = 1 + // SuperchainConfigGuardianKey is the Guardian of the SuperchainConfig. +- SuperchainConfigGuardianKey SuperchainOperatorRole = 1 ++ SuperchainConfigGuardianKey SuperchainOperatorRole = 2 ++ // SuperchainProtocolVersionsOwner is the key that can make ProtocolVersions changes. ++ SuperchainProtocolVersionsOwner SuperchainOperatorRole = 3 + // DependencySetManagerKey is the key used to manage the dependency set of a superchain. +- DependencySetManagerKey SuperchainOperatorRole = 2 ++ DependencySetManagerKey SuperchainOperatorRole = 4 + ) +  + func (role SuperchainOperatorRole) String() string { + switch role { + case SuperchainDeployerKey: + return "superchain-deployer" ++ case SuperchainProxyAdminOwner: ++ return "superchain-proxy-admin-owner" + case SuperchainConfigGuardianKey: + return "superchain-config-guardian" ++ case SuperchainProtocolVersionsOwner: ++ return "superchain-protocol-versions-owner" + case DependencySetManagerKey: + return "dependency-set-manager" + default: + return fmt.Sprintf("unknown-superchain-%d", uint64(role)) ++ } ++} + -+ constructor(bool testingDeployment) { -+ if (!testingDeployment) { -+ initialized = true; -+ } -+ } -+}
++func (role SuperchainOperatorRole) Key(chainID *big.Int) Key { ++ return &SuperchainOperatorKey{ ++ ChainID: chainID, ++ Role: role, + } + } +  +@@ -122,6 +141,8 @@ // L1FeeVaultRecipientRole is the key that receives from the L1FeeVault predeploy + L1FeeVaultRecipientRole ChainOperatorRole = 8 + // SequencerFeeVaultRecipientRole is the key that receives form the SequencerFeeVault predeploy + SequencerFeeVaultRecipientRole ChainOperatorRole = 9 ++ // SystemConfigOwner is the key that can make SystemConfig changes. ++ SystemConfigOwner ChainOperatorRole = 10 + ) +  + func (role ChainOperatorRole) String() string { +@@ -146,12 +167,14 @@ case L1FeeVaultRecipientRole: + return "l1-fee-vault-recipient" + case SequencerFeeVaultRecipientRole: + return "sequencer-fee-vault-recipient" ++ case SystemConfigOwner: ++ return "system-config-owner" + default: + return fmt.Sprintf("unknown-operator-%d", uint64(role)) + } + } +  +-func (role ChainOperatorRole) Key(chainID *big.Int) *ChainOperatorKey { ++func (role ChainOperatorRole) Key(chainID *big.Int) Key { + return &ChainOperatorKey{ + ChainID: chainID, + Role: role,
@@ -11550,13 +54874,13 @@
- (new) + OP
@@ -11566,113 +54890,37 @@
-
+85
+
+4
-0
-
diff --git OP/packages/contracts-bedrock/src/celo/MentoFeeHandlerSeller.sol CELO/packages/contracts-bedrock/src/celo/MentoFeeHandlerSeller.sol -new file mode 100644 -index 0000000000000000000000000000000000000000..e5a9ff455f391f797bbc2ace5101c0ef58c3c192 ---- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/MentoFeeHandlerSeller.sol -@@ -0,0 +1,85 @@ -+// SPDX-License-Identifier: MIT -+pragma solidity ^0.8.15; -+ -+import "../../lib/openzeppelin-contracts/contracts/access/Ownable.sol"; -+import "../../lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; -+ -+import "./interfaces/IStableTokenMento.sol"; -+ -+import "./common/interfaces/IFeeHandlerSeller.sol"; -+import "./stability/interfaces/ISortedOracles.sol"; -+import "./common/FixidityLib.sol"; -+import "./common/Initializable.sol"; -+ -+import "./FeeHandlerSeller.sol"; -+ -+// An implementation of FeeHandlerSeller supporting interfaces compatible with -+// Mento -+// See https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0052.md -+contract MentoFeeHandlerSeller is FeeHandlerSeller { -+ using FixidityLib for FixidityLib.Fraction; -+ -+ /** -+ * @notice Sets initialized == true on implementation contracts. -+ * @param test Set to true to skip implementation initialisation. -+ */ -+ constructor(bool test) FeeHandlerSeller(test) { } -+ -+ // without this line the contract can't receive native Celo transfers -+ receive() external payable { } -+ -+ /** -+ * @notice Returns the storage, major, minor, and patch version of the contract. -+ * @return Storage version of the contract. -+ * @return Major version of the contract. -+ * @return Minor version of the contract. -+ * @return Patch version of the contract. -+ */ -+ function getVersionNumber() external pure returns (uint256, uint256, uint256, uint256) { -+ return (1, 1, 0, 0); -+ } -+ -+ function sell( -+ address sellTokenAddress, -+ address buyTokenAddress, -+ uint256 amount, -+ uint256 maxSlippage // as fraction, -+ ) -+ external -+ returns (uint256) -+ { -+ require( -+ buyTokenAddress == registry.getAddressForOrDie(GOLD_TOKEN_REGISTRY_ID), "Buy token can only be gold token" -+ ); -+ -+ IStableTokenMento stableToken = IStableTokenMento(sellTokenAddress); -+ require(amount <= stableToken.balanceOf(address(this)), "Balance of token to burn not enough"); -+ -+ address exchangeAddress = registry.getAddressForOrDie(stableToken.getExchangeRegistryId()); -+ -+ IExchange exchange = IExchange(exchangeAddress); -+ -+ uint256 minAmount = 0; -+ -+ ISortedOracles sortedOracles = getSortedOracles(); -+ -+ require( -+ sortedOracles.numRates(sellTokenAddress) >= minimumReports[sellTokenAddress], -+ "Number of reports for token not enough" -+ ); -+ -+ (uint256 rateNumerator, uint256 rateDenominator) = sortedOracles.medianRate(sellTokenAddress); -+ minAmount = calculateMinAmount(rateNumerator, rateDenominator, amount, maxSlippage); -+ -+ // TODO an upgrade would be to compare using routers as well -+ stableToken.approve(exchangeAddress, amount); -+ exchange.sell(amount, minAmount, false); -+ -+ IERC20 goldToken = getGoldToken(); -+ uint256 celoAmount = goldToken.balanceOf(address(this)); -+ goldToken.transfer(msg.sender, celoAmount); +
diff --git OP/op-chain-ops/foundry/allocs.go CELO/op-chain-ops/foundry/allocs.go +index b7300511431d962095978f79bf642b05c871014d..af0c28f4faf00483607741e731f55bf4f2cb0e51 100644 +--- OP/op-chain-ops/foundry/allocs.go ++++ CELO/op-chain-ops/foundry/allocs.go +@@ -82,6 +82,10 @@ maps.Copy(out, d.Accounts) + return &ForgeAllocs{Accounts: out} + } +  ++func (d ForgeAllocs) MarshalJSON() ([]byte, error) { ++ return json.Marshal(d.Accounts) ++} + -+ emit TokenSold(sellTokenAddress, buyTokenAddress, amount); -+ return celoAmount; -+ } -+}
+ func (d *ForgeAllocs) UnmarshalJSON(b []byte) error { + // forge, since integrating Alloy, likes to hex-encode everything. + type forgeAllocAccount struct {
@@ -11681,13 +54929,13 @@
- (new) + OP
@@ -11697,364 +54945,613 @@
-
+336
+
+23
-0
-
diff --git OP/packages/contracts-bedrock/src/celo/StableTokenV2.sol CELO/packages/contracts-bedrock/src/celo/StableTokenV2.sol -new file mode 100644 -index 0000000000000000000000000000000000000000..68632df65abc9d352de50b7f273afc491ff8a1b2 ---- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/StableTokenV2.sol -@@ -0,0 +1,336 @@ -+// SPDX-License-Identifier: MIT -+pragma solidity ^0.8.15; -+ -+import { ERC20PermitUpgradeable } from -+ "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/draft-ERC20PermitUpgradeable.sol"; -+import { ERC20Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol"; -+import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; -+ -+import { IStableTokenV2 } from "./interfaces/IStableToken.sol"; -+import { CalledByVm } from "./CalledByVm.sol"; -+ -+/** -+ * @title ERC20 token with minting and burning permissioned to a broker and validators. -+ */ -+contract StableTokenV2 is IStableTokenV2, ERC20PermitUpgradeable, CalledByVm, OwnableUpgradeable { -+ address public validators; -+ address public broker; -+ address public exchange; -+ -+ event TransferComment(string comment); -+ event BrokerUpdated(address broker); -+ event ValidatorsUpdated(address validators); -+ event ExchangeUpdated(address exchange); -+ -+ /** -+ * @dev Restricts a function so it can only be executed by an address that's allowed to mint. -+ * Currently that's the broker, validators, or exchange. -+ */ -+ modifier onlyMinter() { -+ address sender = _msgSender(); -+ require(sender == broker || sender == validators || sender == exchange, "StableTokenV2: not allowed to mint"); -+ _; -+ } -+ -+ /** -+ * @dev Restricts a function so it can only be executed by an address that's allowed to burn. -+ * Currently that's the broker or exchange. -+ */ -+ modifier onlyBurner() { -+ address sender = _msgSender(); -+ require(sender == broker || sender == exchange, "StableTokenV2: not allowed to burn"); -+ _; -+ } -+ -+ /** -+ * @notice The constructor for the StableTokenV2 contract. -+ * @dev Should be called with disable=true in deployments when -+ * it's accessed through a Proxy. -+ * Call this with disable=false during testing, when used -+ * without a proxy. -+ * @param disable Set to true to run `_disableInitializers()` inherited from -+ * openzeppelin-contracts-upgradeable/Initializable.sol -+ */ -+ constructor(bool disable) { -+ if (disable) { -+ _disableInitializers(); -+ } -+ } -+ -+ /** -+ * @notice Initializes a StableTokenV2. -+ * It keeps the same signature as the original initialize() function -+ * in legacy/StableToken.sol -+ * @param _name The name of the stable token (English) -+ * @param _symbol A short symbol identifying the token (e.g. "cUSD") -+ * @param initialBalanceAddresses Array of addresses with an initial balance. -+ * @param initialBalanceValues Array of balance values corresponding to initialBalanceAddresses. -+ * deprecated-param exchangeIdentifier String identifier of exchange in registry (for specific fiat pairs) -+ */ -+ function initialize( -+ // slither-disable-start shadowing-local -+ string calldata _name, -+ string calldata _symbol, -+ // slither-disable-end shadowing-local -+ address[] calldata initialBalanceAddresses, -+ uint256[] calldata initialBalanceValues -+ ) -+ external -+ initializer -+ { -+ __ERC20_init_unchained(_name, _symbol); -+ __ERC20Permit_init(_symbol); -+ _transferOwnership(_msgSender()); -+ -+ require(initialBalanceAddresses.length == initialBalanceValues.length, "Array length mismatch"); -+ for (uint256 i = 0; i < initialBalanceAddresses.length; i += 1) { -+ _mint(initialBalanceAddresses[i], initialBalanceValues[i]); -+ } -+ } -+ -+ /** -+ * @notice Initializes a StableTokenV2 contract -+ * when upgrading from legacy/StableToken.sol. -+ * It sets the addresses that were previously read from the Registry. -+ * It runs the ERC20PermitUpgradeable initializer. -+ * @dev This function is only callable once. -+ * @param _broker The address of the Broker contract. -+ * @param _validators The address of the Validators contract. -+ * @param _exchange The address of the Exchange contract. -+ */ -+ function initializeV2( -+ address _broker, -+ address _validators, -+ address _exchange -+ ) -+ external -+ reinitializer(2) -+ onlyOwner -+ { -+ _setBroker(_broker); -+ _setValidators(_validators); -+ _setExchange(_exchange); -+ __ERC20Permit_init(symbol()); -+ } -+ -+ /** -+ * @notice Sets the address of the Broker contract. -+ * @dev This function is only callable by the owner. -+ * @param _broker The address of the Broker contract. -+ */ -+ function setBroker(address _broker) external onlyOwner { -+ _setBroker(_broker); -+ } -+ -+ /** -+ * @notice Sets the address of the Validators contract. -+ * @dev This function is only callable by the owner. -+ * @param _validators The address of the Validators contract. -+ */ -+ function setValidators(address _validators) external onlyOwner { -+ _setValidators(_validators); -+ } -+ -+ /** -+ * @notice Sets the address of the Exchange contract. -+ * @dev This function is only callable by the owner. -+ * @param _exchange The address of the Exchange contract. -+ */ -+ function setExchange(address _exchange) external onlyOwner { -+ _setExchange(_exchange); -+ } -+ -+ /** -+ * @notice Transfer token for a specified address -+ * @param to The address to transfer to. -+ * @param value The amount to be transferred. -+ * @param comment The transfer comment. -+ * @return True if the transaction succeeds. -+ */ -+ function transferWithComment(address to, uint256 value, string calldata comment) external returns (bool) { -+ emit TransferComment(comment); -+ return transfer(to, value); -+ } -+ -+ /** -+ * @notice Mints new StableToken and gives it to 'to'. -+ * @param to The account for which to mint tokens. -+ * @param value The amount of StableToken to mint. -+ */ -+ function mint(address to, uint256 value) external onlyMinter returns (bool) { -+ _mint(to, value); -+ return true; -+ } -+ -+ /** -+ * @notice Burns StableToken from the balance of msg.sender. -+ * @param value The amount of StableToken to burn. -+ */ -+ function burn(uint256 value) external onlyBurner returns (bool) { -+ _burn(msg.sender, value); -+ return true; -+ } -+ -+ /** -+ * @notice Set the address of the Broker contract and emit an event -+ * @param _broker The address of the Broker contract. -+ */ -+ function _setBroker(address _broker) internal { -+ broker = _broker; -+ emit BrokerUpdated(_broker); -+ } -+ -+ /** -+ * @notice Set the address of the Validators contract and emit an event -+ * @param _validators The address of the Validators contract. -+ */ -+ function _setValidators(address _validators) internal { -+ validators = _validators; -+ emit ValidatorsUpdated(_validators); -+ } -+ -+ /** -+ * @notice Set the address of the Exchange contract and emit an event -+ * @param _exchange The address of the Exchange contract. -+ */ -+ function _setExchange(address _exchange) internal { -+ exchange = _exchange; -+ emit ExchangeUpdated(_exchange); -+ } -+ -+ /// @inheritdoc ERC20Upgradeable -+ function transferFrom( -+ address from, -+ address to, -+ uint256 amount -+ ) -+ public -+ override(ERC20Upgradeable, IStableTokenV2) -+ returns (bool) -+ { -+ return ERC20Upgradeable.transferFrom(from, to, amount); -+ } -+ -+ /// @inheritdoc ERC20Upgradeable -+ function transfer(address to, uint256 amount) public override(ERC20Upgradeable, IStableTokenV2) returns (bool) { -+ return ERC20Upgradeable.transfer(to, amount); -+ } -+ -+ /// @inheritdoc ERC20Upgradeable -+ function balanceOf(address account) public view override(ERC20Upgradeable, IStableTokenV2) returns (uint256) { -+ return ERC20Upgradeable.balanceOf(account); -+ } -+ -+ /// @inheritdoc ERC20Upgradeable -+ function approve( -+ address spender, -+ uint256 amount -+ ) -+ public -+ override(ERC20Upgradeable, IStableTokenV2) -+ returns (bool) -+ { -+ return ERC20Upgradeable.approve(spender, amount); -+ } -+ -+ /// @inheritdoc ERC20Upgradeable -+ function allowance( -+ address owner, -+ address spender -+ ) -+ public -+ view -+ override(ERC20Upgradeable, IStableTokenV2) -+ returns (uint256) -+ { -+ return ERC20Upgradeable.allowance(owner, spender); -+ } +
diff --git OP/op-chain-ops/foundry/allocs_test.go CELO/op-chain-ops/foundry/allocs_test.go +index a11d69fa9eff1b4449efbc62b0e96e9f5a1fbf35..6d19557016cb9feabcc6d84989d4dca27418e48c 100644 +--- OP/op-chain-ops/foundry/allocs_test.go ++++ CELO/op-chain-ops/foundry/allocs_test.go +@@ -1,6 +1,8 @@ + package foundry +  + import ( ++ "encoding/json" ++ "math/big" + "os" + "testing" +  +@@ -96,3 +98,24 @@ allocs.Accounts[contract].Storage[crypto.Keccak256Hash([]byte("hello"))]) + require.Equal(t, "0", allocs.Accounts[contract].Balance.String()) + require.Equal(t, uint64(30), allocs.Accounts[contract].Nonce) + } + -+ /// @inheritdoc ERC20Upgradeable -+ function totalSupply() public view override(ERC20Upgradeable, IStableTokenV2) returns (uint256) { -+ return ERC20Upgradeable.totalSupply(); -+ } ++func TestForgeAllocs_Marshaling(t *testing.T) { ++ data := &ForgeAllocs{ ++ Accounts: map[common.Address]types.Account{ ++ common.HexToAddress("0x12345"): { ++ Balance: big.NewInt(12345), ++ Code: []byte{0x01, 0x02, 0x03}, ++ Nonce: 123, ++ Storage: map[common.Hash]common.Hash{ ++ common.HexToHash("0x12345"): common.HexToHash("0x12345"), ++ }, ++ }, ++ }, ++ } + -+ /// @inheritdoc ERC20PermitUpgradeable -+ function permit( -+ address owner, -+ address spender, -+ uint256 value, -+ uint256 deadline, -+ uint8 v, -+ bytes32 r, -+ bytes32 s -+ ) -+ public -+ override(ERC20PermitUpgradeable, IStableTokenV2) -+ { -+ ERC20PermitUpgradeable.permit(owner, spender, value, deadline, v, r, s); -+ } ++ out, err := json.Marshal(data) ++ require.NoError(t, err) + -+ /** -+ * @notice Reserve balance for making payments for gas in this StableToken currency. -+ * @param from The account to reserve balance from -+ * @param value The amount of balance to reserve -+ * @dev Note that this function is called by the protocol when paying for tx fees in this -+ * currency. After the tx is executed, gas is refunded to the sender and credited to the -+ * various tx fee recipients via a call to `creditGasFees`. -+ */ -+ function debitGasFees(address from, uint256 value) external onlyVm { -+ _burn(from, value); -+ } ++ var in ForgeAllocs ++ require.NoError(t, json.Unmarshal(out, &in)) ++}
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+3
+
-3
+ +
+ +
+
+
diff --git OP/op-chain-ops/foundry/artifactsfs.go CELO/op-chain-ops/foundry/artifactsfs.go +index 2b5599c85c2029f026693f63fb24c9c661bb08d7..13229c41bc069e53965d9a0f5dfbc049d8b03062 100644 +--- OP/op-chain-ops/foundry/artifactsfs.go ++++ CELO/op-chain-ops/foundry/artifactsfs.go +@@ -9,14 +9,14 @@ "path" + "strings" + ) +  +-type statDirFs interface { ++type StatDirFs interface { + fs.StatFS + fs.ReadDirFS + } +  + func OpenArtifactsDir(dirPath string) *ArtifactsFS { + dir := os.DirFS(dirPath) +- if d, ok := dir.(statDirFs); !ok { ++ if d, ok := dir.(StatDirFs); !ok { + panic("Go DirFS guarantees changed") + } else { + return &ArtifactsFS{FS: d} +@@ -29,7 +29,7 @@ // each containing one or more entries (one per solidity compiler version) for a solidity contract. + // See OpenArtifactsDir for reading from a local directory. + // Alternative FS systems, like a tarball, may be used too. + type ArtifactsFS struct { +- FS statDirFs ++ FS StatDirFs + } +  + // ListArtifacts lists the artifacts. Each artifact matches a source-file name.
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+42
+
-29
+ +
+ +
+
+
diff --git OP/op-chain-ops/genesis/config.go CELO/op-chain-ops/genesis/config.go +index 0fc628727fe681e8c2040f456b9ef180c1bdd5b9..0f0cfcf35951df6820982743c1a76672b5279cf7 100644 +--- OP/op-chain-ops/genesis/config.go ++++ CELO/op-chain-ops/genesis/config.go +@@ -230,9 +230,9 @@ // GasPriceOracleScalar represents the initial value of the gas scalar in the GasPriceOracle predeploy. + // Deprecated: Since Ecotone, this field is superseded by GasPriceOracleBaseFeeScalar and GasPriceOracleBlobBaseFeeScalar. + GasPriceOracleScalar uint64 `json:"gasPriceOracleScalar"` + // GasPriceOracleBaseFeeScalar represents the value of the base fee scalar used for fee calculations. +- GasPriceOracleBaseFeeScalar uint32 `json:"gasPriceOracleBaseFeeScalar"` ++ GasPriceOracleBaseFeeScalar uint32 `json:"gasPriceOracleBaseFeeScalar" evm:"basefeeScalar"` + // GasPriceOracleBlobBaseFeeScalar represents the value of the blob base fee scalar used for fee calculations. +- GasPriceOracleBlobBaseFeeScalar uint32 `json:"gasPriceOracleBlobBaseFeeScalar"` ++ GasPriceOracleBlobBaseFeeScalar uint32 `json:"gasPriceOracleBlobBaseFeeScalar" evm:"blobbasefeeScalar"` + } +  + var _ ConfigChecker = (*GasPriceOracleDeployConfig)(nil) +@@ -271,9 +271,11 @@ var _ ConfigChecker = (*GasTokenDeployConfig)(nil) +  + func (d *GasTokenDeployConfig) Check(log log.Logger) error { + if d.UseCustomGasToken { +- if d.CustomGasTokenAddress == (common.Address{}) { +- return fmt.Errorf("%w: CustomGasTokenAddress cannot be address(0)", ErrInvalidDeployConfig) +- } ++ // NOTE: we are using the address(0) as an instruction to deploy the L1 token, ++ // so this deploy-config validation has to be disabled ++ // if d.CustomGasTokenAddress == (common.Address{}) { ++ // return fmt.Errorf("%w: CustomGasTokenAddress cannot be address(0)", ErrInvalidDeployConfig) ++ // } + log.Info("Using custom gas token", "address", d.CustomGasTokenAddress) + } + return nil +@@ -282,7 +284,7 @@ + // OperatorDeployConfig configures the hot-key addresses for operations such as sequencing and batch-submission. + type OperatorDeployConfig struct { + // P2PSequencerAddress is the address of the key the sequencer uses to sign blocks on the P2P layer. +- P2PSequencerAddress common.Address `json:"p2pSequencerAddress"` ++ P2PSequencerAddress common.Address `json:"p2pSequencerAddress" evm:"p2pSequencerAddress"` + // BatchSenderAddress represents the initial sequencer account that authorizes batches. + // Transactions sent from this account to the batch inbox address are considered valid. + BatchSenderAddress common.Address `json:"batchSenderAddress"` +@@ -308,6 +310,8 @@ // EIP1559Denominator is the denominator of EIP1559 base fee market. + EIP1559Denominator uint64 `json:"eip1559Denominator"` + // EIP1559DenominatorCanyon is the denominator of EIP1559 base fee market when Canyon is active. + EIP1559DenominatorCanyon uint64 `json:"eip1559DenominatorCanyon"` ++ // EIP1559BaseFeeFloor is the fixed floor for the EIP1559 base fee market. ++ EIP1559BaseFeeFloor uint64 `json:"eip1559BaseFeeFloor,omitempty"` + } +  + var _ ConfigChecker = (*EIP1559DeployConfig)(nil) +@@ -627,7 +631,7 @@ // to the L2OutputOracle contract located on L1. + L2OutputOracleSubmissionInterval uint64 `json:"l2OutputOracleSubmissionInterval"` + // L2OutputOracleStartingTimestamp is the starting timestamp for the L2OutputOracle. + // MUST be the same as the timestamp of the L2OO start block. +- L2OutputOracleStartingTimestamp int `json:"l2OutputOracleStartingTimestamp"` ++ L2OutputOracleStartingTimestamp int64 `json:"l2OutputOracleStartingTimestamp"` + // L2OutputOracleStartingBlockNumber is the starting block number for the L2OutputOracle. + // Must be greater than or equal to the first Bedrock block. The first L2 output will correspond + // to this value plus the submission interval. +@@ -732,6 +736,8 @@ OptimismPortalProxy common.Address `json:"optimismPortalProxy"` +  + // DAChallengeProxy represents the L1 address of the DataAvailabilityChallenge contract. + DAChallengeProxy common.Address `json:"daChallengeProxy"` + -+ /** -+ * @notice Alternative function to credit balance after making payments -+ * for gas in this StableToken currency. -+ * @param from The account to debit balance from -+ * @param feeRecipient Coinbase address -+ * @param gatewayFeeRecipient Gateway address -+ * @param communityFund Community fund address -+ * @param refund amount to be refunded by the VM -+ * @param tipTxFee Coinbase fee -+ * @param baseTxFee Community fund fee -+ * @param gatewayFee Gateway fee -+ * @dev Note that this function is called by the protocol when paying for tx fees in this -+ * currency. Before the tx is executed, gas is debited from the sender via a call to -+ * `debitGasFees`. -+ */ -+ function creditGasFees( -+ address from, -+ address feeRecipient, -+ address gatewayFeeRecipient, -+ address communityFund, -+ uint256 refund, -+ uint256 tipTxFee, -+ uint256 gatewayFee, -+ uint256 baseTxFee -+ ) -+ external -+ onlyVm -+ { -+ // slither-disable-next-line uninitialized-local -+ uint256 amountToBurn; -+ _mint(from, refund + tipTxFee + gatewayFee + baseTxFee); ++ ProtocolVersionsProxy common.Address `json:"protocolVersionsProxy"` + } +  + // DependencyContext is the contextual configuration needed to verify the L1 dependencies, +@@ -808,7 +814,7 @@ // The Output oracle deploy script may use it if the L2 starting timestamp is nil, assuming the L2 genesis is set up with this. + // The L2 genesis timestamp does not affect the initial L2 account state: + // the storage of the L1Block contract at genesis is zeroed, since the adoption of + // the L2-genesis allocs-generation through solidity script. +- L1StartingBlockTag *MarshalableRPCBlockNumberOrHash `json:"l1StartingBlockTag"` ++ L1StartingBlockTag *MarshalableRPCBlockNumberOrHash `json:"l1StartingBlockTag" evm:"-"` +  + // L1 contracts configuration. + // The deployer of the contracts chooses which sub-systems to deploy. +@@ -820,7 +826,10 @@ // Post-L1-deployment L2 configs + L1DependenciesConfig +  + // Legacy, ignored, here for strict-JSON decoding to be accepted. +- LegacyDeployConfig ++ LegacyDeployConfig `evm:"-"` + -+ if (feeRecipient != address(0)) { -+ _transfer(from, feeRecipient, tipTxFee); -+ } else if (tipTxFee > 0) { -+ amountToBurn += tipTxFee; -+ } ++ // DeployCeloContracts indicates whether to deploy Celo contracts. ++ DeployCeloContracts bool `json:"deployCeloContracts"` + } +  + // Copy will deeply copy the DeployConfig. This does a JSON roundtrip to copy +@@ -877,7 +886,7 @@ } +  + // RollupConfig converts a DeployConfig to a rollup.Config. If Ecotone is active at genesis, the + // Overhead value is considered a noop. +-func (d *DeployConfig) RollupConfig(l1StartBlock *types.Block, l2GenesisBlockHash common.Hash, l2GenesisBlockNumber uint64) (*rollup.Config, error) { ++func (d *DeployConfig) RollupConfig(l1StartBlock *types.Header, l2GenesisBlockHash common.Hash, l2GenesisBlockNumber uint64) (*rollup.Config, error) { + if d.OptimismPortalProxy == (common.Address{}) { + return nil, errors.New("OptimismPortalProxy cannot be address(0)") + } +@@ -894,17 +903,19 @@ DAResolveWindow: d.DAResolveWindow, + } + } +  ++ l1StartTime := l1StartBlock.Time ++ + return &rollup.Config{ + Genesis: rollup.Genesis{ + L1: eth.BlockID{ + Hash: l1StartBlock.Hash(), +- Number: l1StartBlock.NumberU64(), ++ Number: l1StartBlock.Number.Uint64(), + }, + L2: eth.BlockID{ + Hash: l2GenesisBlockHash, + Number: l2GenesisBlockNumber, + }, +- L2Time: l1StartBlock.Time(), ++ L2Time: l1StartBlock.Time, + SystemConfig: eth.SystemConfig{ + BatcherAddr: d.BatchSenderAddress, + Overhead: eth.Bytes32(common.BigToHash(new(big.Int).SetUint64(d.GasPriceOracleOverhead))), +@@ -912,23 +923,25 @@ Scalar: eth.Bytes32(d.FeeScalar()), + GasLimit: uint64(d.L2GenesisBlockGasLimit), + }, + }, +- BlockTime: d.L2BlockTime, +- MaxSequencerDrift: d.MaxSequencerDrift, +- SeqWindowSize: d.SequencerWindowSize, +- ChannelTimeoutBedrock: d.ChannelTimeoutBedrock, +- L1ChainID: new(big.Int).SetUint64(d.L1ChainID), +- L2ChainID: new(big.Int).SetUint64(d.L2ChainID), +- BatchInboxAddress: d.BatchInboxAddress, +- DepositContractAddress: d.OptimismPortalProxy, +- L1SystemConfigAddress: d.SystemConfigProxy, +- RegolithTime: d.RegolithTime(l1StartBlock.Time()), +- CanyonTime: d.CanyonTime(l1StartBlock.Time()), +- DeltaTime: d.DeltaTime(l1StartBlock.Time()), +- EcotoneTime: d.EcotoneTime(l1StartBlock.Time()), +- FjordTime: d.FjordTime(l1StartBlock.Time()), +- GraniteTime: d.GraniteTime(l1StartBlock.Time()), +- InteropTime: d.InteropTime(l1StartBlock.Time()), +- AltDAConfig: altDA, ++ BlockTime: d.L2BlockTime, ++ MaxSequencerDrift: d.MaxSequencerDrift, ++ SeqWindowSize: d.SequencerWindowSize, ++ ChannelTimeoutBedrock: d.ChannelTimeoutBedrock, ++ L1ChainID: new(big.Int).SetUint64(d.L1ChainID), ++ L2ChainID: new(big.Int).SetUint64(d.L2ChainID), ++ BatchInboxAddress: d.BatchInboxAddress, ++ DepositContractAddress: d.OptimismPortalProxy, ++ L1SystemConfigAddress: d.SystemConfigProxy, ++ RegolithTime: d.RegolithTime(l1StartTime), ++ CanyonTime: d.CanyonTime(l1StartTime), ++ DeltaTime: d.DeltaTime(l1StartTime), ++ EcotoneTime: d.EcotoneTime(l1StartTime), ++ FjordTime: d.FjordTime(l1StartTime), ++ GraniteTime: d.GraniteTime(l1StartTime), ++ InteropTime: d.InteropTime(l1StartTime), ++ ProtocolVersionsAddress: d.ProtocolVersionsProxy, ++ AltDAConfig: altDA, ++ Cel2Time: d.RegolithTime(l1StartTime), + }, nil + } +
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+16
+
-10
+ +
+ +
+
+
diff --git OP/op-chain-ops/genesis/genesis.go CELO/op-chain-ops/genesis/genesis.go +index f517912e109a714935c0be7ed0ca5561e396fcc8..846e393d5abab67df5fd1a463440f61388b4c5f7 100644 +--- OP/op-chain-ops/genesis/genesis.go ++++ CELO/op-chain-ops/genesis/genesis.go +@@ -22,7 +22,7 @@ // BedrockTransitionBlockExtraData represents the default extra data for the bedrock transition block. + var BedrockTransitionBlockExtraData = []byte("BEDROCK") +  + // NewL2Genesis will create a new L2 genesis +-func NewL2Genesis(config *DeployConfig, block *types.Block) (*core.Genesis, error) { ++func NewL2Genesis(config *DeployConfig, l1StartHeader *types.Header) (*core.Genesis, error) { + if config.L2ChainID == 0 { + return nil, errors.New("must define L2 ChainID") + } +@@ -39,6 +39,8 @@ eip1559Elasticity := config.EIP1559Elasticity + if eip1559Elasticity == 0 { + eip1559Elasticity = 10 + } + -+ if (gatewayFeeRecipient != address(0)) { -+ _transfer(from, gatewayFeeRecipient, gatewayFee); -+ } else if (gatewayFee > 0) { -+ amountToBurn += gatewayFee; -+ } ++ l1StartTime := l1StartHeader.Time +  + optimismChainConfig := params.ChainConfig{ + ChainID: new(big.Int).SetUint64(config.L2ChainID), +@@ -61,18 +63,22 @@ MergeNetsplitBlock: big.NewInt(0), + TerminalTotalDifficulty: big.NewInt(0), + TerminalTotalDifficultyPassed: true, + BedrockBlock: new(big.Int).SetUint64(uint64(config.L2GenesisBlockNumber)), +- RegolithTime: config.RegolithTime(block.Time()), +- CanyonTime: config.CanyonTime(block.Time()), +- ShanghaiTime: config.CanyonTime(block.Time()), +- CancunTime: config.EcotoneTime(block.Time()), +- EcotoneTime: config.EcotoneTime(block.Time()), +- FjordTime: config.FjordTime(block.Time()), +- GraniteTime: config.GraniteTime(block.Time()), +- InteropTime: config.InteropTime(block.Time()), ++ RegolithTime: config.RegolithTime(l1StartTime), ++ CanyonTime: config.CanyonTime(l1StartTime), ++ ShanghaiTime: config.CanyonTime(l1StartTime), ++ CancunTime: config.EcotoneTime(l1StartTime), ++ EcotoneTime: config.EcotoneTime(l1StartTime), ++ FjordTime: config.FjordTime(l1StartTime), ++ GraniteTime: config.GraniteTime(l1StartTime), ++ InteropTime: config.InteropTime(l1StartTime), ++ Cel2Time: config.RegolithTime(l1StartTime), + Optimism: &params.OptimismConfig{ + EIP1559Denominator: eip1559Denom, + EIP1559Elasticity: eip1559Elasticity, + EIP1559DenominatorCanyon: &eip1559DenomCanyon, ++ }, ++ Celo: &params.CeloConfig{ ++ EIP1559BaseFeeFloor: config.EIP1559BaseFeeFloor, + }, + } +  +@@ -102,7 +108,7 @@ + genesis := &core.Genesis{ + Config: &optimismChainConfig, + Nonce: uint64(config.L2GenesisBlockNonce), +- Timestamp: block.Time(), ++ Timestamp: l1StartTime, + ExtraData: extraData, + GasLimit: uint64(gasLimit), + Difficulty: difficulty.ToInt(),
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+1
+
-1
+ +
+ +
+
+
diff --git OP/op-chain-ops/genesis/layer_two.go CELO/op-chain-ops/genesis/layer_two.go +index 46c17a4f9c763bb4866f179a002dede969fb0bf5..5e79b55ce69dc0a35e77ecd8e9c88c13182dbeb9 100644 +--- OP/op-chain-ops/genesis/layer_two.go ++++ CELO/op-chain-ops/genesis/layer_two.go +@@ -36,7 +36,7 @@ + type AllocsLoader func(mode L2AllocsMode) *foundry.ForgeAllocs +  + // BuildL2Genesis will build the L2 genesis block. +-func BuildL2Genesis(config *DeployConfig, dump *foundry.ForgeAllocs, l1StartBlock *types.Block) (*core.Genesis, error) { ++func BuildL2Genesis(config *DeployConfig, dump *foundry.ForgeAllocs, l1StartBlock *types.Header) (*core.Genesis, error) { + genspec, err := NewL2Genesis(config, l1StartBlock) + if err != nil { + return nil, err
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+4
+
-1
+ +
+ +
+
+
diff --git OP/op-chain-ops/genesis/testdata/test-deploy-config-full.json CELO/op-chain-ops/genesis/testdata/test-deploy-config-full.json +index dfe420b2b7f44bc785e627da1fa8e350340c7ac8..7aaec4c95cf68ca38094ebae5e23b4c22e28bb9b 100644 +--- OP/op-chain-ops/genesis/testdata/test-deploy-config-full.json ++++ CELO/op-chain-ops/genesis/testdata/test-deploy-config-full.json +@@ -55,6 +55,7 @@ "l1ERC721BridgeProxy": "0x4200000000000000000000000000000000000060", + "systemConfigProxy": "0x4200000000000000000000000000000000000061", + "optimismPortalProxy": "0x4200000000000000000000000000000000000062", + "proxyAdminOwner": "0x0000000000000000000000000000000000000222", ++ "protocolVersionsProxy": "0x0000000000000000000000000000000000000000", + "gasPriceOracleBaseFeeScalar": 0, + "gasPriceOracleBlobBaseFeeScalar": 0, + "gasPriceOracleOverhead": 2100, +@@ -92,5 +93,7 @@ "daCommitmentType": "KeccakCommitment", + "daChallengeProxy": "0x0000000000000000000000000000000000000000", + "daChallengeWindow": 0, + "daResolveWindow": 0, +- "daResolverRefundPercentage": 0 ++ "daResolverRefundPercentage": 0, ++ "deployCeloContracts": false, ++ "eip1559BaseFeeFloor": 5000000000 + }
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+7
+
-0
+ +
+ +
+
+
diff --git OP/op-chain-ops/genesis/withdrawal_network.go CELO/op-chain-ops/genesis/withdrawal_network.go +index f52f12d5558dcc6def1e9d1eb5bb831fcc90a1fa..6aa753d36bd857a120180e2a100127a570369fc3 100644 +--- OP/op-chain-ops/genesis/withdrawal_network.go ++++ CELO/op-chain-ops/genesis/withdrawal_network.go +@@ -4,6 +4,8 @@ import ( + "encoding/json" + "fmt" + "strconv" + -+ if (communityFund != address(0)) { -+ _transfer(from, communityFund, baseTxFee); -+ } else if (baseTxFee > 0) { -+ amountToBurn += baseTxFee; -+ } ++ "github.com/holiman/uint256" + ) +  + // WithdrawalNetwork represents the network that withdrawals are sent to. +@@ -30,6 +32,11 @@ return 0 + default: + return 1 + } ++} + -+ if (amountToBurn > 0) { -+ _burn(from, amountToBurn); -+ } -+ } -+}
++func (w WithdrawalNetwork) ToABI() []byte { ++ out := uint256.NewInt(uint64(w.ToUint8())).Bytes32() ++ return out[:] + } +  + // FromUint8 converts a uint8 to a WithdrawalNetwork.
@@ -12069,7 +55566,7 @@
@@ -12079,211 +55576,128 @@
-
+193
+
+110
-0
-
diff --git OP/packages/contracts-bedrock/src/celo/UniswapFeeHandlerSeller.sol CELO/packages/contracts-bedrock/src/celo/UniswapFeeHandlerSeller.sol +
diff --git OP/op-chain-ops/interopgen/configs.go CELO/op-chain-ops/interopgen/configs.go new file mode 100644 -index 0000000000000000000000000000000000000000..54ce14eaf37cfd30695729e4a2990b294d589b86 +index 0000000000000000000000000000000000000000..f40d29904c2f5c15abdcac8fad9f5c5e70745fdb --- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/UniswapFeeHandlerSeller.sol -@@ -0,0 +1,193 @@ -+// SPDX-License-Identifier: MIT -+pragma solidity ^0.8.15; -+ -+import "../../lib/openzeppelin-contracts/contracts/utils/math/Math.sol"; -+import "../../lib/openzeppelin-contracts/contracts/access/Ownable.sol"; -+import "../../lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol"; -+import "../../lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; -+ -+import "./UsingRegistry.sol"; -+ -+import "./common/interfaces/IFeeHandlerSeller.sol"; -+import "./stability/interfaces/ISortedOracles.sol"; -+import "./common/FixidityLib.sol"; -+import "./common/Initializable.sol"; -+import "./FeeHandlerSeller.sol"; -+ -+import "./uniswap/interfaces/IUniswapV2RouterMin.sol"; -+import "./uniswap/interfaces/IUniswapV2FactoryMin.sol"; -+ -+// An implementation of FeeHandlerSeller supporting interfaces compatible with -+// Uniswap V2 API -+// See https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0052.md -+contract UniswapFeeHandlerSeller is FeeHandlerSeller { -+ using FixidityLib for FixidityLib.Fraction; -+ using EnumerableSet for EnumerableSet.AddressSet; -+ -+ uint256 constant MAX_TIMESTAMP_BLOCK_EXCHANGE = 20; -+ uint256 constant MAX_NUMBER_ROUTERS_PER_TOKEN = 3; -+ mapping(address => EnumerableSet.AddressSet) private routerAddresses; -+ -+ event ReceivedQuote(address indexed tokneAddress, address indexed router, uint256 quote); -+ event RouterUsed(address router); -+ event RouterAddressSet(address token, address router); -+ event RouterAddressRemoved(address token, address router); -+ -+ /** -+ * @notice Sets initialized == true on implementation contracts. -+ * @param test Set to true to skip implementation initialisation. -+ */ -+ constructor(bool test) FeeHandlerSeller(test) { } -+ -+ // without this line the contract can't receive native Celo transfers -+ receive() external payable { } -+ -+ /** -+ * @notice Returns the storage, major, minor, and patch version of the contract. -+ * @return Storage version of the contract. -+ * @return Major version of the contract. -+ * @return Minor version of the contract. -+ * @return Patch version of the contract. -+ */ -+ function getVersionNumber() external pure returns (uint256, uint256, uint256, uint256) { -+ return (1, 1, 0, 0); -+ } -+ -+ /** -+ * @notice Allows owner to set the router for a token. -+ * @param token Address of the token to set. -+ * @param router The new router. -+ */ -+ function setRouter(address token, address router) external onlyOwner { -+ _setRouter(token, router); -+ } -+ -+ function _setRouter(address token, address router) private { -+ require(router != address(0), "Router can't be address zero"); -+ routerAddresses[token].add(router); -+ require(routerAddresses[token].values().length <= MAX_NUMBER_ROUTERS_PER_TOKEN, "Max number of routers reached"); -+ emit RouterAddressSet(token, router); -+ } -+ -+ /** -+ * @notice Allows owner to remove a router for a token. -+ * @param token Address of the token. -+ * @param router Address of the router to remove. -+ */ -+ function removeRouter(address token, address router) external onlyOwner { -+ routerAddresses[token].remove(router); -+ emit RouterAddressRemoved(token, router); -+ } -+ -+ /** -+ * @notice Get the list of routers for a token. -+ * @param token The address of the token to query. -+ * @return An array of all the allowed router. -+ */ -+ function getRoutersForToken(address token) external view returns (address[] memory) { -+ return routerAddresses[token].values(); -+ } ++++ CELO/op-chain-ops/interopgen/configs.go +@@ -0,0 +1,110 @@ ++package interopgen + -+ /** -+ * @dev Calculates the minimum amount of tokens that can be received for a given amount of sell tokens, -+ * taking into account the slippage and the rates of the sell token and CELO token on the Uniswap V2 pair. -+ * @param sellTokenAddress The address of the sell token. -+ * @param maxSlippage The maximum slippage allowed. -+ * @param amount The amount of sell tokens to be traded. -+ * @param bestRouter The Uniswap V2 router with the best price. -+ * @return The minimum amount of tokens that can be received. -+ */ -+ function calculateAllMinAmount( -+ address sellTokenAddress, -+ uint256 maxSlippage, -+ uint256 amount, -+ IUniswapV2RouterMin bestRouter -+ ) -+ private -+ view -+ returns (uint256) -+ { -+ ISortedOracles sortedOracles = getSortedOracles(); -+ uint256 minReports = minimumReports[sellTokenAddress]; ++import ( ++ "errors" ++ "fmt" ++ "math/big" + -+ require(sortedOracles.numRates(sellTokenAddress) >= minReports, "Number of reports for token not enough"); ++ "github.com/ethereum/go-ethereum/common" ++ "github.com/ethereum/go-ethereum/log" + -+ uint256 minimalSortedOracles = 0; -+ // if minimumReports for this token is zero, assume the check is not needed -+ if (minReports > 0) { -+ (uint256 rateNumerator, uint256 rateDenominator) = sortedOracles.medianRate(sellTokenAddress); ++ "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" ++) + -+ minimalSortedOracles = calculateMinAmount(rateNumerator, rateDenominator, amount, maxSlippage); -+ } ++type L1Config struct { ++ ChainID *big.Int ++ genesis.DevL1DeployConfig ++ Prefund map[common.Address]*big.Int ++} + -+ IERC20 celoToken = getGoldToken(); -+ address pair = IUniswapV2FactoryMin(bestRouter.factory()).getPair(sellTokenAddress, address(celoToken)); -+ uint256 minAmountPair = -+ calculateMinAmount(IERC20(sellTokenAddress).balanceOf(pair), celoToken.balanceOf(pair), amount, maxSlippage); ++func (c *L1Config) Check(log log.Logger) error { ++ if c.ChainID == nil { ++ return errors.New("missing L1 chain ID") ++ } ++ // nothing to check on c.DevL1DeployConfig ++ return nil ++} + -+ return Math.max(minAmountPair, minimalSortedOracles); -+ } ++type SuperFaultProofConfig struct { ++ WithdrawalDelaySeconds *big.Int ++ MinProposalSizeBytes *big.Int ++ ChallengePeriodSeconds *big.Int ++ ProofMaturityDelaySeconds *big.Int ++ DisputeGameFinalityDelaySeconds *big.Int ++} + -+ // This function explicitly defines few variables because it was getting error "stack too deep" -+ function sell( -+ address sellTokenAddress, -+ address buyTokenAddress, -+ uint256 amount, -+ uint256 maxSlippage // as fraction, -+ ) -+ external -+ returns (uint256) -+ { -+ require( -+ buyTokenAddress == registry.getAddressForOrDie(GOLD_TOKEN_REGISTRY_ID), "Buy token can only be gold token" -+ ); ++type OPCMImplementationsConfig struct { ++ Release string + -+ require(routerAddresses[sellTokenAddress].values().length > 0, "routerAddresses should be non empty"); ++ FaultProof SuperFaultProofConfig + -+ // An improvement to this function would be to allow the user to pass a path as argument -+ // and if it generates a better outcome that the ones enabled that gets used -+ // and the user gets a reward ++ UseInterop bool // to deploy Interop implementation contracts, instead of the regular ones. + -+ IERC20 celoToken = getGoldToken(); ++ StandardVersionsToml string // serialized string of superchain-registry 'standard-versions.toml' file ++} + -+ IUniswapV2RouterMin bestRouter; -+ uint256 bestRouterQuote = 0; ++type SuperchainConfig struct { ++ Deployer common.Address + -+ address[] memory path = new address[](2); ++ ProxyAdminOwner common.Address ++ ProtocolVersionsOwner common.Address + -+ path[0] = sellTokenAddress; -+ path[1] = address(celoToken); ++ Paused bool + -+ for (uint256 i = 0; i < routerAddresses[sellTokenAddress].values().length; i++) { -+ address poolAddress = routerAddresses[sellTokenAddress].at(i); -+ IUniswapV2RouterMin router = IUniswapV2RouterMin(poolAddress); ++ Implementations OPCMImplementationsConfig + -+ // Using the second return value becuase it's the last argument, -+ // the previous values show how many tokens are exchanged in each path -+ // so the first value would be equivalent to balanceToBurn -+ uint256 wouldGet = router.getAmountsOut(amount, path)[1]; ++ genesis.SuperchainL1DeployConfig ++} + -+ emit ReceivedQuote(sellTokenAddress, poolAddress, wouldGet); -+ if (wouldGet > bestRouterQuote) { -+ bestRouterQuote = wouldGet; -+ bestRouter = router; -+ } -+ } ++func (c *SuperchainConfig) Check(log log.Logger) error { ++ if c.Deployer == (common.Address{}) { ++ return errors.New("missing superchain deployer address") ++ } ++ if c.ProxyAdminOwner == (common.Address{}) { ++ return errors.New("missing superchain ProxyAdminOwner address") ++ } ++ if err := c.SuperchainL1DeployConfig.Check(log); err != nil { ++ return err ++ } ++ return nil ++} + -+ require(bestRouterQuote != 0, "Can't exchange with zero quote"); ++type L2Config struct { ++ Deployer common.Address // account used to deploy contracts to L2 ++ Proposer common.Address ++ Challenger common.Address ++ SystemConfigOwner common.Address ++ genesis.L2InitializationConfig ++ Prefund map[common.Address]*big.Int ++} + -+ uint256 minAmount = 0; -+ minAmount = calculateAllMinAmount(sellTokenAddress, maxSlippage, amount, bestRouter); ++func (c *L2Config) Check(log log.Logger) error { ++ if c.Deployer == (common.Address{}) { ++ return errors.New("missing L2 deployer address") ++ } ++ if err := c.L2InitializationConfig.Check(log); err != nil { ++ return err ++ } ++ return nil ++} + -+ IERC20(sellTokenAddress).approve(address(bestRouter), amount); -+ bestRouter.swapExactTokensForTokens( -+ amount, minAmount, path, address(this), block.timestamp + MAX_TIMESTAMP_BLOCK_EXCHANGE -+ ); ++type WorldConfig struct { ++ L1 *L1Config ++ Superchain *SuperchainConfig ++ L2s map[string]*L2Config ++} + -+ uint256 celoAmount = celoToken.balanceOf(address(this)); -+ celoToken.transfer(msg.sender, celoAmount); -+ emit RouterUsed(address(bestRouter)); -+ emit TokenSold(sellTokenAddress, buyTokenAddress, amount); -+ return celoAmount; -+ } ++func (c *WorldConfig) Check(log log.Logger) error { ++ if err := c.L1.Check(log); err != nil { ++ return fmt.Errorf("invalid L1 config: %w", err) ++ } ++ if err := c.Superchain.Check(log); err != nil { ++ return fmt.Errorf("invalid Superchain config: %w", err) ++ } ++ for l2ChainID, l2Cfg := range c.L2s { ++ if err := l2Cfg.Check(log.New("l2", &l2ChainID)); err != nil { ++ return fmt.Errorf("invalid L2 (chain ID %s) config: %w", l2ChainID, err) ++ } ++ } ++ return nil +}
@@ -12291,9 +55705,9 @@
@@ -12308,7 +55722,7 @@
@@ -12318,138 +55732,359 @@
-
+120
+
+341
-0
-
diff --git OP/packages/contracts-bedrock/src/celo/UsingRegistry.sol CELO/packages/contracts-bedrock/src/celo/UsingRegistry.sol +
diff --git OP/op-chain-ops/interopgen/deploy.go CELO/op-chain-ops/interopgen/deploy.go new file mode 100644 -index 0000000000000000000000000000000000000000..b5bf928d11f22346afcada6a6f830ffb8f4eee8c +index 0000000000000000000000000000000000000000..be837484e512432fea4f875dc255a8a96713f732 --- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/UsingRegistry.sol -@@ -0,0 +1,120 @@ -+// SPDX-License-Identifier: MIT -+pragma solidity ^0.8.15; ++++ CELO/op-chain-ops/interopgen/deploy.go +@@ -0,0 +1,341 @@ ++package interopgen + -+import "../../lib/openzeppelin-contracts/contracts/access/Ownable.sol"; -+import "../../lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; ++import ( ++ "errors" ++ "fmt" ++ "math/big" + -+import "./interfaces/IAccounts.sol"; -+import "./interfaces/IFreezer.sol"; -+import "./interfaces/ICeloRegistry.sol"; ++ "github.com/ethereum/go-ethereum/common" ++ "github.com/ethereum/go-ethereum/core/types" ++ "github.com/ethereum/go-ethereum/crypto" ++ "github.com/ethereum/go-ethereum/log" + -+import "./governance/interfaces/IElection.sol"; -+import "./governance/interfaces/IGovernance.sol"; -+import "./governance/interfaces/ILockedGold.sol"; -+import "./governance/interfaces/IValidators.sol"; ++ "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/opcm" ++ "github.com/ethereum-optimism/optimism/op-chain-ops/foundry" ++ "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" ++ "github.com/ethereum-optimism/optimism/op-chain-ops/genesis/beacondeposit" ++ "github.com/ethereum-optimism/optimism/op-chain-ops/interopgen/deployers" ++ "github.com/ethereum-optimism/optimism/op-chain-ops/script" ++) + -+import "./identity/interfaces/IRandom.sol"; -+import "./identity/interfaces/IAttestations.sol"; ++var ( ++ // sysGenesisDeployer is used as tx.origin/msg.sender on system genesis script calls. ++ // At the end we verify none of the deployed contracts persist (there may be temporary ones, to insert bytecode). ++ sysGenesisDeployer = common.Address(crypto.Keccak256([]byte("System genesis deployer"))[12:]) ++) + -+import "./stability/interfaces/ISortedOracles.sol"; ++func Deploy(logger log.Logger, fa *foundry.ArtifactsFS, srcFS *foundry.SourceMapFS, cfg *WorldConfig) (*WorldDeployment, *WorldOutput, error) { ++ // Sanity check all L2s have consistent chain ID and attach to the same L1 ++ for id, l2Cfg := range cfg.L2s { ++ if fmt.Sprintf("%d", l2Cfg.L2ChainID) != id { ++ return nil, nil, fmt.Errorf("chain L2 %s declared different L2 chain ID %d in config", id, l2Cfg.L2ChainID) ++ } ++ if !cfg.L1.ChainID.IsUint64() || cfg.L1.ChainID.Uint64() != l2Cfg.L1ChainID { ++ return nil, nil, fmt.Errorf("chain L2 %s declared different L1 chain ID %d in config than global %d", id, l2Cfg.L1ChainID, cfg.L1.ChainID) ++ } ++ } + -+import "./mento/interfaces/IExchange.sol"; -+import "./mento/interfaces/IReserve.sol"; -+import "./mento/interfaces/IStableToken.sol"; ++ deployments := &WorldDeployment{ ++ L2s: make(map[string]*L2Deployment), ++ } + -+contract UsingRegistry is Ownable { -+ event RegistrySet(address indexed registryAddress); ++ l1Host := createL1(logger, fa, srcFS, cfg.L1) ++ if err := l1Host.EnableCheats(); err != nil { ++ return nil, nil, fmt.Errorf("failed to enable cheats in L1 state: %w", err) ++ } + -+ // solhint-disable state-visibility -+ bytes32 constant ACCOUNTS_REGISTRY_ID = keccak256(abi.encodePacked("Accounts")); -+ bytes32 constant ATTESTATIONS_REGISTRY_ID = keccak256(abi.encodePacked("Attestations")); -+ bytes32 constant DOWNTIME_SLASHER_REGISTRY_ID = keccak256(abi.encodePacked("DowntimeSlasher")); -+ bytes32 constant DOUBLE_SIGNING_SLASHER_REGISTRY_ID = keccak256(abi.encodePacked("DoubleSigningSlasher")); -+ bytes32 constant ELECTION_REGISTRY_ID = keccak256(abi.encodePacked("Election")); -+ bytes32 constant EXCHANGE_REGISTRY_ID = keccak256(abi.encodePacked("Exchange")); -+ bytes32 constant FREEZER_REGISTRY_ID = keccak256(abi.encodePacked("Freezer")); -+ bytes32 constant GOLD_TOKEN_REGISTRY_ID = keccak256(abi.encodePacked("GoldToken")); -+ bytes32 constant GOVERNANCE_REGISTRY_ID = keccak256(abi.encodePacked("Governance")); -+ bytes32 constant GOVERNANCE_SLASHER_REGISTRY_ID = keccak256(abi.encodePacked("GovernanceSlasher")); -+ bytes32 constant LOCKED_GOLD_REGISTRY_ID = keccak256(abi.encodePacked("LockedGold")); -+ bytes32 constant RESERVE_REGISTRY_ID = keccak256(abi.encodePacked("Reserve")); -+ bytes32 constant RANDOM_REGISTRY_ID = keccak256(abi.encodePacked("Random")); -+ bytes32 constant SORTED_ORACLES_REGISTRY_ID = keccak256(abi.encodePacked("SortedOracles")); -+ bytes32 constant STABLE_TOKEN_REGISTRY_ID = keccak256(abi.encodePacked("StableToken")); -+ bytes32 constant VALIDATORS_REGISTRY_ID = keccak256(abi.encodePacked("Validators")); -+ // solhint-enable state-visibility ++ l1Deployment, err := prepareInitialL1(l1Host, cfg.L1) ++ if err != nil { ++ return nil, nil, fmt.Errorf("failed to deploy initial L1 content: %w", err) ++ } ++ deployments.L1 = l1Deployment + -+ ICeloRegistry public registry; ++ superDeployment, err := deploySuperchainToL1(l1Host, cfg.Superchain) ++ if err != nil { ++ return nil, nil, fmt.Errorf("failed to deploy superchain to L1: %w", err) ++ } ++ deployments.Superchain = superDeployment + -+ modifier onlyRegisteredContract(bytes32 identifierHash) { -+ require(registry.getAddressForOrDie(identifierHash) == msg.sender, "only registered contract"); -+ _; -+ } ++ // We deploy contracts for each L2 to the L1 ++ // because we need to compute the genesis block hash ++ // to put into the L2 genesis configs, and can thus not mutate the L1 state ++ // after creating the final config for any particular L2. Will add comments. + -+ modifier onlyRegisteredContracts(bytes32[] memory identifierHashes) { -+ require(registry.isOneOf(identifierHashes, msg.sender), "only registered contracts"); -+ _; -+ } ++ for l2ChainID, l2Cfg := range cfg.L2s { ++ l2Deployment, err := deployL2ToL1(l1Host, cfg.Superchain, superDeployment, l2Cfg) ++ if err != nil { ++ return nil, nil, fmt.Errorf("failed to deploy L2 %d to L1: %w", &l2ChainID, err) ++ } ++ deployments.L2s[l2ChainID] = l2Deployment ++ } + -+ /** -+ * @notice Updates the address pointing to a Registry contract. -+ * @param registryAddress The address of a registry contract for routing to other contracts. -+ */ -+ function setRegistry(address registryAddress) public onlyOwner { -+ require(registryAddress != address(0), "Cannot register the null address"); -+ registry = ICeloRegistry(registryAddress); -+ emit RegistrySet(registryAddress); -+ } ++ out := &WorldOutput{ ++ L2s: make(map[string]*L2Output), ++ } ++ l1Out, err := completeL1(l1Host, cfg.L1) ++ if err != nil { ++ return nil, nil, fmt.Errorf("failed to complete L1: %w", err) ++ } ++ out.L1 = l1Out + -+ function getAccounts() internal view returns (IAccounts) { -+ return IAccounts(registry.getAddressForOrDie(ACCOUNTS_REGISTRY_ID)); -+ } ++ // Now that the L1 does not change anymore we can compute the L1 genesis block, to anchor all the L2s to. ++ l1GenesisBlock := l1Out.Genesis.ToBlock() ++ genesisTimestamp := l1Out.Genesis.Timestamp + -+ function getAttestations() internal view returns (IAttestations) { -+ return IAttestations(registry.getAddressForOrDie(ATTESTATIONS_REGISTRY_ID)); -+ } ++ for l2ChainID, l2Cfg := range cfg.L2s { ++ l2Host := createL2(logger, fa, srcFS, l2Cfg, genesisTimestamp) ++ if err := l2Host.EnableCheats(); err != nil { ++ return nil, nil, fmt.Errorf("failed to enable cheats in L2 state %s: %w", l2ChainID, err) ++ } ++ if err := genesisL2(l2Host, l2Cfg, deployments.L2s[l2ChainID]); err != nil { ++ return nil, nil, fmt.Errorf("failed to apply genesis data to L2 %s: %w", l2ChainID, err) ++ } ++ l2Out, err := completeL2(l2Host, l2Cfg, l1GenesisBlock, deployments.L2s[l2ChainID]) ++ if err != nil { ++ return nil, nil, fmt.Errorf("failed to complete L2 %s: %w", l2ChainID, err) ++ } ++ out.L2s[l2ChainID] = l2Out ++ } ++ return deployments, out, nil ++} + -+ function getElection() internal view returns (IElection) { -+ return IElection(registry.getAddressForOrDie(ELECTION_REGISTRY_ID)); -+ } ++func createL1(logger log.Logger, fa *foundry.ArtifactsFS, srcFS *foundry.SourceMapFS, cfg *L1Config) *script.Host { ++ l1Context := script.Context{ ++ ChainID: cfg.ChainID, ++ Sender: sysGenesisDeployer, ++ Origin: sysGenesisDeployer, ++ FeeRecipient: common.Address{}, ++ GasLimit: script.DefaultFoundryGasLimit, ++ BlockNum: uint64(cfg.L1GenesisBlockNumber), ++ Timestamp: uint64(cfg.L1GenesisBlockTimestamp), ++ PrevRandao: cfg.L1GenesisBlockMixHash, ++ BlobHashes: nil, ++ } ++ l1Host := script.NewHost(logger.New("role", "l1", "chain", cfg.ChainID), fa, srcFS, l1Context) ++ return l1Host ++} + -+ function getExchange() internal view returns (IExchange) { -+ return IExchange(registry.getAddressForOrDie(EXCHANGE_REGISTRY_ID)); -+ } ++func createL2(logger log.Logger, fa *foundry.ArtifactsFS, srcFS *foundry.SourceMapFS, l2Cfg *L2Config, genesisTimestamp uint64) *script.Host { ++ l2Context := script.Context{ ++ ChainID: new(big.Int).SetUint64(l2Cfg.L2ChainID), ++ Sender: sysGenesisDeployer, ++ Origin: sysGenesisDeployer, ++ FeeRecipient: common.Address{}, ++ GasLimit: script.DefaultFoundryGasLimit, ++ BlockNum: uint64(l2Cfg.L2GenesisBlockNumber), ++ Timestamp: genesisTimestamp, ++ PrevRandao: l2Cfg.L2GenesisBlockMixHash, ++ BlobHashes: nil, ++ } ++ l2Host := script.NewHost(logger.New("role", "l2", "chain", l2Cfg.L2ChainID), fa, srcFS, l2Context) ++ l2Host.SetEnvVar("OUTPUT_MODE", "none") // we don't use the cheatcode, but capture the state outside of EVM execution ++ l2Host.SetEnvVar("FORK", "granite") // latest fork ++ return l2Host ++} + -+ function getFreezer() internal view returns (IFreezer) { -+ return IFreezer(registry.getAddressForOrDie(FREEZER_REGISTRY_ID)); -+ } ++// prepareInitialL1 deploys basics such as preinstalls to L1 (incl. EIP-4788) ++func prepareInitialL1(l1Host *script.Host, cfg *L1Config) (*L1Deployment, error) { ++ l1Host.SetTxOrigin(sysGenesisDeployer) + -+ function getGoldToken() internal view returns (IERC20) { -+ return IERC20(registry.getAddressForOrDie(GOLD_TOKEN_REGISTRY_ID)); -+ } ++ if err := deployers.InsertPreinstalls(l1Host); err != nil { ++ return nil, fmt.Errorf("failed to install preinstalls in L1: %w", err) ++ } ++ // No global contracts inserted at this point. ++ // All preinstalls have known constant addresses. ++ return &L1Deployment{}, nil ++} + -+ function getGovernance() internal view returns (IGovernance) { -+ return IGovernance(registry.getAddressForOrDie(GOVERNANCE_REGISTRY_ID)); -+ } ++func deploySuperchainToL1(l1Host *script.Host, superCfg *SuperchainConfig) (*SuperchainDeployment, error) { ++ l1Host.SetTxOrigin(superCfg.Deployer) + -+ function getLockedGold() internal view returns (ILockedGold) { -+ return ILockedGold(registry.getAddressForOrDie(LOCKED_GOLD_REGISTRY_ID)); -+ } ++ superDeployment, err := opcm.DeploySuperchain(l1Host, opcm.DeploySuperchainInput{ ++ SuperchainProxyAdminOwner: superCfg.ProxyAdminOwner, ++ ProtocolVersionsOwner: superCfg.ProtocolVersionsOwner, ++ Guardian: superCfg.SuperchainConfigGuardian, ++ Paused: superCfg.Paused, ++ RequiredProtocolVersion: superCfg.RequiredProtocolVersion, ++ RecommendedProtocolVersion: superCfg.RecommendedProtocolVersion, ++ }) ++ if err != nil { ++ return nil, fmt.Errorf("failed to deploy Superchain contracts: %w", err) ++ } + -+ function getRandom() internal view returns (IRandom) { -+ return IRandom(registry.getAddressForOrDie(RANDOM_REGISTRY_ID)); -+ } ++ implementationsDeployment, err := opcm.DeployImplementations(l1Host, opcm.DeployImplementationsInput{ ++ WithdrawalDelaySeconds: superCfg.Implementations.FaultProof.WithdrawalDelaySeconds, ++ MinProposalSizeBytes: superCfg.Implementations.FaultProof.MinProposalSizeBytes, ++ ChallengePeriodSeconds: superCfg.Implementations.FaultProof.ChallengePeriodSeconds, ++ ProofMaturityDelaySeconds: superCfg.Implementations.FaultProof.ProofMaturityDelaySeconds, ++ DisputeGameFinalityDelaySeconds: superCfg.Implementations.FaultProof.DisputeGameFinalityDelaySeconds, ++ Release: superCfg.Implementations.Release, ++ SuperchainConfigProxy: superDeployment.SuperchainConfigProxy, ++ ProtocolVersionsProxy: superDeployment.ProtocolVersionsProxy, ++ SuperchainProxyAdmin: superDeployment.SuperchainProxyAdmin, ++ UseInterop: superCfg.Implementations.UseInterop, ++ StandardVersionsToml: opcm.StandardVersionsData, ++ }) ++ if err != nil { ++ return nil, fmt.Errorf("failed to deploy Implementations contracts: %w", err) ++ } + -+ function getReserve() internal view returns (IReserve) { -+ return IReserve(registry.getAddressForOrDie(RESERVE_REGISTRY_ID)); -+ } ++ // Collect deployment addresses ++ // This could all be automatic once we have better output-contract typing/scripting ++ return &SuperchainDeployment{ ++ Implementations: Implementations(implementationsDeployment), ++ ProxyAdmin: superDeployment.SuperchainProxyAdmin, ++ ProtocolVersions: superDeployment.ProtocolVersionsImpl, ++ ProtocolVersionsProxy: superDeployment.ProtocolVersionsProxy, ++ SuperchainConfig: superDeployment.SuperchainConfigImpl, ++ SuperchainConfigProxy: superDeployment.SuperchainConfigProxy, ++ }, nil ++} + -+ function getSortedOracles() internal view returns (ISortedOracles) { -+ return ISortedOracles(registry.getAddressForOrDie(SORTED_ORACLES_REGISTRY_ID)); -+ } ++func deployL2ToL1(l1Host *script.Host, superCfg *SuperchainConfig, superDeployment *SuperchainDeployment, cfg *L2Config) (*L2Deployment, error) { ++ if cfg.UseAltDA { ++ return nil, errors.New("alt-da mode not supported yet") ++ } + -+ function getStableToken() internal view returns (IStableToken) { -+ return IStableToken(registry.getAddressForOrDie(STABLE_TOKEN_REGISTRY_ID)); -+ } ++ l1Host.SetTxOrigin(cfg.Deployer) ++ ++ output, err := opcm.DeployOPChain(l1Host, opcm.DeployOPChainInput{ ++ OpChainProxyAdminOwner: cfg.ProxyAdminOwner, ++ SystemConfigOwner: cfg.SystemConfigOwner, ++ Batcher: cfg.BatchSenderAddress, ++ UnsafeBlockSigner: cfg.P2PSequencerAddress, ++ Proposer: cfg.Proposer, ++ Challenger: cfg.Challenger, ++ BasefeeScalar: cfg.GasPriceOracleBaseFeeScalar, ++ BlobBaseFeeScalar: cfg.GasPriceOracleBlobBaseFeeScalar, ++ L2ChainId: new(big.Int).SetUint64(cfg.L2ChainID), ++ OpcmProxy: superDeployment.OpcmProxy, ++ }) ++ if err != nil { ++ return nil, fmt.Errorf("failed to deploy L2 OP chain: %w", err) ++ } + -+ function getValidators() internal view returns (IValidators) { -+ return IValidators(registry.getAddressForOrDie(VALIDATORS_REGISTRY_ID)); -+ } ++ // Collect deployment addresses ++ return &L2Deployment{ ++ L2OpchainDeployment: L2OpchainDeployment(output), ++ }, nil ++} ++ ++func genesisL2(l2Host *script.Host, cfg *L2Config, deployment *L2Deployment) error { ++ if err := opcm.L2Genesis(l2Host, &opcm.L2GenesisInput{ ++ L1Deployments: opcm.L1Deployments{ ++ L1CrossDomainMessengerProxy: deployment.L1CrossDomainMessengerProxy, ++ L1StandardBridgeProxy: deployment.L1StandardBridgeProxy, ++ L1ERC721BridgeProxy: deployment.L1ERC721BridgeProxy, ++ }, ++ L2Config: cfg.L2InitializationConfig, ++ }); err != nil { ++ return fmt.Errorf("failed L2 genesis: %w", err) ++ } ++ ++ return nil ++} ++ ++func completeL1(l1Host *script.Host, cfg *L1Config) (*L1Output, error) { ++ l1Genesis, err := genesis.NewL1Genesis(&genesis.DeployConfig{ ++ L2InitializationConfig: genesis.L2InitializationConfig{ ++ L2CoreDeployConfig: genesis.L2CoreDeployConfig{ ++ L1ChainID: cfg.ChainID.Uint64(), ++ }, ++ }, ++ DevL1DeployConfig: cfg.DevL1DeployConfig, ++ }) ++ if err != nil { ++ return nil, fmt.Errorf("failed to build L1 genesis template: %w", err) ++ } ++ allocs, err := l1Host.StateDump() ++ if err != nil { ++ return nil, fmt.Errorf("failed to dump L1 state: %w", err) ++ } ++ ++ // Sanity check that the default deployer didn't include anything, ++ // and make sure it's not in the state. ++ if err := ensureNoDeployed(allocs, sysGenesisDeployer); err != nil { ++ return nil, fmt.Errorf("unexpected deployed account content by L1 genesis deployer: %w", err) ++ } ++ ++ for addr, amount := range cfg.Prefund { ++ acc := allocs.Accounts[addr] ++ acc.Balance = amount ++ allocs.Accounts[addr] = acc ++ } ++ ++ l1Genesis.Alloc = allocs.Accounts ++ ++ // Insert an empty beaconchain deposit contract with valid empty-tree prestate. ++ // This is part of dev-genesis, but not part of scripts yet. ++ beaconDepositAddr := common.HexToAddress("0x1111111111111111111111111111111111111111") ++ if err := beacondeposit.InsertEmptyBeaconDepositContract(l1Genesis, beaconDepositAddr); err != nil { ++ return nil, fmt.Errorf("failed to insert beacon deposit contract into L1 dev genesis: %w", err) ++ } ++ ++ return &L1Output{ ++ Genesis: l1Genesis, ++ }, nil ++} ++ ++func completeL2(l2Host *script.Host, cfg *L2Config, l1Block *types.Block, deployment *L2Deployment) (*L2Output, error) { ++ deployCfg := &genesis.DeployConfig{ ++ L2InitializationConfig: cfg.L2InitializationConfig, ++ L1DependenciesConfig: genesis.L1DependenciesConfig{ ++ L1StandardBridgeProxy: deployment.L1StandardBridgeProxy, ++ L1CrossDomainMessengerProxy: deployment.L1CrossDomainMessengerProxy, ++ L1ERC721BridgeProxy: deployment.L1ERC721BridgeProxy, ++ SystemConfigProxy: deployment.SystemConfigProxy, ++ OptimismPortalProxy: deployment.OptimismPortalProxy, ++ DAChallengeProxy: common.Address{}, // unsupported for now ++ }, ++ } ++ // l1Block is used to determine genesis time. ++ l2Genesis, err := genesis.NewL2Genesis(deployCfg, l1Block.Header()) ++ if err != nil { ++ return nil, fmt.Errorf("failed to build L2 genesis config: %w", err) ++ } ++ ++ allocs, err := l2Host.StateDump() ++ if err != nil { ++ return nil, fmt.Errorf("failed to dump L1 state: %w", err) ++ } ++ ++ // Sanity check that the default deployer didn't include anything, ++ // and make sure it's not in the state. ++ if err := ensureNoDeployed(allocs, sysGenesisDeployer); err != nil { ++ return nil, fmt.Errorf("unexpected deployed account content by L2 genesis deployer: %w", err) ++ } ++ ++ for addr, amount := range cfg.Prefund { ++ acc := allocs.Accounts[addr] ++ acc.Balance = amount ++ allocs.Accounts[addr] = acc ++ } ++ ++ l2Genesis.Alloc = allocs.Accounts ++ l2GenesisBlock := l2Genesis.ToBlock() ++ ++ rollupCfg, err := deployCfg.RollupConfig(l1Block.Header(), l2GenesisBlock.Hash(), l2GenesisBlock.NumberU64()) ++ if err != nil { ++ return nil, fmt.Errorf("failed to build L2 rollup config: %w", err) ++ } ++ return &L2Output{ ++ Genesis: l2Genesis, ++ RollupCfg: rollupCfg, ++ }, nil ++} ++ ++// ensureNoDeployed checks that non of the contracts that ++// could have been deployed by the given deployer address are around. ++// And removes deployer from the allocs. ++func ensureNoDeployed(allocs *foundry.ForgeAllocs, deployer common.Address) error { ++ // Sanity check we have no deploy output that's not meant to be there. ++ for i := uint64(0); i <= allocs.Accounts[deployer].Nonce; i++ { ++ addr := crypto.CreateAddress(deployer, i) ++ if _, ok := allocs.Accounts[addr]; ok { ++ return fmt.Errorf("system deployer output %s (deployed with nonce %d) was not cleaned up", addr, i) ++ } ++ } ++ // Don't include the deployer account ++ delete(allocs.Accounts, deployer) ++ return nil +}
@@ -12457,9 +56092,9 @@
@@ -12468,13 +56103,13 @@
- OP + (new)
@@ -12484,43 +56119,52 @@
-
+2
-
-1
+
+24
+
-0
-
diff --git OP/packages/contracts-bedrock/src/universal/OptimismMintableERC20.sol CELO/packages/contracts-bedrock/src/universal/OptimismMintableERC20.sol -index 43ddd65424f895b007d2eab8f5907b281c714f74..fdf16f8a7371964628efe2f456c2601ed4cb3657 100644 ---- OP/packages/contracts-bedrock/src/universal/OptimismMintableERC20.sol -+++ CELO/packages/contracts-bedrock/src/universal/OptimismMintableERC20.sol -@@ -5,6 +5,7 @@ import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; - import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; - import { ILegacyMintableERC20, IOptimismMintableERC20 } from "src/universal/IOptimismMintableERC20.sol"; - import { ISemver } from "src/universal/ISemver.sol"; -+import { AbstractFeeCurrency } from "src/celo/AbstractFeeCurrency.sol"; -  - /// @title OptimismMintableERC20 - /// @notice OptimismMintableERC20 is a standard extension of the base ERC20 token contract designed -@@ -12,7 +13,7 @@ /// to allow the StandardBridge contracts to mint and burn tokens. This makes it possible to - /// use an OptimismMintablERC20 as the L2 representation of an L1 token, or vice-versa. - /// Designed to be backwards compatible with the older StandardL2ERC20 token which was only - /// meant for use on L2. --contract OptimismMintableERC20 is IOptimismMintableERC20, ILegacyMintableERC20, ERC20, ISemver { -+contract OptimismMintableERC20 is IOptimismMintableERC20, ILegacyMintableERC20, ERC20, ISemver, AbstractFeeCurrency { - /// @notice Address of the corresponding version of this token on the remote chain. - address public immutable REMOTE_TOKEN; -
+
diff --git OP/op-chain-ops/interopgen/deployers/preinstalls.go CELO/op-chain-ops/interopgen/deployers/preinstalls.go +new file mode 100644 +index 0000000000000000000000000000000000000000..8a4dca1af26d862582963b51d717155d362f9746 +--- /dev/null ++++ CELO/op-chain-ops/interopgen/deployers/preinstalls.go +@@ -0,0 +1,24 @@ ++package deployers ++ ++import ( ++ "fmt" ++ ++ "github.com/ethereum-optimism/optimism/op-chain-ops/script" ++) ++ ++type PreinstallsScript struct { ++ SetPreinstalls func() error ++} ++ ++func InsertPreinstalls(host *script.Host) error { ++ l2GenesisScript, cleanupL2Genesis, err := script.WithScript[PreinstallsScript](host, "SetPreinstalls.s.sol", "SetPreinstalls") ++ if err != nil { ++ return fmt.Errorf("failed to load SetPreinstalls script: %w", err) ++ } ++ defer cleanupL2Genesis() ++ ++ if err := l2GenesisScript.SetPreinstalls(); err != nil { ++ return fmt.Errorf("failed to set preinstalls: %w", err) ++ } ++ return nil ++}
@@ -12529,13 +56173,13 @@
- OP + (new)
@@ -12545,274 +56189,163 @@
-
+2
+
+68
-0
-
diff --git OP/packages/contracts-bedrock/test/L2Genesis.t.sol CELO/packages/contracts-bedrock/test/L2Genesis.t.sol -index be5cc0c50edf08d81e889427f32ab2bc0054332f..08faaf32de93a17b5047c17b03aa7402794f226a 100644 ---- OP/packages/contracts-bedrock/test/L2Genesis.t.sol -+++ CELO/packages/contracts-bedrock/test/L2Genesis.t.sol -@@ -181,6 +181,7 @@ - /// @notice Tests the number of accounts in the genesis setup - function _test_allocs_size(string memory _path) internal { - genesis.cfg().setFundDevAccounts(false); -+ genesis.cfg().setDeployCeloContracts(true); - genesis.runWithLatestLocal(_dummyL1Deps()); - genesis.writeGenesisAllocs(_path); -  -@@ -190,6 +191,7 @@ expected += 21; // predeploy implementations (excl. legacy erc20-style eth and legacy message sender) - expected += 256; // precompiles - expected += 13; // preinstalls - expected += 1; // 4788 deployer account -+ expected += 14; // Celo contracts - // 16 prefunded dev accounts are excluded - assertEq(expected, getJSONKeyCount(_path), "key count check"); -
- - - - - -
- -
- - - - -
- -
-
-
- - -
-
- -
-
-
- - -
- -
-
-
- - -
-
- -
-
-
- - -
- -
-
-
- - -
-
- -
-
-
- - - - - - - -
- -
-
-
- - -
-
- -
+
diff --git OP/op-chain-ops/interopgen/deployments.go CELO/op-chain-ops/interopgen/deployments.go +new file mode 100644 +index 0000000000000000000000000000000000000000..ba18fbfdf9bde059fc1e645ba8ef7ad17d97b3cb +--- /dev/null ++++ CELO/op-chain-ops/interopgen/deployments.go +@@ -0,0 +1,68 @@ ++package interopgen ++ ++import ( ++ "github.com/ethereum/go-ethereum/common" ++) ++ ++type L1Deployment struct { ++ // No global deployed contracts that aren't part of the superchain, yet. ++} ++ ++type Implementations struct { ++ OpcmProxy common.Address `json:"OPCMProxy"` ++ OpcmImpl common.Address `json:"OPCMImpl"` ++ DelayedWETHImpl common.Address `json:"DelayedWETHImpl"` ++ OptimismPortalImpl common.Address `json:"OptimismPortalImpl"` ++ PreimageOracleSingleton common.Address `json:"PreimageOracleSingleton"` ++ MipsSingleton common.Address `json:"MipsSingleton"` ++ SystemConfigImpl common.Address `json:"SystemConfigImpl"` ++ L1CrossDomainMessengerImpl common.Address `json:"L1CrossDomainMessengerImpl"` ++ L1ERC721BridgeImpl common.Address `json:"L1ERC721BridgeImpl"` ++ L1StandardBridgeImpl common.Address `json:"L1StandardBridgeImpl"` ++ OptimismMintableERC20FactoryImpl common.Address `json:"OptimismMintableERC20FactoryImpl"` ++ DisputeGameFactoryImpl common.Address `json:"DisputeGameFactoryImpl"` ++} ++ ++type SuperchainDeployment struct { ++ Implementations ++ ++ ProxyAdmin common.Address `json:"ProxyAdmin"` ++ ++ ProtocolVersions common.Address `json:"ProtocolVersions"` ++ ProtocolVersionsProxy common.Address `json:"ProtocolVersionsProxy"` ++ ++ SuperchainConfig common.Address `json:"SuperchainConfig"` ++ SuperchainConfigProxy common.Address `json:"SuperchainConfigProxy"` ++} ++ ++type L2OpchainDeployment struct { ++ OpChainProxyAdmin common.Address `json:"OpChainProxyAdmin"` ++ AddressManager common.Address `json:"AddressManager"` ++ L1ERC721BridgeProxy common.Address `json:"L1ERC721BridgeProxy"` ++ SystemConfigProxy common.Address `json:"SystemConfigProxy"` ++ OptimismMintableERC20FactoryProxy common.Address `json:"OptimismMintableERC20FactoryProxy"` ++ L1StandardBridgeProxy common.Address `json:"L1StandardBridgeProxy"` ++ L1CrossDomainMessengerProxy common.Address `json:"L1CrossDomainMessengerProxy"` ++ // Fault proof contracts below. ++ OptimismPortalProxy common.Address `json:"OptimismPortalProxy"` ++ DisputeGameFactoryProxy common.Address `json:"DisputeGameFactoryProxy"` ++ AnchorStateRegistryProxy common.Address `json:"AnchorStateRegistryProxy"` ++ AnchorStateRegistryImpl common.Address `json:"AnchorStateRegistryImpl"` ++ FaultDisputeGame common.Address `json:"FaultDisputeGame"` ++ PermissionedDisputeGame common.Address `json:"PermissionedDisputeGame"` ++ DelayedWETHPermissionedGameProxy common.Address `json:"DelayedWETHPermissionedGameProxy"` ++ DelayedWETHPermissionlessGameProxy common.Address `json:"DelayedWETHPermissionlessGameProxy"` ++} ++ ++type L2Deployment struct { ++ L2OpchainDeployment ++ ++ // In the future this may contain optional extras, ++ // e.g. a Safe that will own the L2 chain contracts ++} ++ ++type WorldDeployment struct { ++ L1 *L1Deployment `json:"L1"` ++ Superchain *SuperchainDeployment `json:"Superchain"` ++ L2s map[string]*L2Deployment `json:"L2s"` ++}
-
-
+
+ +
+
+ + + +
+ +
+
+
+ +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+102
+
-41
+ +
+ +
+
+
diff --git OP/op-challenger/cmd/main_test.go CELO/op-challenger/cmd/main_test.go +index 926f38eced514365424711755682d8f9b14e2a6b..529711bbf6605421815de94fbf81f29dbb468c80 100644 +--- OP/op-challenger/cmd/main_test.go ++++ CELO/op-challenger/cmd/main_test.go +@@ -264,66 +264,117 @@ addRequiredArgs(types.TraceTypeAlphabet, "--http-poll-interval", "abc")) + }) + } +  +-func TestAsteriscRequiredArgs(t *testing.T) { +- for _, traceType := range []types.TraceType{types.TraceTypeAsterisc} { +- traceType := traceType +- t.Run(fmt.Sprintf("TestAsteriscBin-%v", traceType), func(t *testing.T) { +- t.Run("NotRequiredForAlphabetTrace", func(t *testing.T) { +- configForArgs(t, addRequiredArgsExcept(types.TraceTypeAlphabet, "--asterisc-bin")) +- }) ++func TestAsteriscOpProgramRequiredArgs(t *testing.T) { ++ traceType := types.TraceTypeAsterisc ++ t.Run(fmt.Sprintf("TestAsteriscServer-%v", traceType), func(t *testing.T) { ++ t.Run("NotRequiredForAlphabetTrace", func(t *testing.T) { ++ configForArgs(t, addRequiredArgsExcept(types.TraceTypeAlphabet, "--asterisc-server")) ++ }) ++ ++ t.Run("Required", func(t *testing.T) { ++ verifyArgsInvalid(t, "flag asterisc-server is required", addRequiredArgsExcept(traceType, "--asterisc-server")) ++ }) ++ ++ t.Run("Valid", func(t *testing.T) { ++ cfg := configForArgs(t, addRequiredArgsExcept(traceType, "--asterisc-server", "--asterisc-server=./op-program")) ++ require.Equal(t, "./op-program", cfg.Asterisc.Server) ++ }) ++ }) ++ ++ t.Run(fmt.Sprintf("TestAsteriscAbsolutePrestate-%v", traceType), func(t *testing.T) { ++ t.Run("NotRequiredForAlphabetTrace", func(t *testing.T) { ++ configForArgs(t, addRequiredArgsExcept(types.TraceTypeAlphabet, "--asterisc-prestate")) ++ }) ++ ++ t.Run("Required", func(t *testing.T) { ++ verifyArgsInvalid(t, "flag asterisc-prestates-url or asterisc-prestate is required", addRequiredArgsExcept(traceType, "--asterisc-prestate")) ++ }) ++ ++ t.Run("Valid", func(t *testing.T) { ++ cfg := configForArgs(t, addRequiredArgsExcept(traceType, "--asterisc-prestate", "--asterisc-prestate=./pre.json")) ++ require.Equal(t, "./pre.json", cfg.AsteriscAbsolutePreState) ++ }) ++ }) ++ ++ t.Run(fmt.Sprintf("TestAsteriscAbsolutePrestateBaseURL-%v", traceType), func(t *testing.T) { ++ t.Run("NotRequiredForAlphabetTrace", func(t *testing.T) { ++ configForArgs(t, addRequiredArgsExcept(types.TraceTypeAlphabet, "--asterisc-prestates-url")) ++ }) ++ ++ t.Run("Required", func(t *testing.T) { ++ verifyArgsInvalid(t, "flag asterisc-prestates-url or asterisc-prestate is required", addRequiredArgsExcept(traceType, "--asterisc-prestate")) ++ }) ++ ++ t.Run("Valid", func(t *testing.T) { ++ cfg := configForArgs(t, addRequiredArgsExcept(traceType, "--asterisc-prestates-url", "--asterisc-prestates-url=http://localhost/bar")) ++ require.Equal(t, "http://localhost/bar", cfg.AsteriscAbsolutePreStateBaseURL.String()) ++ }) ++ }) ++} ++ ++func TestAsteriscKonaRequiredArgs(t *testing.T) { ++ traceType := types.TraceTypeAsteriscKona ++ t.Run(fmt.Sprintf("TestAsteriscServer-%v", traceType), func(t *testing.T) { ++ t.Run("NotRequiredForAlphabetTrace", func(t *testing.T) { ++ configForArgs(t, addRequiredArgsExcept(types.TraceTypeAlphabet, "--asterisc-kona-server")) ++ }) +  +- t.Run("Required", func(t *testing.T) { +- verifyArgsInvalid(t, "flag asterisc-bin is required", addRequiredArgsExcept(traceType, "--asterisc-bin")) +- }) ++ t.Run("Required", func(t *testing.T) { ++ verifyArgsInvalid(t, "flag asterisc-kona-server is required", addRequiredArgsExcept(traceType, "--asterisc-kona-server")) ++ }) +  +- t.Run("Valid", func(t *testing.T) { +- cfg := configForArgs(t, addRequiredArgsExcept(traceType, "--asterisc-bin", "--asterisc-bin=./asterisc")) +- require.Equal(t, "./asterisc", cfg.Asterisc.VmBin) +- }) ++ t.Run("Valid", func(t *testing.T) { ++ cfg := configForArgs(t, addRequiredArgsExcept(traceType, "--asterisc-kona-server", "--asterisc-kona-server=./kona-host")) ++ require.Equal(t, "./kona-host", cfg.AsteriscKona.Server) + }) ++ }) +  +- t.Run(fmt.Sprintf("TestAsteriscServer-%v", traceType), func(t *testing.T) { +- t.Run("NotRequiredForAlphabetTrace", func(t *testing.T) { +- configForArgs(t, addRequiredArgsExcept(types.TraceTypeAlphabet, "--asterisc-server")) +- }) ++ t.Run(fmt.Sprintf("TestAsteriscAbsolutePrestate-%v", traceType), func(t *testing.T) { ++ t.Run("NotRequiredForAlphabetTrace", func(t *testing.T) { ++ configForArgs(t, addRequiredArgsExcept(types.TraceTypeAlphabet, "--asterisc-kona-prestate")) ++ }) +  +- t.Run("Required", func(t *testing.T) { +- verifyArgsInvalid(t, "flag asterisc-server is required", addRequiredArgsExcept(traceType, "--asterisc-server")) +- }) ++ t.Run("Required", func(t *testing.T) { ++ verifyArgsInvalid(t, "flag asterisc-kona-prestates-url or asterisc-kona-prestate is required", addRequiredArgsExcept(traceType, "--asterisc-kona-prestate")) ++ }) +  +- t.Run("Valid", func(t *testing.T) { +- cfg := configForArgs(t, addRequiredArgsExcept(traceType, "--asterisc-server", "--asterisc-server=./op-program")) +- require.Equal(t, "./op-program", cfg.Asterisc.Server) +- }) ++ t.Run("Valid", func(t *testing.T) { ++ cfg := configForArgs(t, addRequiredArgsExcept(traceType, "--asterisc-kona-prestate", "--asterisc-kona-prestate=./pre.json")) ++ require.Equal(t, "./pre.json", cfg.AsteriscKonaAbsolutePreState) + }) ++ }) +  +- t.Run(fmt.Sprintf("TestAsteriscAbsolutePrestate-%v", traceType), func(t *testing.T) { +- t.Run("NotRequiredForAlphabetTrace", func(t *testing.T) { +- configForArgs(t, addRequiredArgsExcept(types.TraceTypeAlphabet, "--asterisc-prestate")) +- }) ++ t.Run(fmt.Sprintf("TestAsteriscAbsolutePrestateBaseURL-%v", traceType), func(t *testing.T) { ++ t.Run("NotRequiredForAlphabetTrace", func(t *testing.T) { ++ configForArgs(t, addRequiredArgsExcept(types.TraceTypeAlphabet, "--asterisc-kona-prestates-url")) ++ }) +  +- t.Run("Required", func(t *testing.T) { +- verifyArgsInvalid(t, "flag asterisc-prestates-url or asterisc-prestate is required", addRequiredArgsExcept(traceType, "--asterisc-prestate")) +- }) ++ t.Run("Required", func(t *testing.T) { ++ verifyArgsInvalid(t, "flag asterisc-kona-prestates-url or asterisc-kona-prestate is required", addRequiredArgsExcept(traceType, "--asterisc-kona-prestate")) ++ }) +  +- t.Run("Valid", func(t *testing.T) { +- cfg := configForArgs(t, addRequiredArgsExcept(traceType, "--asterisc-prestate", "--asterisc-prestate=./pre.json")) +- require.Equal(t, "./pre.json", cfg.AsteriscAbsolutePreState) +- }) ++ t.Run("Valid", func(t *testing.T) { ++ cfg := configForArgs(t, addRequiredArgsExcept(traceType, "--asterisc-kona-prestates-url", "--asterisc-kona-prestates-url=http://localhost/bar")) ++ require.Equal(t, "http://localhost/bar", cfg.AsteriscKonaAbsolutePreStateBaseURL.String()) + }) ++ }) ++} +  +- t.Run(fmt.Sprintf("TestAsteriscAbsolutePrestateBaseURL-%v", traceType), func(t *testing.T) { ++func TestAsteriscBaseRequiredArgs(t *testing.T) { ++ for _, traceType := range []types.TraceType{types.TraceTypeAsterisc, types.TraceTypeAsteriscKona} { ++ traceType := traceType ++ t.Run(fmt.Sprintf("TestAsteriscBin-%v", traceType), func(t *testing.T) { + t.Run("NotRequiredForAlphabetTrace", func(t *testing.T) { +- configForArgs(t, addRequiredArgsExcept(types.TraceTypeAlphabet, "--asterisc-prestates-url")) ++ configForArgs(t, addRequiredArgsExcept(types.TraceTypeAlphabet, "--asterisc-bin")) + }) +  + t.Run("Required", func(t *testing.T) { +- verifyArgsInvalid(t, "flag asterisc-prestates-url or asterisc-prestate is required", addRequiredArgsExcept(traceType, "--asterisc-prestate")) ++ verifyArgsInvalid(t, "flag asterisc-bin is required", addRequiredArgsExcept(traceType, "--asterisc-bin")) + }) +  + t.Run("Valid", func(t *testing.T) { +- cfg := configForArgs(t, addRequiredArgsExcept(traceType, "--asterisc-prestates-url", "--asterisc-prestates-url=http://localhost/bar")) +- require.Equal(t, "http://localhost/bar", cfg.AsteriscAbsolutePreStateBaseURL.String()) ++ cfg := configForArgs(t, addRequiredArgsExcept(traceType, "--asterisc-bin", "--asterisc-bin=./asterisc")) ++ require.Equal(t, "./asterisc", cfg.Asterisc.VmBin) + }) + }) +  +@@ -853,6 +904,8 @@ case types.TraceTypeCannon, types.TraceTypePermissioned: + addRequiredCannonArgs(args) + case types.TraceTypeAsterisc: + addRequiredAsteriscArgs(args) ++ case types.TraceTypeAsteriscKona: ++ addRequiredAsteriscKonaArgs(args) + } + return args + } +@@ -870,6 +923,14 @@ args["--asterisc-network"] = asteriscNetwork + args["--asterisc-bin"] = asteriscBin + args["--asterisc-server"] = asteriscServer + args["--asterisc-prestate"] = asteriscPreState ++ args["--l2-eth-rpc"] = l2EthRpc ++} ++ ++func addRequiredAsteriscKonaArgs(args map[string]string) { ++ args["--asterisc-network"] = asteriscNetwork ++ args["--asterisc-bin"] = asteriscBin ++ args["--asterisc-kona-server"] = asteriscServer ++ args["--asterisc-kona-prestate"] = asteriscPreState + args["--l2-eth-rpc"] = l2EthRpc + } +
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+47
+
-2
+ +
+ +
+
+
diff --git OP/op-challenger/cmd/run_trace.go CELO/op-challenger/cmd/run_trace.go +index a3438807837b51d02edb2c49159f11748a9bf4dc..c1d2261230f9e026366a6dda0ecc0e3fe847095d 100644 +--- OP/op-challenger/cmd/run_trace.go ++++ CELO/op-challenger/cmd/run_trace.go +@@ -2,10 +2,17 @@ package main +  + import ( + "context" ++ "errors" ++ "fmt" ++ "net/url" +  ++ "github.com/ethereum-optimism/optimism/op-challenger/config" + "github.com/ethereum-optimism/optimism/op-challenger/flags" ++ "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/vm" + "github.com/ethereum-optimism/optimism/op-challenger/runner" ++ opservice "github.com/ethereum-optimism/optimism/op-service" + "github.com/ethereum-optimism/optimism/op-service/cliapp" ++ "github.com/ethereum/go-ethereum/common" + "github.com/urfave/cli/v2" + ) +  +@@ -24,11 +31,36 @@ } + if err := cfg.Check(); err != nil { + return nil, err + } +- return runner.NewRunner(logger, cfg), nil ++ if err := checkMTCannonFlags(ctx, cfg); err != nil { ++ return nil, err ++ } ++ ++ var mtPrestate common.Hash ++ var mtPrestateURL *url.URL ++ if ctx.IsSet(addMTCannonPrestateFlag.Name) { ++ mtPrestate = common.HexToHash(ctx.String(addMTCannonPrestateFlag.Name)) ++ mtPrestateURL, err = url.Parse(ctx.String(addMTCannonPrestateURLFlag.Name)) ++ if err != nil { ++ return nil, fmt.Errorf("invalid mt-cannon prestate url (%v): %w", ctx.String(addMTCannonPrestateFlag.Name), err) ++ } ++ } ++ return runner.NewRunner(logger, cfg, mtPrestate, mtPrestateURL), nil ++} ++ ++func checkMTCannonFlags(ctx *cli.Context, cfg *config.Config) error { ++ if ctx.IsSet(addMTCannonPrestateFlag.Name) || ctx.IsSet(addMTCannonPrestateURLFlag.Name) { ++ if ctx.IsSet(addMTCannonPrestateFlag.Name) != ctx.IsSet(addMTCannonPrestateURLFlag.Name) { ++ return fmt.Errorf("both flag %v and %v must be set when running MT-Cannon traces", addMTCannonPrestateURLFlag.Name, addMTCannonPrestateFlag.Name) ++ } ++ if cfg.Cannon == (vm.Config{}) { ++ return errors.New("required Cannon vm configuration for mt-cannon traces is missing") ++ } ++ } ++ return nil + } +  + func runTraceFlags() []cli.Flag { +- return flags.Flags ++ return append(flags.Flags, addMTCannonPrestateFlag, addMTCannonPrestateURLFlag) + } +  + var RunTraceCommand = &cli.Command{ +@@ -38,3 +70,16 @@ Description: "Runs trace providers against real chain data to confirm compatibility", + Action: cliapp.LifecycleCmd(RunTrace), + Flags: runTraceFlags(), + } ++ ++var ( ++ addMTCannonPrestateFlag = &cli.StringFlag{ ++ Name: "add-mt-cannon-prestate", ++ Usage: "Use this prestate to run MT-Cannon compatibility tests", ++ EnvVars: opservice.PrefixEnvVar(flags.EnvVarPrefix, "ADD_MT_CANNON_PRESTATE"), ++ } ++ addMTCannonPrestateURLFlag = &cli.StringFlag{ ++ Name: "add-mt-cannon-prestate-url", ++ Usage: "Use this prestate URL to run MT-Cannon compatibility tests", ++ EnvVars: opservice.PrefixEnvVar(flags.EnvVarPrefix, "ADD_MT_CANNON_PRESTATE_URL"), ++ } ++)
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+8
+
-7
+ +
+ +
+
+
diff --git OP/op-challenger/config/config.go CELO/op-challenger/config/config.go +index a9937a68af869a6475db7fd02745523bc095c74b..e8a245936f33f5311f1e50e60149e1b1ba4d3d3c 100644 +--- OP/op-challenger/config/config.go ++++ CELO/op-challenger/config/config.go +@@ -139,13 +139,14 @@ + Datadir: datadir, +  + Cannon: vm.Config{ +- VmType: types.TraceTypeCannon, +- L1: l1EthRpc, +- L1Beacon: l1BeaconApi, +- L2: l2EthRpc, +- SnapshotFreq: DefaultCannonSnapshotFreq, +- InfoFreq: DefaultCannonInfoFreq, +- DebugInfo: true, ++ VmType: types.TraceTypeCannon, ++ L1: l1EthRpc, ++ L1Beacon: l1BeaconApi, ++ L2: l2EthRpc, ++ SnapshotFreq: DefaultCannonSnapshotFreq, ++ InfoFreq: DefaultCannonInfoFreq, ++ DebugInfo: true, ++ BinarySnapshots: true, + }, + Asterisc: vm.Config{ + VmType: types.TraceTypeAsterisc,
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+26
+
-1
+ +
+ +
+
+
diff --git OP/op-challenger/flags/flags.go CELO/op-challenger/flags/flags.go +index df62b48aa4132e28cdecffd133f7c9458df3b67c..38e59d350cec4673e2969dc5c5b2c7fdf01386b6 100644 +--- OP/op-challenger/flags/flags.go ++++ CELO/op-challenger/flags/flags.go +@@ -327,7 +327,7 @@ } + return nil + } +  +-func CheckAsteriscFlags(ctx *cli.Context) error { ++func CheckAsteriscBaseFlags(ctx *cli.Context) error { + if ctx.IsSet(AsteriscNetworkFlag.Name) && ctx.IsSet(flags.NetworkFlagName) { + return fmt.Errorf("flag %v can not be used with %v", AsteriscNetworkFlag.Name, flags.NetworkFlagName) + } +@@ -350,6 +350,13 @@ } + if !ctx.IsSet(AsteriscBinFlag.Name) { + return fmt.Errorf("flag %s is required", AsteriscBinFlag.Name) + } ++ return nil ++} ++ ++func CheckAsteriscFlags(ctx *cli.Context) error { ++ if err := CheckAsteriscBaseFlags(ctx); err != nil { ++ return err ++ } + if !ctx.IsSet(AsteriscServerFlag.Name) { + return fmt.Errorf("flag %s is required", AsteriscServerFlag.Name) + } +@@ -359,6 +366,19 @@ } + return nil + } +  ++func CheckAsteriscKonaFlags(ctx *cli.Context) error { ++ if err := CheckAsteriscBaseFlags(ctx); err != nil { ++ return err ++ } ++ if !ctx.IsSet(AsteriscKonaServerFlag.Name) { ++ return fmt.Errorf("flag %s is required", AsteriscKonaServerFlag.Name) ++ } ++ if !ctx.IsSet(AsteriscKonaPreStateFlag.Name) && !ctx.IsSet(AsteriscKonaPreStatesURLFlag.Name) { ++ return fmt.Errorf("flag %s or %s is required", AsteriscKonaPreStatesURLFlag.Name, AsteriscKonaPreStateFlag.Name) ++ } ++ return nil ++} ++ + func CheckRequired(ctx *cli.Context, traceTypes []types.TraceType) error { + for _, f := range requiredFlags { + if !ctx.IsSet(f.Names()[0]) { +@@ -377,6 +397,10 @@ return err + } + case types.TraceTypeAsterisc: + if err := CheckAsteriscFlags(ctx); err != nil { ++ return err ++ } ++ case types.TraceTypeAsteriscKona: ++ if err := CheckAsteriscKonaFlags(ctx); err != nil { + return err + } + case types.TraceTypeAlphabet, types.TraceTypeFast: +@@ -554,6 +578,7 @@ L2GenesisPath: ctx.String(CannonL2GenesisFlag.Name), + SnapshotFreq: ctx.Uint(CannonSnapshotFreqFlag.Name), + InfoFreq: ctx.Uint(CannonInfoFreqFlag.Name), + DebugInfo: true, ++ BinarySnapshots: true, + }, + CannonAbsolutePreState: ctx.String(CannonPreStateFlag.Name), + CannonAbsolutePreStateBaseURL: cannonPrestatesURL,
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+9
+
-3
+ +
+ +
+
+
diff --git OP/op-challenger/game/fault/player.go CELO/op-challenger/game/fault/player.go +index cede89217c59112cc2bbf6c9e8b9e664a13a89b8..5ab187707557616d4efa1080ec1ede54a48a1fdd 100644 +--- OP/op-challenger/game/fault/player.go ++++ CELO/op-challenger/game/fault/player.go +@@ -64,6 +64,10 @@ GetOracle(ctx context.Context) (contracts.PreimageOracleContract, error) + GetL1Head(ctx context.Context) (common.Hash, error) + } +  ++var actNoop = func(ctx context.Context) error { ++ return nil ++} ++ + type resourceCreator func(ctx context.Context, logger log.Logger, gameDepth types.Depth, dir string) (types.TraceAccessor, error) +  + func NewGamePlayer( +@@ -98,9 +102,7 @@ loader: loader, + prestateValidators: validators, + status: status, + // Act function does nothing because the game is already complete +- act: func(ctx context.Context) error { +- return nil +- }, ++ act: actNoop, + }, nil + } +  +@@ -195,6 +197,10 @@ return gameTypes.GameStatusInProgress + } + g.logGameStatus(ctx, status) + g.status = status ++ if status != gameTypes.GameStatusInProgress { ++ // Release the agent as we will no longer need to act on this game. ++ g.act = actNoop ++ } + return status + } +
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+5
+
-0
+ +
+ +
+
+
diff --git OP/op-challenger/game/fault/player_test.go CELO/op-challenger/game/fault/player_test.go +index 0c662ac638836d5e237b1daead739db8fc2ef40e..7c05525a8823dc08d3fd1ad10937b9d376f5052f 100644 +--- OP/op-challenger/game/fault/player_test.go ++++ CELO/op-challenger/game/fault/player_test.go +@@ -90,6 +90,11 @@ // Should not act when it knows the game is already complete + fetched = game.ProgressGame(context.Background()) + require.Equal(t, 1, gameState.callCount, "does not act after game is complete") + require.Equal(t, status, fetched) ++ ++ // Should have replaced the act function with a noop so callCount doesn't update even when called directly ++ // This allows the agent resources to be GC'd ++ require.NoError(t, game.act(context.Background())) ++ require.Equal(t, 1, gameState.callCount) + }) + } + }
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+1
+
-1
+ +
+ +
+
+
diff --git OP/op-challenger/game/fault/register.go CELO/op-challenger/game/fault/register.go +index a76f456f16f3dbcf2a1f522106797eb18c8e50a7..08140164a17ce480e501f46cb4f60bbb457e8c56 100644 +--- OP/op-challenger/game/fault/register.go ++++ CELO/op-challenger/game/fault/register.go +@@ -77,7 +77,7 @@ if cfg.TraceTypeEnabled(faultTypes.TraceTypeAsterisc) { + registerTasks = append(registerTasks, NewAsteriscRegisterTask(faultTypes.AsteriscGameType, cfg, m, vm.NewOpProgramServerExecutor())) + } + if cfg.TraceTypeEnabled(faultTypes.TraceTypeAsteriscKona) { +- registerTasks = append(registerTasks, NewAsteriscRegisterTask(faultTypes.AsteriscKonaGameType, cfg, m, vm.NewKonaServerExecutor())) ++ registerTasks = append(registerTasks, NewAsteriscKonaRegisterTask(faultTypes.AsteriscKonaGameType, cfg, m, vm.NewKonaExecutor())) + } + if cfg.TraceTypeEnabled(faultTypes.TraceTypeFast) { + registerTasks = append(registerTasks, NewAlphabetRegisterTask(faultTypes.FastGameType))
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+42
+
-5
+ +
+ +
+
+
diff --git OP/op-challenger/game/fault/register_task.go CELO/op-challenger/game/fault/register_task.go +index b9b2db6b49516f80a304083c444ab5166d098373..3b438ad8eea22615718743c56af5ac8e003fcac2 100644 +--- OP/op-challenger/game/fault/register_task.go ++++ CELO/op-challenger/game/fault/register_task.go +@@ -48,16 +48,18 @@ poststateBlock uint64) (*trace.Accessor, error) + } +  + func NewCannonRegisterTask(gameType faultTypes.GameType, cfg *config.Config, m caching.Metrics, serverExecutor vm.OracleServerExecutor) *RegisterTask { ++ stateConverter := cannon.NewStateConverter() + return &RegisterTask{ + gameType: gameType, + getPrestateProvider: cachePrestates( + gameType, ++ stateConverter, + m, + cfg.CannonAbsolutePreStateBaseURL, + cfg.CannonAbsolutePreState, + filepath.Join(cfg.Datadir, "cannon-prestates"), + func(path string) faultTypes.PrestateProvider { +- return cannon.NewPrestateProvider(path) ++ return vm.NewPrestateProvider(path, stateConverter) + }), + newTraceAccessor: func( + logger log.Logger, +@@ -71,23 +73,25 @@ l1Head eth.BlockID, + splitDepth faultTypes.Depth, + prestateBlock uint64, + poststateBlock uint64) (*trace.Accessor, error) { +- provider := vmPrestateProvider.(*cannon.CannonPrestateProvider) ++ provider := vmPrestateProvider.(*vm.PrestateProvider) + return outputs.NewOutputCannonTraceAccessor(logger, m, cfg.Cannon, serverExecutor, l2Client, prestateProvider, provider.PrestatePath(), rollupClient, dir, l1Head, splitDepth, prestateBlock, poststateBlock) + }, + } + } +  + func NewAsteriscRegisterTask(gameType faultTypes.GameType, cfg *config.Config, m caching.Metrics, serverExecutor vm.OracleServerExecutor) *RegisterTask { ++ stateConverter := asterisc.NewStateConverter() + return &RegisterTask{ + gameType: gameType, + getPrestateProvider: cachePrestates( + gameType, ++ stateConverter, + m, + cfg.AsteriscAbsolutePreStateBaseURL, + cfg.AsteriscAbsolutePreState, + filepath.Join(cfg.Datadir, "asterisc-prestates"), + func(path string) faultTypes.PrestateProvider { +- return asterisc.NewPrestateProvider(path) ++ return vm.NewPrestateProvider(path, stateConverter) + }), + newTraceAccessor: func( + logger log.Logger, +@@ -101,12 +105,44 @@ l1Head eth.BlockID, + splitDepth faultTypes.Depth, + prestateBlock uint64, + poststateBlock uint64) (*trace.Accessor, error) { +- provider := vmPrestateProvider.(*asterisc.AsteriscPreStateProvider) ++ provider := vmPrestateProvider.(*vm.PrestateProvider) + return outputs.NewOutputAsteriscTraceAccessor(logger, m, cfg.Asterisc, serverExecutor, l2Client, prestateProvider, provider.PrestatePath(), rollupClient, dir, l1Head, splitDepth, prestateBlock, poststateBlock) + }, + } + } +  ++func NewAsteriscKonaRegisterTask(gameType faultTypes.GameType, cfg *config.Config, m caching.Metrics, serverExecutor vm.OracleServerExecutor) *RegisterTask { ++ stateConverter := asterisc.NewStateConverter() ++ return &RegisterTask{ ++ gameType: gameType, ++ getPrestateProvider: cachePrestates( ++ gameType, ++ stateConverter, ++ m, ++ cfg.AsteriscKonaAbsolutePreStateBaseURL, ++ cfg.AsteriscKonaAbsolutePreState, ++ filepath.Join(cfg.Datadir, "asterisc-kona-prestates"), ++ func(path string) faultTypes.PrestateProvider { ++ return vm.NewPrestateProvider(path, stateConverter) ++ }), ++ newTraceAccessor: func( ++ logger log.Logger, ++ m metrics.Metricer, ++ l2Client utils.L2HeaderSource, ++ prestateProvider faultTypes.PrestateProvider, ++ vmPrestateProvider faultTypes.PrestateProvider, ++ rollupClient outputs.OutputRollupClient, ++ dir string, ++ l1Head eth.BlockID, ++ splitDepth faultTypes.Depth, ++ prestateBlock uint64, ++ poststateBlock uint64) (*trace.Accessor, error) { ++ provider := vmPrestateProvider.(*vm.PrestateProvider) ++ return outputs.NewOutputAsteriscTraceAccessor(logger, m, cfg.AsteriscKona, serverExecutor, l2Client, prestateProvider, provider.PrestatePath(), rollupClient, dir, l1Head, splitDepth, prestateBlock, poststateBlock) ++ }, ++ } ++} ++ + func NewAlphabetRegisterTask(gameType faultTypes.GameType) *RegisterTask { + return &RegisterTask{ + gameType: gameType, +@@ -132,13 +168,14 @@ } +  + func cachePrestates( + gameType faultTypes.GameType, ++ stateConverter vm.StateConverter, + m caching.Metrics, + prestateBaseURL *url.URL, + preStatePath string, + prestateDir string, + newPrestateProvider func(path string) faultTypes.PrestateProvider, + ) func(prestateHash common.Hash) (faultTypes.PrestateProvider, error) { +- prestateSource := prestates.NewPrestateSource(prestateBaseURL, preStatePath, prestateDir) ++ prestateSource := prestates.NewPrestateSource(prestateBaseURL, preStatePath, prestateDir, stateConverter) + prestateProviderCache := prestates.NewPrestateProviderCache(m, fmt.Sprintf("prestates-%v", gameType), func(prestateHash common.Hash) (faultTypes.PrestateProvider, error) { + prestatePath, err := prestateSource.PrestatePath(prestateHash) + if err != nil {
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+8
+
-2
+ +
+ +
+
+
diff --git OP/op-challenger/metrics/metrics.go CELO/op-challenger/metrics/metrics.go +index fdea90841a043d8bc39bdcf7ade4c187bb134477..c6acc2b2f7bbf29957ade8e2f4e88fde3a33f9b0 100644 +--- OP/op-challenger/metrics/metrics.go ++++ CELO/op-challenger/metrics/metrics.go +@@ -38,8 +38,6 @@ + RecordGameStep() + RecordGameMove() + RecordGameL2Challenge() +- RecordVmExecutionTime(vmType string, t time.Duration) +- RecordVmMemoryUsed(vmType string, memoryUsed uint64) + RecordClaimResolutionTime(t float64) + RecordGameActTime(t float64) +  +@@ -60,6 +58,10 @@ IncActiveExecutors() + DecActiveExecutors() + IncIdleExecutors() + DecIdleExecutors() ++ ++ // Record vm execution metrics ++ VmMetricer ++ VmMetrics(vmType string) *VmMetrics + } +  + // Metrics implementation must implement RegistryMetricer to allow the metrics server to work. +@@ -339,3 +341,7 @@ + func (m *Metrics) RecordGameUpdateCompleted() { + m.inflightGames.Sub(1) + } ++ ++func (m *Metrics) VmMetrics(vmType string) *VmMetrics { ++ return NewVmMetrics(m, vmType) ++}
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+4
+
-0
+ +
+ +
+
+
diff --git OP/op-challenger/metrics/noop.go CELO/op-challenger/metrics/noop.go +index 99a89965aa213c94c4efd5b6fdaf362447411ec3..84b5923a33d98ea336b45b9d66d648da58936dcc 100644 +--- OP/op-challenger/metrics/noop.go ++++ CELO/op-challenger/metrics/noop.go +@@ -56,3 +56,7 @@ func (*NoopMetricsImpl) DecIdleExecutors() {} +  + func (*NoopMetricsImpl) CacheAdd(_ string, _ int, _ bool) {} + func (*NoopMetricsImpl) CacheGet(_ string, _ bool) {} ++ ++func (m *NoopMetricsImpl) VmMetrics(vmType string) *VmMetrics { ++ return NewVmMetrics(m, vmType) ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+28
+
-0
+ +
+ +
+
+
diff --git OP/op-challenger/metrics/vm.go CELO/op-challenger/metrics/vm.go +new file mode 100644 +index 0000000000000000000000000000000000000000..70e9a363cb368612951910318586387cc0d41820 +--- /dev/null ++++ CELO/op-challenger/metrics/vm.go +@@ -0,0 +1,28 @@ ++package metrics ++ ++import "time" ++ ++type VmMetricer interface { ++ RecordVmExecutionTime(vmType string, t time.Duration) ++ RecordVmMemoryUsed(vmType string, memoryUsed uint64) ++} ++ ++type VmMetrics struct { ++ m VmMetricer ++ vmType string ++} ++ ++func NewVmMetrics(m VmMetricer, vmType string) *VmMetrics { ++ return &VmMetrics{ ++ m: m, ++ vmType: vmType, ++ } ++} ++ ++func (m *VmMetrics) RecordExecutionTime(dur time.Duration) { ++ m.m.RecordVmExecutionTime(m.vmType, dur) ++} ++ ++func (m *VmMetrics) RecordMemoryUsed(memoryUsed uint64) { ++ m.m.RecordVmMemoryUsed(m.vmType, memoryUsed) ++}
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+36
+
-10
+ +
+ +
+
+
diff --git OP/op-challenger/runner/factory.go CELO/op-challenger/runner/factory.go +index dae0a3fce14608504f3a408bed854ead85ada6ee..898afdbbf1b7a8977cb934e425fc903be23080a2 100644 +--- OP/op-challenger/runner/factory.go ++++ CELO/op-challenger/runner/factory.go +@@ -29,37 +29,63 @@ ) (types.TraceProvider, error) { + switch traceType { + case types.TraceTypeCannon: + vmConfig := vm.NewOpProgramServerExecutor() +- prestate, err := getPrestate(prestateHash, cfg.CannonAbsolutePreStateBaseURL, cfg.CannonAbsolutePreState, dir) ++ stateConverter := cannon.NewStateConverter() ++ prestate, err := getPrestate(prestateHash, cfg.CannonAbsolutePreStateBaseURL, cfg.CannonAbsolutePreState, dir, stateConverter) + if err != nil { + return nil, err + } +- prestateProvider := cannon.NewPrestateProvider(prestate) ++ prestateProvider := vm.NewPrestateProvider(prestate, stateConverter) + return cannon.NewTraceProvider(logger, m, cfg.Cannon, vmConfig, prestateProvider, prestate, localInputs, dir, 42), nil + case types.TraceTypeAsterisc: + vmConfig := vm.NewOpProgramServerExecutor() +- prestate, err := getPrestate(prestateHash, cfg.AsteriscAbsolutePreStateBaseURL, cfg.AsteriscAbsolutePreState, dir) ++ stateConverter := asterisc.NewStateConverter() ++ prestate, err := getPrestate(prestateHash, cfg.AsteriscAbsolutePreStateBaseURL, cfg.AsteriscAbsolutePreState, dir, stateConverter) + if err != nil { + return nil, err + } +- prestateProvider := asterisc.NewPrestateProvider(prestate) ++ prestateProvider := vm.NewPrestateProvider(prestate, stateConverter) + return asterisc.NewTraceProvider(logger, m, cfg.Asterisc, vmConfig, prestateProvider, prestate, localInputs, dir, 42), nil + case types.TraceTypeAsteriscKona: +- vmConfig := vm.NewKonaServerExecutor() +- prestate, err := getPrestate(prestateHash, cfg.AsteriscAbsolutePreStateBaseURL, cfg.AsteriscAbsolutePreState, dir) ++ vmConfig := vm.NewKonaExecutor() ++ stateConverter := asterisc.NewStateConverter() ++ prestate, err := getPrestate(prestateHash, cfg.AsteriscKonaAbsolutePreStateBaseURL, cfg.AsteriscKonaAbsolutePreState, dir, stateConverter) + if err != nil { + return nil, err + } +- prestateProvider := asterisc.NewPrestateProvider(prestate) +- return asterisc.NewTraceProvider(logger, m, cfg.Asterisc, vmConfig, prestateProvider, prestate, localInputs, dir, 42), nil ++ prestateProvider := vm.NewPrestateProvider(prestate, stateConverter) ++ return asterisc.NewTraceProvider(logger, m, cfg.AsteriscKona, vmConfig, prestateProvider, prestate, localInputs, dir, 42), nil + } + return nil, errors.New("invalid trace type") + } +  +-func getPrestate(prestateHash common.Hash, prestateBaseUrl *url.URL, prestatePath string, dataDir string) (string, error) { ++func createMTTraceProvider( ++ logger log.Logger, ++ m vm.Metricer, ++ vmConfig vm.Config, ++ prestateHash common.Hash, ++ absolutePrestateBaseURL *url.URL, ++ traceType types.TraceType, ++ localInputs utils.LocalGameInputs, ++ dir string, ++) (types.TraceProvider, error) { ++ executor := vm.NewOpProgramServerExecutor() ++ stateConverter := cannon.NewStateConverter() ++ ++ prestateSource := prestates.NewMultiPrestateProvider(absolutePrestateBaseURL, filepath.Join(dir, "prestates"), cannon.NewStateConverter()) ++ prestatePath, err := prestateSource.PrestatePath(prestateHash) ++ if err != nil { ++ return nil, fmt.Errorf("failed to get prestate %v: %w", prestateHash, err) ++ } ++ prestateProvider := vm.NewPrestateProvider(prestatePath, stateConverter) ++ return cannon.NewTraceProvider(logger, m, vmConfig, executor, prestateProvider, prestatePath, localInputs, dir, 42), nil ++} ++ ++func getPrestate(prestateHash common.Hash, prestateBaseUrl *url.URL, prestatePath string, dataDir string, stateConverter vm.StateConverter) (string, error) { + prestateSource := prestates.NewPrestateSource( + prestateBaseUrl, + prestatePath, +- filepath.Join(dataDir, "prestates")) ++ filepath.Join(dataDir, "prestates"), ++ stateConverter) +  + prestate, err := prestateSource.PrestatePath(prestateHash) + if err != nil {
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+6
+
-7
+ +
+ +
+
+
diff --git OP/op-challenger/runner/metrics.go CELO/op-challenger/runner/metrics.go +index e15ad95adc1bf52d8c7c8bfd3fed195f44c5174e..1f347b62aa685244e7ca74c1fc9fe50d3f782fef 100644 +--- OP/op-challenger/runner/metrics.go ++++ CELO/op-challenger/runner/metrics.go +@@ -4,7 +4,6 @@ import ( + "time" +  + contractMetrics "github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts/metrics" +- "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" + opmetrics "github.com/ethereum-optimism/optimism/op-service/metrics" + "github.com/prometheus/client_golang/prometheus" + ) +@@ -100,14 +99,14 @@ m.vmMemoryUsed.WithLabelValues(vmType).Observe(float64(memoryUsed)) + m.vmLastMemoryUsed.WithLabelValues(vmType).Set(float64(memoryUsed)) + } +  +-func (m *Metrics) RecordSuccess(vmType types.TraceType) { +- m.successTotal.WithLabelValues(vmType.String()).Inc() ++func (m *Metrics) RecordSuccess(vmType string) { ++ m.successTotal.WithLabelValues(vmType).Inc() + } +  +-func (m *Metrics) RecordFailure(vmType types.TraceType) { +- m.failuresTotal.WithLabelValues(vmType.String()).Inc() ++func (m *Metrics) RecordFailure(vmType string) { ++ m.failuresTotal.WithLabelValues(vmType).Inc() + } +  +-func (m *Metrics) RecordInvalid(vmType types.TraceType) { +- m.invalidTotal.WithLabelValues(vmType.String()).Inc() ++func (m *Metrics) RecordInvalid(vmType string) { ++ m.invalidTotal.WithLabelValues(vmType).Inc() + }
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+88
+
-31
+ +
+ +
+
+
diff --git OP/op-challenger/runner/runner.go CELO/op-challenger/runner/runner.go +index 8c46f0f0a6bf50970574db83b8b58e845a185f6b..61fc8180905f69ad7057b496350c2a54a1eeddfa 100644 +--- OP/op-challenger/runner/runner.go ++++ CELO/op-challenger/runner/runner.go +@@ -5,6 +5,7 @@ "context" + "errors" + "fmt" + "math/big" ++ "net/url" + "os" + "path/filepath" + "sync" +@@ -16,8 +17,8 @@ "github.com/ethereum-optimism/optimism/op-challenger/config" + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts" + contractMetrics "github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts/metrics" + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/utils" +- "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/vm" + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" ++ "github.com/ethereum-optimism/optimism/op-challenger/metrics" + "github.com/ethereum-optimism/optimism/op-service/cliapp" + "github.com/ethereum-optimism/optimism/op-service/dial" + "github.com/ethereum-optimism/optimism/op-service/httputil" +@@ -28,23 +29,28 @@ "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/log" + ) +  ++const mtCannonType = "mt-cannon" ++ + var ( + ErrUnexpectedStatusCode = errors.New("unexpected status code") + ) +  + type Metricer interface { +- vm.Metricer + contractMetrics.ContractMetricer +  +- RecordFailure(vmType types.TraceType) +- RecordInvalid(vmType types.TraceType) +- RecordSuccess(vmType types.TraceType) ++ RecordVmExecutionTime(vmType string, t time.Duration) ++ RecordVmMemoryUsed(vmType string, memoryUsed uint64) ++ RecordFailure(vmType string) ++ RecordInvalid(vmType string) ++ RecordSuccess(vmType string) + } +  + type Runner struct { +- log log.Logger +- cfg *config.Config +- m Metricer ++ log log.Logger ++ cfg *config.Config ++ addMTCannonPrestate common.Hash ++ addMTCannonPrestateURL *url.URL ++ m Metricer +  + running atomic.Bool + ctx context.Context +@@ -53,11 +59,13 @@ wg sync.WaitGroup + metricsSrv *httputil.HTTPServer + } +  +-func NewRunner(logger log.Logger, cfg *config.Config) *Runner { ++func NewRunner(logger log.Logger, cfg *config.Config, mtCannonPrestate common.Hash, mtCannonPrestateURL *url.URL) *Runner { + return &Runner{ +- log: logger, +- cfg: cfg, +- m: NewMetrics(), ++ log: logger, ++ cfg: cfg, ++ addMTCannonPrestate: mtCannonPrestate, ++ addMTCannonPrestateURL: mtCannonPrestateURL, ++ m: NewMetrics(), + } + } +  +@@ -97,16 +105,7 @@ defer r.wg.Done() + t := time.NewTicker(1 * time.Minute) + defer t.Stop() + for { +- if err := r.runOnce(ctx, traceType, client, caller); errors.Is(err, ErrUnexpectedStatusCode) { +- r.log.Error("Incorrect status code", "type", traceType, "err", err) +- r.m.RecordInvalid(traceType) +- } else if err != nil { +- r.log.Error("Failed to run", "type", traceType, "err", err) +- r.m.RecordFailure(traceType) +- } else { +- r.log.Info("Successfully verified output root", "type", traceType) +- r.m.RecordSuccess(traceType) +- } ++ r.runAndRecordOnce(ctx, traceType, client, caller) + select { + case <-t.C: + case <-ctx.Done(): +@@ -115,22 +114,80 @@ } + } + } +  +-func (r *Runner) runOnce(ctx context.Context, traceType types.TraceType, client *sources.RollupClient, caller *batching.MultiCaller) error { ++func (r *Runner) runAndRecordOnce(ctx context.Context, traceType types.TraceType, client *sources.RollupClient, caller *batching.MultiCaller) { ++ recordError := func(err error, traceType string, m Metricer, log log.Logger) { ++ if errors.Is(err, ErrUnexpectedStatusCode) { ++ log.Error("Incorrect status code", "type", traceType, "err", err) ++ m.RecordInvalid(traceType) ++ } else if err != nil { ++ log.Error("Failed to run", "type", traceType, "err", err) ++ m.RecordFailure(traceType) ++ } else { ++ log.Info("Successfully verified output root", "type", traceType) ++ m.RecordSuccess(traceType) ++ } ++ } ++ + prestateHash, err := r.getPrestateHash(ctx, traceType, caller) + if err != nil { +- return err ++ recordError(err, traceType.String(), r.m, r.log) ++ return + } +  + localInputs, err := r.createGameInputs(ctx, client) + if err != nil { +- return err ++ recordError(err, traceType.String(), r.m, r.log) ++ return ++ } ++ ++ inputsLogger := r.log.New("l1", localInputs.L1Head, "l2", localInputs.L2Head, "l2Block", localInputs.L2BlockNumber, "claim", localInputs.L2Claim) ++ var wg sync.WaitGroup ++ wg.Add(1) ++ go func() { ++ defer wg.Done() ++ dir, err := r.prepDatadir(traceType.String()) ++ if err != nil { ++ recordError(err, traceType.String(), r.m, r.log) ++ return ++ } ++ err = r.runOnce(ctx, inputsLogger.With("type", traceType), traceType, prestateHash, localInputs, dir) ++ recordError(err, traceType.String(), r.m, r.log) ++ }() ++ ++ if traceType == types.TraceTypeCannon && r.addMTCannonPrestate != (common.Hash{}) && r.addMTCannonPrestateURL != nil { ++ wg.Add(1) ++ go func() { ++ defer wg.Done() ++ dir, err := r.prepDatadir(mtCannonType) ++ if err != nil { ++ recordError(err, mtCannonType, r.m, r.log) ++ return ++ } ++ logger := inputsLogger.With("type", mtCannonType) ++ err = r.runMTOnce(ctx, logger, localInputs, dir) ++ recordError(err, mtCannonType, r.m, r.log.With(mtCannonType, true)) ++ }() ++ } ++ wg.Wait() ++} ++ ++func (r *Runner) runOnce(ctx context.Context, logger log.Logger, traceType types.TraceType, prestateHash common.Hash, localInputs utils.LocalGameInputs, dir string) error { ++ provider, err := createTraceProvider(logger, metrics.NewVmMetrics(r.m, traceType.String()), r.cfg, prestateHash, traceType, localInputs, dir) ++ if err != nil { ++ return fmt.Errorf("failed to create trace provider: %w", err) + } +- dir, err := r.prepDatadir(traceType) ++ hash, err := provider.Get(ctx, types.RootPosition) + if err != nil { +- return err ++ return fmt.Errorf("failed to execute trace provider: %w", err) ++ } ++ if hash[0] != mipsevm.VMStatusValid { ++ return fmt.Errorf("%w: %v", ErrUnexpectedStatusCode, hash) + } +- logger := r.log.New("l1", localInputs.L1Head, "l2", localInputs.L2Head, "l2Block", localInputs.L2BlockNumber, "claim", localInputs.L2Claim, "type", traceType) +- provider, err := createTraceProvider(logger, r.m, r.cfg, prestateHash, traceType, localInputs, dir) ++ return nil ++} ++ ++func (r *Runner) runMTOnce(ctx context.Context, logger log.Logger, localInputs utils.LocalGameInputs, dir string) error { ++ provider, err := createMTTraceProvider(logger, metrics.NewVmMetrics(r.m, mtCannonType), r.cfg.Cannon, r.addMTCannonPrestate, r.addMTCannonPrestateURL, types.TraceTypeCannon, localInputs, dir) + if err != nil { + return fmt.Errorf("failed to create trace provider: %w", err) + } +@@ -144,8 +201,8 @@ } + return nil + } +  +-func (r *Runner) prepDatadir(traceType types.TraceType) (string, error) { +- dir := filepath.Join(r.cfg.Datadir, traceType.String()) ++func (r *Runner) prepDatadir(traceType string) (string, error) { ++ dir := filepath.Join(r.cfg.Datadir, traceType) + if err := os.RemoveAll(dir); err != nil { + return "", fmt.Errorf("failed to remove old dir: %w", err) + }
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+9
+
-0
+ +
+ +
+
+
diff --git OP/op-challenger/sender/sender_test.go CELO/op-challenger/sender/sender_test.go +index 2e0f09830605c377b3033c7af2f6160ebf28caa5..5169ae67192ad8726c378dd201bc06bf09a8cd83 100644 +--- OP/op-challenger/sender/sender_test.go ++++ CELO/op-challenger/sender/sender_test.go +@@ -3,6 +3,7 @@ + import ( + "context" + "fmt" ++ "math/big" + "sync" + "testing" + "time" +@@ -128,6 +129,10 @@ ch := s.recordTx(candidate) + return <-ch, nil + } +  ++func (s *stubTxMgr) SendAsync(ctx context.Context, candidate txmgr.TxCandidate, ch chan txmgr.SendResponse) { ++ panic("unimplemented") ++} ++ + func (s *stubTxMgr) recordTx(candidate txmgr.TxCandidate) chan *types.Receipt { + s.m.Lock() + defer s.m.Unlock() +@@ -177,3 +182,7 @@ } +  + func (s *stubTxMgr) Close() { + } ++ ++func (s *stubTxMgr) SuggestGasPriceCaps(context.Context) (*big.Int, *big.Int, *big.Int, error) { ++ panic("unimplemented") ++}
+
+ + + +
+
+ +
+
+
+ + +
+ +
+
+
+ +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+9
+
-8
+ +
+ +
+
+
diff --git OP/op-e2e/Makefile CELO/op-e2e/Makefile +index bd0cdba73bef92123626fd5631270dfd0b583f9d..f3f67f8050da20ee9aef72363e8ce2ca63e4e8cd 100644 +--- OP/op-e2e/Makefile ++++ CELO/op-e2e/Makefile +@@ -17,15 +17,15 @@ make -C ./external_$*/ + $(go_test) $(go_test_flags) --externalL2 ./external_$*/ +  + test-ws: pre-test +- $(go_test) $(go_test_flags) . ./e2eutils/... ++ $(go_test) $(go_test_flags) ./system/... ./e2eutils/... ./opgeth/... ./interop/... + .PHONY: test-ws +  + test-actions: pre-test +- $(go_test) $(go_test_flags) ./actions ++ $(go_test) $(go_test_flags) ./actions/... + .PHONY: test-actions +  + test-http: pre-test +- OP_E2E_USE_HTTP=true $(go_test) $(go_test_flags) . ./e2eutils/... ++ OP_E2E_USE_HTTP=true $(go_test) $(go_test_flags) ./system/... ./e2eutils/... ./opgeth/... ./interop/... + .PHONY: test-http +  + test-cannon: pre-test +@@ -40,8 +40,9 @@ test-devnet: pre-test + $(go_test) $(go_test_flags) ./devnet + .PHONY: test-devnet +  +-cannon-prestate: ++cannon-prestates: + make -C .. cannon-prestate ++ make -C .. cannon-prestate-mt + .PHONY: cannon-prestate +  + # We depend on the absolute pre-state generated by cannon to deploy the dispute game contracts. +@@ -54,7 +55,7 @@ .PHONY: pre-test +  + pre-test-cannon: + @if [ ! -e ../op-program/bin ]; then \ +- make cannon-prestate; \ ++ make cannon-prestates; \ + fi + .PHONY: pre-test-cannon +  +@@ -70,7 +71,7 @@ rm -r ../op-program/bin + .PHONY: clean +  + fuzz: +- go test -run NOTAREALTEST -tags cgo_test -v -fuzztime 10s -fuzz FuzzFjordCostFunction ./ +- go test -run NOTAREALTEST -tags cgo_test -v -fuzztime 10s -fuzz FuzzFastLzGethSolidity ./ +- go test -run NOTAREALTEST -tags cgo_test -v -fuzztime 10s -fuzz FuzzFastLzCgo ./ ++ go test -run NOTAREALTEST -tags cgo_test -v -fuzztime 10s -fuzz FuzzFjordCostFunction ./opgeth ++ go test -run NOTAREALTEST -tags cgo_test -v -fuzztime 10s -fuzz FuzzFastLzGethSolidity ./opgeth ++ go test -run NOTAREALTEST -tags cgo_test -v -fuzztime 10s -fuzz FuzzFastLzCgo ./opgeth +
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+41
+
-41
+ +
+ +
+
+
diff --git OP/op-e2e/actions/altda_test.go CELO/op-e2e/actions/altda/altda_test.go +rename from op-e2e/actions/altda_test.go +rename to op-e2e/actions/altda/altda_test.go +index 14889edabc889c4fae4a1cd6ad9cd68164dbbea3..ac122d9d999a58eea2b961da848cefe89a8dc10e 100644 +--- OP/op-e2e/actions/altda_test.go ++++ CELO/op-e2e/actions/altda/altda_test.go +@@ -1,10 +1,11 @@ +-package actions ++package altda +  + import ( + "math/big" + "math/rand" + "testing" +  ++ "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" + "github.com/stretchr/testify/require" +  + "github.com/ethereum/go-ethereum/accounts/abi/bind" +@@ -32,21 +33,21 @@ storage *altda.DAErrFaker + daMgr *altda.DA + altDACfg altda.Config + contract *bindings.DataAvailabilityChallenge +- batcher *L2Batcher +- sequencer *L2Sequencer +- engine *L2Engine ++ batcher *helpers.L2Batcher ++ sequencer *helpers.L2Sequencer ++ engine *helpers.L2Engine + engCl *sources.EngineClient + sd *e2eutils.SetupData + dp *e2eutils.DeployParams +- miner *L1Miner +- alice *CrossLayerUser ++ miner *helpers.L1Miner ++ alice *helpers.CrossLayerUser + lastComm []byte + lastCommBn uint64 + } +  + type AltDAParam func(p *e2eutils.TestParams) +  +-func NewL2AltDA(t Testing, params ...AltDAParam) *L2AltDA { ++func NewL2AltDA(t helpers.Testing, params ...AltDAParam) *L2AltDA { + p := &e2eutils.TestParams{ + MaxSequencerDrift: 40, + SequencerWindowSize: 12, +@@ -60,15 +61,15 @@ } + log := testlog.Logger(t, log.LvlDebug) +  + dp := e2eutils.MakeDeployParams(t, p) +- sd := e2eutils.Setup(t, dp, defaultAlloc) ++ sd := e2eutils.Setup(t, dp, helpers.DefaultAlloc) +  + require.True(t, sd.RollupCfg.AltDAEnabled()) +  +- miner := NewL1Miner(t, log, sd.L1Cfg) ++ miner := helpers.NewL1Miner(t, log, sd.L1Cfg) + l1Client := miner.EthClient() +  + jwtPath := e2eutils.WriteDefaultJWT(t) +- engine := NewL2Engine(t, log, sd.L2Cfg, sd.RollupCfg.Genesis.L1, jwtPath) ++ engine := helpers.NewL2Engine(t, log, sd.L2Cfg, sd.RollupCfg.Genesis.L1, jwtPath) + engCl := engine.EngineClient(t, sd.RollupCfg) +  + storage := &altda.DAErrFaker{Client: altda.NewMockDAClient(log)} +@@ -81,21 +82,21 @@ require.NoError(t, err) +  + daMgr := altda.NewAltDAWithStorage(log, altDACfg, storage, &altda.NoopMetrics{}) +  +- sequencer := NewL2Sequencer(t, log, l1F, miner.BlobStore(), daMgr, engCl, sd.RollupCfg, 0) ++ sequencer := helpers.NewL2Sequencer(t, log, l1F, miner.BlobStore(), daMgr, engCl, sd.RollupCfg, 0, nil) + miner.ActL1SetFeeRecipient(common.Address{'A'}) + sequencer.ActL2PipelineFull(t) +  +- batcher := NewL2Batcher(log, sd.RollupCfg, AltDABatcherCfg(dp, storage), sequencer.RollupClient(), l1Client, engine.EthClient(), engCl) ++ batcher := helpers.NewL2Batcher(log, sd.RollupCfg, helpers.AltDABatcherCfg(dp, storage), sequencer.RollupClient(), l1Client, engine.EthClient(), engCl) +  + addresses := e2eutils.CollectAddresses(sd, dp) + cl := engine.EthClient() +- l2UserEnv := &BasicUserEnv[*L2Bindings]{ ++ l2UserEnv := &helpers.BasicUserEnv[*helpers.L2Bindings]{ + EthCl: cl, + Signer: types.LatestSigner(sd.L2Cfg.Config), + AddressCorpora: addresses, +- Bindings: NewL2Bindings(t, cl, engine.GethClient()), ++ Bindings: helpers.NewL2Bindings(t, cl, engine.GethClient()), + } +- alice := NewCrossLayerUser(log, dp.Secrets.Alice, rand.New(rand.NewSource(0xa57b))) ++ alice := helpers.NewCrossLayerUser(log, dp.Secrets.Alice, rand.New(rand.NewSource(0xa57b))) + alice.L2.SetUserEnv(l2UserEnv) +  + contract, err := bindings.NewDataAvailabilityChallenge(sd.RollupCfg.AltDAConfig.DAChallengeAddress, l1Client) +@@ -130,21 +131,21 @@ func (a *L2AltDA) StorageClient() *altda.DAErrFaker { + return a.storage + } +  +-func (a *L2AltDA) NewVerifier(t Testing) *L2Verifier { ++func (a *L2AltDA) NewVerifier(t helpers.Testing) *helpers.L2Verifier { + jwtPath := e2eutils.WriteDefaultJWT(t) +- engine := NewL2Engine(t, a.log, a.sd.L2Cfg, a.sd.RollupCfg.Genesis.L1, jwtPath) ++ engine := helpers.NewL2Engine(t, a.log, a.sd.L2Cfg, a.sd.RollupCfg.Genesis.L1, jwtPath) + engCl := engine.EngineClient(t, a.sd.RollupCfg) + l1F, err := sources.NewL1Client(a.miner.RPCClient(), a.log, nil, sources.L1ClientDefaultConfig(a.sd.RollupCfg, false, sources.RPCKindBasic)) + require.NoError(t, err) +  + daMgr := altda.NewAltDAWithStorage(a.log, a.altDACfg, a.storage, &altda.NoopMetrics{}) +  +- verifier := NewL2Verifier(t, a.log, l1F, a.miner.BlobStore(), daMgr, engCl, a.sd.RollupCfg, &sync.Config{}, safedb.Disabled) ++ verifier := helpers.NewL2Verifier(t, a.log, l1F, a.miner.BlobStore(), daMgr, engCl, a.sd.RollupCfg, &sync.Config{}, safedb.Disabled, nil) +  + return verifier + } +  +-func (a *L2AltDA) ActSequencerIncludeTx(t Testing) { ++func (a *L2AltDA) ActSequencerIncludeTx(t helpers.Testing) { + a.alice.L2.ActResetTxOpts(t) + a.alice.L2.ActSetTxToAddr(&a.dp.Addresses.Bob)(t) + a.alice.L2.ActMakeTx(t) +@@ -156,7 +157,7 @@ a.engine.ActL2IncludeTx(a.alice.Address())(t) + a.sequencer.ActL2EndBlock(t) + } +  +-func (a *L2AltDA) ActNewL2Tx(t Testing) { ++func (a *L2AltDA) ActNewL2Tx(t helpers.Testing) { + a.ActSequencerIncludeTx(t) +  + a.batcher.ActL2BatchBuffer(t) +@@ -170,20 +171,20 @@ a.miner.ActL1StartBlock(12)(t) + a.miner.ActL1IncludeTx(a.dp.Addresses.Batcher)(t) + a.miner.ActL1EndBlock(t) +  +- a.lastCommBn = a.miner.l1Chain.CurrentBlock().Number.Uint64() ++ a.lastCommBn = a.miner.L1Chain().CurrentBlock().Number.Uint64() + } +  +-func (a *L2AltDA) ActDeleteLastInput(t Testing) { ++func (a *L2AltDA) ActDeleteLastInput(t helpers.Testing) { + require.NoError(t, a.storage.Client.DeleteData(a.lastComm)) + } +  +-func (a *L2AltDA) ActChallengeLastInput(t Testing) { ++func (a *L2AltDA) ActChallengeLastInput(t helpers.Testing) { + a.ActChallengeInput(t, a.lastComm, a.lastCommBn) +  + a.log.Info("challenged last input", "block", a.lastCommBn) + } +  +-func (a *L2AltDA) ActChallengeInput(t Testing, comm []byte, bn uint64) { ++func (a *L2AltDA) ActChallengeInput(t helpers.Testing, comm []byte, bn uint64) { + bondValue, err := a.contract.BondSize(&bind.CallOpts{}) + require.NoError(t, err) +  +@@ -209,15 +210,15 @@ a.miner.ActL1IncludeTx(a.alice.Address())(t) + a.miner.ActL1EndBlock(t) + } +  +-func (a *L2AltDA) ActExpireLastInput(t Testing) { ++func (a *L2AltDA) ActExpireLastInput(t helpers.Testing) { + reorgWindow := a.altDACfg.ResolveWindow + a.altDACfg.ChallengeWindow +- for a.miner.l1Chain.CurrentBlock().Number.Uint64() <= a.lastCommBn+reorgWindow { ++ for a.miner.L1Chain().CurrentBlock().Number.Uint64() <= a.lastCommBn+reorgWindow { + a.miner.ActL1StartBlock(12)(t) + a.miner.ActL1EndBlock(t) + } + } +  +-func (a *L2AltDA) ActResolveInput(t Testing, comm []byte, input []byte, bn uint64) { ++func (a *L2AltDA) ActResolveInput(t helpers.Testing, comm []byte, input []byte, bn uint64) { + txOpts, err := bind.NewKeyedTransactorWithChainID(a.dp.Secrets.Alice, a.sd.L1Cfg.Config.ChainID) + require.NoError(t, err) +  +@@ -229,7 +230,7 @@ a.miner.ActL1IncludeTx(a.alice.Address())(t) + a.miner.ActL1EndBlock(t) + } +  +-func (a *L2AltDA) ActResolveLastChallenge(t Testing) { ++func (a *L2AltDA) ActResolveLastChallenge(t helpers.Testing) { + // remove derivation byte prefix + input, err := a.storage.GetInput(t.Ctx(), altda.Keccak256Commitment(a.lastComm[1:])) + require.NoError(t, err) +@@ -237,23 +238,22 @@ + a.ActResolveInput(t, a.lastComm, input, a.lastCommBn) + } +  +-func (a *L2AltDA) ActL1Blocks(t Testing, n uint64) { ++func (a *L2AltDA) ActL1Blocks(t helpers.Testing, n uint64) { + for i := uint64(0); i < n; i++ { + a.miner.ActL1StartBlock(12)(t) + a.miner.ActL1EndBlock(t) + } + } +  +-func (a *L2AltDA) GetLastTxBlock(t Testing) *types.Block { +- rcpt, err := a.engine.EthClient().TransactionReceipt(t.Ctx(), a.alice.L2.lastTxHash) +- require.NoError(t, err) ++func (a *L2AltDA) GetLastTxBlock(t helpers.Testing) *types.Block { ++ rcpt := a.alice.L2.LastTxReceipt(t) + blk, err := a.engine.EthClient().BlockByHash(t.Ctx(), rcpt.BlockHash) + require.NoError(t, err) + return blk + } +  +-func (a *L2AltDA) ActL1Finalized(t Testing) { +- latest := a.miner.l1Chain.CurrentBlock().Number.Uint64() ++func (a *L2AltDA) ActL1Finalized(t helpers.Testing) { ++ latest := a.miner.L1Chain().CurrentBlock().Number.Uint64() + a.miner.ActL1Safe(t, latest) + a.miner.ActL1Finalize(t, latest) + a.sequencer.ActL1FinalizedSignal(t) +@@ -265,7 +265,7 @@ if !e2eutils.UseAltDA() { + gt.Skip("AltDA is not enabled") + } +  +- t := NewDefaultTesting(gt) ++ t := helpers.NewDefaultTesting(gt) + harness := NewL2AltDA(t) +  + // generate enough initial l1 blocks to have a finalized head. +@@ -325,7 +325,7 @@ if !e2eutils.UseAltDA() { + gt.Skip("AltDA is not enabled") + } +  +- t := NewDefaultTesting(gt) ++ t := helpers.NewDefaultTesting(gt) + harness := NewL2AltDA(t) +  + // include a new l2 transaction, submitting an input commitment to the l1. +@@ -373,7 +373,7 @@ if !e2eutils.UseAltDA() { + gt.Skip("AltDA is not enabled") + } +  +- t := NewDefaultTesting(gt) ++ t := helpers.NewDefaultTesting(gt) + harness := NewL2AltDA(t) +  + // include a new l2 transaction, submitting an input commitment to the l1. +@@ -402,7 +402,7 @@ if !e2eutils.UseAltDA() { + gt.Skip("AltDA is not enabled") + } +  +- t := NewDefaultTesting(gt) ++ t := helpers.NewDefaultTesting(gt) + harness := NewL2AltDA(t) +  + // New L2 tx added to a batch and committed to L1 +@@ -450,7 +450,7 @@ if !e2eutils.UseAltDA() { + gt.Skip("AltDA is not enabled") + } +  +- t := NewDefaultTesting(gt) ++ t := helpers.NewDefaultTesting(gt) + a := NewL2AltDA(t) +  + // create a new tx on l2 and commit it to l1 +@@ -509,7 +509,7 @@ // keep track of the second commitment + comm2 := a.lastComm + _, err = a.storage.GetInput(t.Ctx(), altda.Keccak256Commitment(comm2[1:])) + require.NoError(t, err) +- a.lastCommBn = a.miner.l1Chain.CurrentBlock().Number.Uint64() ++ a.lastCommBn = a.miner.L1Chain().CurrentBlock().Number.Uint64() +  + // ensure the second commitment is distinct from the first + require.NotEqual(t, comm1, comm2) +@@ -545,7 +545,7 @@ func TestAltDA_Finalization(gt *testing.T) { + if !e2eutils.UseAltDA() { + gt.Skip("AltDA is not enabled") + } +- t := NewDefaultTesting(gt) ++ t := helpers.NewDefaultTesting(gt) + a := NewL2AltDA(t) +  + // build L1 block #1
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+14
+
-13
+ +
+ +
+
+
diff --git OP/op-e2e/actions/eip4844_test.go CELO/op-e2e/actions/batcher/eip4844_test.go +rename from op-e2e/actions/eip4844_test.go +rename to op-e2e/actions/batcher/eip4844_test.go +index ddab21d48b47dfa518da27a311a869e7a8ce7de3..6d77a3961788d8689323dae09e2f9b169bbeced8 100644 +--- OP/op-e2e/actions/eip4844_test.go ++++ CELO/op-e2e/actions/batcher/eip4844_test.go +@@ -1,8 +1,9 @@ +-package actions ++package batcher +  + import ( + "testing" +  ++ "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" + "github.com/stretchr/testify/require" +  + "github.com/ethereum/go-ethereum/common" +@@ -16,26 +17,26 @@ "github.com/ethereum-optimism/optimism/op-node/rollup/sync" + "github.com/ethereum-optimism/optimism/op-service/testlog" + ) +  +-func setupEIP4844Test(t Testing, log log.Logger) (*e2eutils.SetupData, *e2eutils.DeployParams, *L1Miner, *L2Sequencer, *L2Engine, *L2Verifier, *L2Engine) { +- dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) ++func setupEIP4844Test(t helpers.Testing, log log.Logger) (*e2eutils.SetupData, *e2eutils.DeployParams, *helpers.L1Miner, *helpers.L2Sequencer, *helpers.L2Engine, *helpers.L2Verifier, *helpers.L2Engine) { ++ dp := e2eutils.MakeDeployParams(t, helpers.DefaultRollupTestParams) + genesisActivation := hexutil.Uint64(0) + dp.DeployConfig.L1CancunTimeOffset = &genesisActivation + dp.DeployConfig.L2GenesisCanyonTimeOffset = &genesisActivation + dp.DeployConfig.L2GenesisDeltaTimeOffset = &genesisActivation + dp.DeployConfig.L2GenesisEcotoneTimeOffset = &genesisActivation +  +- sd := e2eutils.Setup(t, dp, defaultAlloc) +- miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) ++ sd := e2eutils.Setup(t, dp, helpers.DefaultAlloc) ++ miner, seqEngine, sequencer := helpers.SetupSequencerTest(t, sd, log) + miner.ActL1SetFeeRecipient(common.Address{'A'}) + sequencer.ActL2PipelineFull(t) +- verifEngine, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) ++ verifEngine, verifier := helpers.SetupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) + return sd, dp, miner, sequencer, seqEngine, verifier, verifEngine + } +  +-func setupBatcher(t Testing, log log.Logger, sd *e2eutils.SetupData, dp *e2eutils.DeployParams, miner *L1Miner, +- sequencer *L2Sequencer, engine *L2Engine, daType batcherFlags.DataAvailabilityType, +-) *L2Batcher { +- return NewL2Batcher(log, sd.RollupCfg, &BatcherCfg{ ++func setupBatcher(t helpers.Testing, log log.Logger, sd *e2eutils.SetupData, dp *e2eutils.DeployParams, miner *helpers.L1Miner, ++ sequencer *helpers.L2Sequencer, engine *helpers.L2Engine, daType batcherFlags.DataAvailabilityType, ++) *helpers.L2Batcher { ++ return helpers.NewL2Batcher(log, sd.RollupCfg, &helpers.BatcherCfg{ + MinL1TxSize: 0, + MaxL1TxSize: 128_000, + BatcherKey: dp.Secrets.Batcher, +@@ -44,7 +45,7 @@ }, sequencer.RollupClient(), miner.EthClient(), engine.EthClient(), engine.EngineClient(t, sd.RollupCfg)) + } +  + func TestEIP4844DataAvailability(gt *testing.T) { +- t := NewDefaultTesting(gt) ++ t := helpers.NewDefaultTesting(gt) +  + log := testlog.Logger(t, log.LevelDebug) + sd, dp, miner, sequencer, seqEngine, verifier, _ := setupEIP4844Test(t, log) +@@ -82,7 +83,7 @@ require.NotEqual(t, sequencer.L2Safe(), sequencer.L2Unsafe(), "sequencer has not processed L1 yet") + } +  + func TestEIP4844MultiBlobs(gt *testing.T) { +- t := NewDefaultTesting(gt) ++ t := helpers.NewDefaultTesting(gt) +  + log := testlog.Logger(t, log.LevelDebug) + sd, dp, miner, sequencer, seqEngine, verifier, _ := setupEIP4844Test(t, log) +@@ -121,7 +122,7 @@ require.NotEqual(t, sequencer.L2Safe(), sequencer.L2Unsafe(), "sequencer has not processed L1 yet") + } +  + func TestEIP4844DataAvailabilitySwitch(gt *testing.T) { +- t := NewDefaultTesting(gt) ++ t := helpers.NewDefaultTesting(gt) +  + log := testlog.Logger(t, log.LevelDebug) + sd, dp, miner, sequencer, seqEngine, verifier, _ := setupEIP4844Test(t, log)
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+60
+
-79
+ +
+ +
+
+
diff --git OP/op-e2e/actions/l2_batcher_test.go CELO/op-e2e/actions/batcher/l2_batcher_test.go +rename from op-e2e/actions/l2_batcher_test.go +rename to op-e2e/actions/batcher/l2_batcher_test.go +index 6235c7482326b022d7d2328bafe6996957f19a52..9739a78b6c019336f3bbc62401e7cb093c2ed465 100644 +--- OP/op-e2e/actions/l2_batcher_test.go ++++ CELO/op-e2e/actions/batcher/l2_batcher_test.go +@@ -1,4 +1,4 @@ +-package actions ++package batcher +  + import ( + "errors" +@@ -6,6 +6,8 @@ "math/big" + "math/rand" + "testing" +  ++ actionsHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" ++ upgradesHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/upgrades/helpers" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/types" +@@ -50,29 +52,8 @@ }) + } + } +  +-// applyDeltaTimeOffset adjusts fork configuration to not conflict with the delta overrides +-func applyDeltaTimeOffset(dp *e2eutils.DeployParams, deltaTimeOffset *hexutil.Uint64) { +- dp.DeployConfig.L2GenesisDeltaTimeOffset = deltaTimeOffset +- // configure Ecotone to not be before Delta accidentally +- if dp.DeployConfig.L2GenesisEcotoneTimeOffset != nil { +- if deltaTimeOffset == nil { +- dp.DeployConfig.L2GenesisEcotoneTimeOffset = nil +- } else if *dp.DeployConfig.L2GenesisEcotoneTimeOffset < *deltaTimeOffset { +- dp.DeployConfig.L2GenesisEcotoneTimeOffset = deltaTimeOffset +- } +- } +- // configure Fjord to not be before Delta accidentally +- if dp.DeployConfig.L2GenesisFjordTimeOffset != nil { +- if deltaTimeOffset == nil { +- dp.DeployConfig.L2GenesisFjordTimeOffset = nil +- } else if *dp.DeployConfig.L2GenesisFjordTimeOffset < *deltaTimeOffset { +- dp.DeployConfig.L2GenesisFjordTimeOffset = deltaTimeOffset +- } +- } +-} +- + func NormalBatcher(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { +- t := NewDefaultTesting(gt) ++ t := actionsHelpers.NewDefaultTesting(gt) + p := &e2eutils.TestParams{ + MaxSequencerDrift: 20, // larger than L1 block time we simulate in this test (12) + SequencerWindowSize: 24, +@@ -80,14 +61,14 @@ ChannelTimeout: 20, + L1BlockTime: 12, + } + dp := e2eutils.MakeDeployParams(t, p) +- applyDeltaTimeOffset(dp, deltaTimeOffset) +- sd := e2eutils.Setup(t, dp, defaultAlloc) ++ upgradesHelpers.ApplyDeltaTimeOffset(dp, deltaTimeOffset) ++ sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) + log := testlog.Logger(t, log.LevelDebug) +- miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) +- verifEngine, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) ++ miner, seqEngine, sequencer := actionsHelpers.SetupSequencerTest(t, sd, log) ++ verifEngine, verifier := actionsHelpers.SetupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) +  + rollupSeqCl := sequencer.RollupClient() +- batcher := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp), ++ batcher := actionsHelpers.NewL2Batcher(log, sd.RollupCfg, actionsHelpers.DefaultBatcherCfg(dp), + rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) +  + // Alice makes a L2 tx +@@ -99,7 +80,7 @@ tx := types.MustSignNewTx(dp.Secrets.Alice, signer, &types.DynamicFeeTx{ + ChainID: sd.L2Cfg.Config.ChainID, + Nonce: n, + GasTipCap: big.NewInt(2 * params.GWei), +- GasFeeCap: new(big.Int).Add(miner.l1Chain.CurrentBlock().BaseFee, big.NewInt(2*params.GWei)), ++ GasFeeCap: new(big.Int).Add(miner.L1Chain().CurrentBlock().BaseFee, big.NewInt(2*params.GWei)), + Gas: params.TxGas, + To: &dp.Addresses.Bob, + Value: e2eutils.Ether(2), +@@ -123,8 +104,8 @@ // confirm batch on L1 + miner.ActL1StartBlock(12)(t) + miner.ActL1IncludeTx(dp.Addresses.Batcher)(t) + miner.ActL1EndBlock(t) +- bl := miner.l1Chain.CurrentBlock() +- log.Info("bl", "txs", len(miner.l1Chain.GetBlockByHash(bl.Hash()).Transactions())) ++ bl := miner.L1Chain().CurrentBlock() ++ log.Info("bl", "txs", len(miner.L1Chain().GetBlockByHash(bl.Hash()).Transactions())) +  + // Now make enough L1 blocks that the verifier will have to derive a L2 block + // It will also eagerly derive the block from the batcher +@@ -147,12 +128,12 @@ require.NotNil(t, vTx) + } +  + func L2Finalization(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { +- t := NewDefaultTesting(gt) +- dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) +- applyDeltaTimeOffset(dp, deltaTimeOffset) +- sd := e2eutils.Setup(t, dp, defaultAlloc) ++ t := actionsHelpers.NewDefaultTesting(gt) ++ dp := e2eutils.MakeDeployParams(t, actionsHelpers.DefaultRollupTestParams) ++ upgradesHelpers.ApplyDeltaTimeOffset(dp, deltaTimeOffset) ++ sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) + log := testlog.Logger(t, log.LevelDebug) +- miner, engine, sequencer := setupSequencerTest(t, sd, log) ++ miner, engine, sequencer := actionsHelpers.SetupSequencerTest(t, sd, log) +  + sequencer.ActL2PipelineFull(t) +  +@@ -184,7 +165,7 @@ require.Equal(t, uint64(2), sequencer.SyncStatus().SafeL1.Number) + require.Equal(t, uint64(1), sequencer.SyncStatus().FinalizedL1.Number) + require.Equal(t, uint64(0), sequencer.SyncStatus().FinalizedL2.Number, "L2 block has to be included on L1 before it can be finalized") +  +- batcher := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp), ++ batcher := actionsHelpers.NewL2Batcher(log, sd.RollupCfg, actionsHelpers.DefaultBatcherCfg(dp), + sequencer.RollupClient(), miner.EthClient(), engine.EthClient(), engine.EngineClient(t, sd.RollupCfg)) +  + heightToSubmit := sequencer.SyncStatus().UnsafeL2.Number +@@ -244,12 +225,12 @@ } +  + // L2FinalizationWithSparseL1 tests that safe L2 blocks can be finalized even if we do not regularly get a L1 finalization signal + func L2FinalizationWithSparseL1(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { +- t := NewDefaultTesting(gt) +- dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) +- applyDeltaTimeOffset(dp, deltaTimeOffset) +- sd := e2eutils.Setup(t, dp, defaultAlloc) ++ t := actionsHelpers.NewDefaultTesting(gt) ++ dp := e2eutils.MakeDeployParams(t, actionsHelpers.DefaultRollupTestParams) ++ upgradesHelpers.ApplyDeltaTimeOffset(dp, deltaTimeOffset) ++ sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) + log := testlog.Logger(t, log.LevelDebug) +- miner, engine, sequencer := setupSequencerTest(t, sd, log) ++ miner, engine, sequencer := actionsHelpers.SetupSequencerTest(t, sd, log) +  + sequencer.ActL2PipelineFull(t) +  +@@ -260,7 +241,7 @@ + startStatus := sequencer.SyncStatus() + require.Less(t, startStatus.SafeL2.Number, startStatus.UnsafeL2.Number, "sequencer has unsafe L2 block") +  +- batcher := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp), ++ batcher := actionsHelpers.NewL2Batcher(log, sd.RollupCfg, actionsHelpers.DefaultBatcherCfg(dp), + sequencer.RollupClient(), miner.EthClient(), engine.EthClient(), engine.EngineClient(t, sd.RollupCfg)) + batcher.ActSubmitAll(t) +  +@@ -300,29 +281,29 @@ // GarbageBatch tests the behavior of an invalid/malformed output channel frame containing + // valid batches being submitted to the batch inbox. These batches should always be rejected + // and the safe L2 head should remain unaltered. + func GarbageBatch(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { +- t := NewDefaultTesting(gt) +- p := defaultRollupTestParams ++ t := actionsHelpers.NewDefaultTesting(gt) ++ p := actionsHelpers.DefaultRollupTestParams + dp := e2eutils.MakeDeployParams(t, p) +- applyDeltaTimeOffset(dp, deltaTimeOffset) +- for _, garbageKind := range GarbageKinds { +- sd := e2eutils.Setup(t, dp, defaultAlloc) ++ upgradesHelpers.ApplyDeltaTimeOffset(dp, deltaTimeOffset) ++ for _, garbageKind := range actionsHelpers.GarbageKinds { ++ sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) + log := testlog.Logger(t, log.LevelError) +- miner, engine, sequencer := setupSequencerTest(t, sd, log) ++ miner, engine, sequencer := actionsHelpers.SetupSequencerTest(t, sd, log) +  +- _, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) ++ _, verifier := actionsHelpers.SetupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) +  +- batcherCfg := DefaultBatcherCfg(dp) ++ batcherCfg := actionsHelpers.DefaultBatcherCfg(dp) +  +- if garbageKind == MALFORM_RLP || garbageKind == INVALID_COMPRESSION { ++ if garbageKind == actionsHelpers.MALFORM_RLP || garbageKind == actionsHelpers.INVALID_COMPRESSION { + // If the garbage kind is `INVALID_COMPRESSION` or `MALFORM_RLP`, use the `actions` packages + // modified `ChannelOut`. +- batcherCfg.GarbageCfg = &GarbageChannelCfg{ +- useInvalidCompression: garbageKind == INVALID_COMPRESSION, +- malformRLP: garbageKind == MALFORM_RLP, ++ batcherCfg.GarbageCfg = &actionsHelpers.GarbageChannelCfg{ ++ UseInvalidCompression: garbageKind == actionsHelpers.INVALID_COMPRESSION, ++ MalformRLP: garbageKind == actionsHelpers.MALFORM_RLP, + } + } +  +- batcher := NewL2Batcher(log, sd.RollupCfg, batcherCfg, sequencer.RollupClient(), miner.EthClient(), engine.EthClient(), engine.EngineClient(t, sd.RollupCfg)) ++ batcher := actionsHelpers.NewL2Batcher(log, sd.RollupCfg, batcherCfg, sequencer.RollupClient(), miner.EthClient(), engine.EthClient(), engine.EngineClient(t, sd.RollupCfg)) +  + sequencer.ActL2PipelineFull(t) + verifier.ActL2PipelineFull(t) +@@ -376,7 +357,7 @@ } + } +  + func ExtendedTimeWithoutL1Batches(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { +- t := NewDefaultTesting(gt) ++ t := actionsHelpers.NewDefaultTesting(gt) + p := &e2eutils.TestParams{ + MaxSequencerDrift: 20, // larger than L1 block time we simulate in this test (12) + SequencerWindowSize: 24, +@@ -384,14 +365,14 @@ ChannelTimeout: 20, + L1BlockTime: 12, + } + dp := e2eutils.MakeDeployParams(t, p) +- applyDeltaTimeOffset(dp, deltaTimeOffset) +- sd := e2eutils.Setup(t, dp, defaultAlloc) ++ upgradesHelpers.ApplyDeltaTimeOffset(dp, deltaTimeOffset) ++ sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) + log := testlog.Logger(t, log.LevelError) +- miner, engine, sequencer := setupSequencerTest(t, sd, log) ++ miner, engine, sequencer := actionsHelpers.SetupSequencerTest(t, sd, log) +  +- _, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) ++ _, verifier := actionsHelpers.SetupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) +  +- batcher := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp), ++ batcher := actionsHelpers.NewL2Batcher(log, sd.RollupCfg, actionsHelpers.DefaultBatcherCfg(dp), + sequencer.RollupClient(), miner.EthClient(), engine.EthClient(), engine.EngineClient(t, sd.RollupCfg)) +  + sequencer.ActL2PipelineFull(t) +@@ -432,7 +413,7 @@ // The goal of this test is to quickly run through an otherwise very slow process of submitting and including lots of data. + // This does not test the batcher code, but is really focused at testing the batcher utils + // and channel-decoding verifier code in the derive package. + func BigL2Txs(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { +- t := NewDefaultTesting(gt) ++ t := actionsHelpers.NewDefaultTesting(gt) + p := &e2eutils.TestParams{ + MaxSequencerDrift: 100, + SequencerWindowSize: 1000, +@@ -440,14 +421,14 @@ ChannelTimeout: 200, // give enough space to buffer large amounts of data before submitting it + L1BlockTime: 12, + } + dp := e2eutils.MakeDeployParams(t, p) +- applyDeltaTimeOffset(dp, deltaTimeOffset) +- sd := e2eutils.Setup(t, dp, defaultAlloc) ++ upgradesHelpers.ApplyDeltaTimeOffset(dp, deltaTimeOffset) ++ sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) + log := testlog.Logger(t, log.LevelInfo) +- miner, engine, sequencer := setupSequencerTest(t, sd, log) ++ miner, engine, sequencer := actionsHelpers.SetupSequencerTest(t, sd, log) +  +- _, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) ++ _, verifier := actionsHelpers.SetupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) +  +- batcher := NewL2Batcher(log, sd.RollupCfg, &BatcherCfg{ ++ batcher := actionsHelpers.NewL2Batcher(log, sd.RollupCfg, &actionsHelpers.BatcherCfg{ + MinL1TxSize: 0, + MaxL1TxSize: 40_000, // try a small batch size, to force the data to be split between more frames + BatcherKey: dp.Secrets.Batcher, +@@ -478,7 +459,7 @@ miner.ActEmptyBlock(t) + } + sequencer.ActL1HeadSignal(t) + sequencer.ActL2StartBlock(t) +- baseFee := engine.l2Chain.CurrentBlock().BaseFee // this will go quite high, since so many consecutive blocks are filled at capacity. ++ baseFee := engine.L2Chain().CurrentBlock().BaseFee // this will go quite high, since so many consecutive blocks are filled at capacity. + // fill the block with large L2 txs from alice + for n := aliceNonce; ; n++ { + require.NoError(t, err) +@@ -486,9 +467,9 @@ signer := types.LatestSigner(sd.L2Cfg.Config) + data := make([]byte, 120_000) // very large L2 txs, as large as the tx-pool will accept + _, err := rng.Read(data[:]) // fill with random bytes, to make compression ineffective + require.NoError(t, err) +- gas, err := core.IntrinsicGas(data, nil, false, true, true, false) ++ gas, err := core.IntrinsicGas(data, nil, false, true, true, false, nil, nil) + require.NoError(t, err) +- if gas > engine.engineApi.RemainingBlockGas() { ++ if gas > engine.EngineApi.RemainingBlockGas() { + break + } + tx := types.MustSignNewTx(dp.Secrets.Alice, signer, &types.DynamicFeeTx{ +@@ -505,12 +486,12 @@ require.NoError(t, cl.SendTransaction(t.Ctx(), tx)) + engine.ActL2IncludeTx(dp.Addresses.Alice)(t) + } + sequencer.ActL2EndBlock(t) +- for batcher.l2BufferedBlock.Number < sequencer.SyncStatus().UnsafeL2.Number { ++ for batcher.L2BufferedBlock.Number < sequencer.SyncStatus().UnsafeL2.Number { + // if we run out of space, close the channel and submit all the txs + if err := batcher.Buffer(t); errors.Is(err, derive.ErrTooManyRLPBytes) || errors.Is(err, derive.ErrCompressorFull) { +- log.Info("flushing filled channel to batch txs", "id", batcher.l2ChannelOut.ID()) ++ log.Info("flushing filled channel to batch txs", "id", batcher.L2ChannelOut.ID()) + batcher.ActL2ChannelClose(t) +- for batcher.l2ChannelOut != nil { ++ for batcher.L2ChannelOut != nil { + batcher.ActL2BatchSubmit(t, batcherTxOpts) + } + } +@@ -518,16 +499,16 @@ } + } +  + // if anything is left in the channel, submit it +- if batcher.l2ChannelOut != nil { +- log.Info("flushing trailing channel to batch txs", "id", batcher.l2ChannelOut.ID()) ++ if batcher.L2ChannelOut != nil { ++ log.Info("flushing trailing channel to batch txs", "id", batcher.L2ChannelOut.ID()) + batcher.ActL2ChannelClose(t) +- for batcher.l2ChannelOut != nil { ++ for batcher.L2ChannelOut != nil { + batcher.ActL2BatchSubmit(t, batcherTxOpts) + } + } +  + // build L1 blocks until we're out of txs +- txs, _ := miner.eth.TxPool().ContentFrom(dp.Addresses.Batcher) ++ txs, _ := miner.Eth.TxPool().ContentFrom(dp.Addresses.Batcher) + for { + if len(txs) == 0 { + break +@@ -538,7 +519,7 @@ if len(txs) == 0 { + break + } + tx := txs[0] +- if miner.l1GasPool.Gas() < tx.Gas() { // fill the L1 block with batcher txs until we run out of gas ++ if miner.L1GasPool.Gas() < tx.Gas() { // fill the L1 block with batcher txs until we run out of gas + break + } + log.Info("including batcher tx", "nonce", tx.Nonce())
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+26
+
-22
+ +
+ +
+
+
diff --git OP/op-e2e/actions/batch_queue_test.go CELO/op-e2e/actions/derivation/batch_queue_test.go +rename from op-e2e/actions/batch_queue_test.go +rename to op-e2e/actions/derivation/batch_queue_test.go +index 40ff0a2da2af3954c117701edc98f248c3c7cbe9..af5b7231b88490eff68bc7b511ffc7b0b675e477 100644 +--- OP/op-e2e/actions/batch_queue_test.go ++++ CELO/op-e2e/actions/derivation/batch_queue_test.go +@@ -1,13 +1,16 @@ +-package actions ++package derivation +  + import ( + "testing" +  + altda "github.com/ethereum-optimism/optimism/op-alt-da" + batcherFlags "github.com/ethereum-optimism/optimism/op-batcher/flags" ++ "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" ++ upgradesHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/upgrades/helpers" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" + "github.com/ethereum-optimism/optimism/op-node/node/safedb" + "github.com/ethereum-optimism/optimism/op-node/rollup/derive" ++ "github.com/ethereum-optimism/optimism/op-node/rollup/sync" + "github.com/ethereum-optimism/optimism/op-service/sources" + "github.com/ethereum-optimism/optimism/op-service/testlog" + "github.com/ethereum/go-ethereum/log" +@@ -20,7 +23,7 @@ // just one block prior to the origin of the safe head. + // This is a regression test, previously the pipeline encountered got stuck in a reset loop with the error: + // buffered L1 chain epoch %s in batch queue does not match safe head origin %s + func TestDeriveChainFromNearL1Genesis(gt *testing.T) { +- t := NewDefaultTesting(gt) ++ t := helpers.NewDefaultTesting(gt) + p := &e2eutils.TestParams{ + MaxSequencerDrift: 20, // larger than L1 block time we simulate in this test (12) + SequencerWindowSize: 24, +@@ -29,22 +32,22 @@ L1BlockTime: 12, + } + dp := e2eutils.MakeDeployParams(t, p) + // do not activate Delta hardfork for verifier +- applyDeltaTimeOffset(dp, nil) +- sd := e2eutils.Setup(t, dp, defaultAlloc) ++ upgradesHelpers.ApplyDeltaTimeOffset(dp, nil) ++ sd := e2eutils.Setup(t, dp, helpers.DefaultAlloc) + logger := testlog.Logger(t, log.LevelInfo) +- miner, seqEngine, sequencer := setupSequencerTest(t, sd, logger) ++ miner, seqEngine, sequencer := helpers.SetupSequencerTest(t, sd, logger) +  + miner.ActEmptyBlock(t) +- require.EqualValues(gt, 1, miner.l1Chain.CurrentBlock().Number.Uint64()) ++ require.EqualValues(gt, 1, miner.L1Chain().CurrentBlock().Number.Uint64()) +  +- ref, err := derive.L2BlockToBlockRef(sequencer.rollupCfg, seqEngine.l2Chain.Genesis()) ++ ref, err := derive.L2BlockToBlockRef(sequencer.RollupCfg, seqEngine.L2Chain().Genesis()) + require.NoError(gt, err) + require.EqualValues(gt, 0, ref.L1Origin.Number) +  + sequencer.ActL1HeadSignal(t) + sequencer.ActBuildToL1Head(t) +- l2BlockNum := seqEngine.l2Chain.CurrentBlock().Number.Uint64() +- ref, err = derive.L2BlockToBlockRef(sequencer.rollupCfg, seqEngine.l2Chain.GetBlockByNumber(l2BlockNum)) ++ l2BlockNum := seqEngine.L2Chain().CurrentBlock().Number.Uint64() ++ ref, err = derive.L2BlockToBlockRef(sequencer.RollupCfg, seqEngine.L2Chain().GetBlockByNumber(l2BlockNum)) + require.NoError(gt, err) + require.EqualValues(gt, 1, ref.L1Origin.Number) +  +@@ -52,7 +55,7 @@ miner.ActEmptyBlock(t) +  + rollupSeqCl := sequencer.RollupClient() + // Force batcher to submit SingularBatches to L1. +- batcher := NewL2Batcher(logger, sd.RollupCfg, &BatcherCfg{ ++ batcher := helpers.NewL2Batcher(logger, sd.RollupCfg, &helpers.BatcherCfg{ + MinL1TxSize: 0, + MaxL1TxSize: 128_000, + BatcherKey: dp.Secrets.Batcher, +@@ -60,39 +63,40 @@ DataAvailabilityType: batcherFlags.CalldataType, + }, rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) +  + batcher.ActSubmitAll(t) +- require.EqualValues(gt, l2BlockNum, batcher.l2BufferedBlock.Number) ++ require.EqualValues(gt, l2BlockNum, batcher.L2BufferedBlock.Number) +  + // confirm batch on L1 + miner.ActL1StartBlock(12)(t) + miner.ActL1IncludeTx(dp.Addresses.Batcher)(t) + miner.ActL1EndBlock(t) +- bl := miner.l1Chain.CurrentBlock() ++ bl := miner.L1Chain().CurrentBlock() + logger.Info("Produced L1 block with batch", +- "num", miner.l1Chain.CurrentBlock().Number.Uint64(), +- "txs", len(miner.l1Chain.GetBlockByHash(bl.Hash()).Transactions())) ++ "num", miner.L1Chain().CurrentBlock().Number.Uint64(), ++ "txs", len(miner.L1Chain().GetBlockByHash(bl.Hash()).Transactions())) +  + // Process batches so safe head updates + sequencer.ActL1HeadSignal(t) + sequencer.ActL2PipelineFull(t) +- require.EqualValues(gt, l2BlockNum, seqEngine.l2Chain.CurrentSafeBlock().Number.Uint64()) ++ require.EqualValues(gt, l2BlockNum, seqEngine.L2Chain().CurrentSafeBlock().Number.Uint64()) +  + // Finalize L1 and process so L2 finalized updates +- miner.ActL1Safe(t, miner.l1Chain.CurrentBlock().Number.Uint64()) +- miner.ActL1Finalize(t, miner.l1Chain.CurrentBlock().Number.Uint64()) ++ miner.ActL1Safe(t, miner.L1Chain().CurrentBlock().Number.Uint64()) ++ miner.ActL1Finalize(t, miner.L1Chain().CurrentBlock().Number.Uint64()) + sequencer.ActL1SafeSignal(t) + sequencer.ActL1FinalizedSignal(t) + sequencer.ActL2PipelineFull(t) +- require.EqualValues(gt, l2BlockNum, seqEngine.l2Chain.CurrentFinalBlock().Number.Uint64()) ++ require.EqualValues(gt, l2BlockNum, seqEngine.L2Chain().CurrentFinalBlock().Number.Uint64()) +  + // Create a new verifier using the existing engine so it already has the safe and finalized heads set. + // This is the same situation as if op-node restarted at this point. + l2Cl, err := sources.NewEngineClient(seqEngine.RPCClient(), logger, nil, sources.EngineClientDefaultConfig(sd.RollupCfg)) + require.NoError(gt, err) +- verifier := NewL2Verifier(t, logger, sequencer.l1, miner.BlobStore(), altda.Disabled, l2Cl, sequencer.rollupCfg, sequencer.syncCfg, safedb.Disabled) ++ verifier := helpers.NewL2Verifier(t, logger, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), altda.Disabled, ++ l2Cl, sequencer.RollupCfg, &sync.Config{}, safedb.Disabled, nil) + verifier.ActL2PipelineFull(t) // Should not get stuck in a reset loop forever +- require.EqualValues(gt, l2BlockNum, seqEngine.l2Chain.CurrentSafeBlock().Number.Uint64()) +- require.EqualValues(gt, l2BlockNum, seqEngine.l2Chain.CurrentFinalBlock().Number.Uint64()) +- syncStatus := verifier.syncStatus.SyncStatus() ++ require.EqualValues(gt, l2BlockNum, seqEngine.L2Chain().CurrentSafeBlock().Number.Uint64()) ++ require.EqualValues(gt, l2BlockNum, seqEngine.L2Chain().CurrentFinalBlock().Number.Uint64()) ++ syncStatus := verifier.SyncStatus() + require.EqualValues(gt, l2BlockNum, syncStatus.SafeL2.Number) + require.EqualValues(gt, l2BlockNum, syncStatus.FinalizedL2.Number) + }
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+18
+
-16
+ +
+ +
+
+
diff --git OP/op-e2e/actions/blocktime_test.go CELO/op-e2e/actions/derivation/blocktime_test.go +rename from op-e2e/actions/blocktime_test.go +rename to op-e2e/actions/derivation/blocktime_test.go +index 7bf34e103cc7ddb94271d8c49a625bc5b5d26065..ec192d08ad78206a4b704429daa49c04fdd92b23 100644 +--- OP/op-e2e/actions/blocktime_test.go ++++ CELO/op-e2e/actions/derivation/blocktime_test.go +@@ -1,9 +1,11 @@ +-package actions ++package derivation +  + import ( + "math/big" + "testing" +  ++ actionsHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" ++ upgradesHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/upgrades/helpers" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" + "github.com/ethereum-optimism/optimism/op-service/testlog" + "github.com/ethereum/go-ethereum/common/hexutil" +@@ -44,16 +46,16 @@ // where there are also no other batches included in the sequence + // window. + // This is a regression test against the bug fixed in PR #4566 + func BatchInLastPossibleBlocks(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { +- t := NewDefaultTesting(gt) +- dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) +- applyDeltaTimeOffset(dp, deltaTimeOffset) ++ t := actionsHelpers.NewDefaultTesting(gt) ++ dp := e2eutils.MakeDeployParams(t, actionsHelpers.DefaultRollupTestParams) ++ upgradesHelpers.ApplyDeltaTimeOffset(dp, deltaTimeOffset) + dp.DeployConfig.SequencerWindowSize = 4 + dp.DeployConfig.L2BlockTime = 2 +  +- sd := e2eutils.Setup(t, dp, defaultAlloc) ++ sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) + log := testlog.Logger(t, log.LevelDebug) +  +- sd, _, miner, sequencer, sequencerEngine, _, _, batcher := setupReorgTestActors(t, dp, sd, log) ++ sd, _, miner, sequencer, sequencerEngine, _, _, batcher := actionsHelpers.SetupReorgTestActors(t, dp, sd, log) +  + signer := types.LatestSigner(sd.L2Cfg.Config) + cl := sequencerEngine.EthClient() +@@ -63,7 +65,7 @@ tx := types.MustSignNewTx(dp.Secrets.Alice, signer, &types.DynamicFeeTx{ + ChainID: sd.L2Cfg.Config.ChainID, + Nonce: aliceNonce, + GasTipCap: big.NewInt(2 * params.GWei), +- GasFeeCap: new(big.Int).Add(miner.l1Chain.CurrentBlock().BaseFee, big.NewInt(2*params.GWei)), ++ GasFeeCap: new(big.Int).Add(miner.L1Chain().CurrentBlock().BaseFee, big.NewInt(2*params.GWei)), + Gas: params.TxGas, + To: &dp.Addresses.Bob, + Value: e2eutils.Ether(2), +@@ -78,7 +80,7 @@ sequencerEngine.ActL2IncludeTx(dp.Addresses.Alice)(t) // include a test tx from alice + sequencer.ActL2EndBlock(t) + } + verifyChainStateOnSequencer := func(l1Number, unsafeHead, unsafeHeadOrigin, safeHead, safeHeadOrigin uint64) { +- require.Equal(t, l1Number, miner.l1Chain.CurrentHeader().Number.Uint64()) ++ require.Equal(t, l1Number, miner.L1Chain().CurrentHeader().Number.Uint64()) + require.Equal(t, unsafeHead, sequencer.L2Unsafe().Number) + require.Equal(t, unsafeHeadOrigin, sequencer.L2Unsafe().L1Origin.Number) + require.Equal(t, safeHead, sequencer.L2Safe().Number) +@@ -155,8 +157,8 @@ // Then it generates 3 more L1 blocks. + // At this point it can verify that the batches where properly generated. + // Note: It batches submits when possible. + func LargeL1Gaps(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { +- t := NewDefaultTesting(gt) +- dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) ++ t := actionsHelpers.NewDefaultTesting(gt) ++ dp := e2eutils.MakeDeployParams(t, actionsHelpers.DefaultRollupTestParams) + dp.DeployConfig.L1BlockTime = 4 + dp.DeployConfig.L2BlockTime = 2 + dp.DeployConfig.SequencerWindowSize = 4 +@@ -165,11 +167,11 @@ dp.DeployConfig.L2GenesisEcotoneTimeOffset = nil + dp.DeployConfig.L2GenesisFjordTimeOffset = nil + // TODO(client-pod#831): The Ecotone (and Fjord) activation blocks don't include user txs, + // so disabling these forks for now. +- applyDeltaTimeOffset(dp, deltaTimeOffset) +- sd := e2eutils.Setup(t, dp, defaultAlloc) ++ upgradesHelpers.ApplyDeltaTimeOffset(dp, deltaTimeOffset) ++ sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) + log := testlog.Logger(t, log.LevelDebug) +  +- sd, _, miner, sequencer, sequencerEngine, verifier, _, batcher := setupReorgTestActors(t, dp, sd, log) ++ sd, _, miner, sequencer, sequencerEngine, verifier, _, batcher := actionsHelpers.SetupReorgTestActors(t, dp, sd, log) +  + signer := types.LatestSigner(sd.L2Cfg.Config) + cl := sequencerEngine.EthClient() +@@ -180,7 +182,7 @@ tx := types.MustSignNewTx(dp.Secrets.Alice, signer, &types.DynamicFeeTx{ + ChainID: sd.L2Cfg.Config.ChainID, + Nonce: aliceNonce, + GasTipCap: big.NewInt(2 * params.GWei), +- GasFeeCap: new(big.Int).Add(miner.l1Chain.CurrentBlock().BaseFee, big.NewInt(2*params.GWei)), ++ GasFeeCap: new(big.Int).Add(miner.L1Chain().CurrentBlock().BaseFee, big.NewInt(2*params.GWei)), + Gas: params.TxGas, + To: &dp.Addresses.Bob, + Value: e2eutils.Ether(2), +@@ -196,7 +198,7 @@ sequencer.ActL2EndBlock(t) + } +  + verifyChainStateOnSequencer := func(l1Number, unsafeHead, unsafeHeadOrigin, safeHead, safeHeadOrigin uint64) { +- require.Equal(t, l1Number, miner.l1Chain.CurrentHeader().Number.Uint64()) ++ require.Equal(t, l1Number, miner.L1Chain().CurrentHeader().Number.Uint64()) + require.Equal(t, unsafeHead, sequencer.L2Unsafe().Number) + require.Equal(t, unsafeHeadOrigin, sequencer.L2Unsafe().L1Origin.Number) + require.Equal(t, safeHead, sequencer.L2Safe().Number) +@@ -204,7 +206,7 @@ require.Equal(t, safeHeadOrigin, sequencer.L2Safe().L1Origin.Number) + } +  + verifyChainStateOnVerifier := func(l1Number, unsafeHead, unsafeHeadOrigin, safeHead, safeHeadOrigin uint64) { +- require.Equal(t, l1Number, miner.l1Chain.CurrentHeader().Number.Uint64()) ++ require.Equal(t, l1Number, miner.L1Chain().CurrentHeader().Number.Uint64()) + require.Equal(t, unsafeHead, verifier.L2Unsafe().Number) + require.Equal(t, unsafeHeadOrigin, verifier.L2Unsafe().L1Origin.Number) + require.Equal(t, safeHead, verifier.L2Safe().Number)
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+78
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/actions/derivation/l2_verifier_test.go CELO/op-e2e/actions/derivation/l2_verifier_test.go +new file mode 100644 +index 0000000000000000000000000000000000000000..2f4fce628d534f0ea3d492a5cdd57b802f26e49c +--- /dev/null ++++ CELO/op-e2e/actions/derivation/l2_verifier_test.go +@@ -0,0 +1,78 @@ ++package derivation ++ ++import ( ++ "testing" ++ ++ "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" ++ "github.com/ethereum/go-ethereum/common" ++ "github.com/ethereum/go-ethereum/log" ++ "github.com/stretchr/testify/require" ++ ++ "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" ++ "github.com/ethereum-optimism/optimism/op-service/testlog" ++) ++ ++func TestL2Verifier_SequenceWindow(gt *testing.T) { ++ t := helpers.NewDefaultTesting(gt) ++ p := &e2eutils.TestParams{ ++ MaxSequencerDrift: 10, ++ SequencerWindowSize: 24, ++ ChannelTimeout: 10, ++ L1BlockTime: 15, ++ } ++ dp := e2eutils.MakeDeployParams(t, p) ++ sd := e2eutils.Setup(t, dp, helpers.DefaultAlloc) ++ log := testlog.Logger(t, log.LevelDebug) ++ miner, engine, verifier := helpers.SetupVerifierOnlyTest(t, sd, log) ++ miner.ActL1SetFeeRecipient(common.Address{'A'}) ++ ++ // Make two sequence windows worth of empty L1 blocks. After we pass the first sequence window, the L2 chain should get blocks ++ for miner.L1Chain().CurrentBlock().Number.Uint64() < sd.RollupCfg.SeqWindowSize*2 { ++ miner.ActL1StartBlock(10)(t) ++ miner.ActL1EndBlock(t) ++ ++ verifier.ActL2PipelineFull(t) ++ ++ l1Head := miner.L1Chain().CurrentBlock().Number.Uint64() ++ expectedL1Origin := uint64(0) ++ // as soon as we complete the sequence window, we force-adopt the L1 origin ++ if l1Head >= sd.RollupCfg.SeqWindowSize { ++ expectedL1Origin = l1Head - sd.RollupCfg.SeqWindowSize ++ } ++ require.Equal(t, expectedL1Origin, verifier.SyncStatus().SafeL2.L1Origin.Number, "L1 origin is forced in, given enough L1 blocks pass by") ++ require.LessOrEqual(t, miner.L1Chain().GetBlockByNumber(expectedL1Origin).Time(), engine.L2Chain().CurrentBlock().Time, "L2 time higher than L1 origin time") ++ } ++ tip2N := verifier.SyncStatus() ++ ++ // Do a deep L1 reorg as deep as a sequence window, this should affect the safe L2 chain ++ miner.ActL1RewindDepth(sd.RollupCfg.SeqWindowSize)(t) ++ ++ // Without new L1 block, the L1 appears to not be synced, and the node shouldn't reorg ++ verifier.ActL2PipelineFull(t) ++ require.Equal(t, tip2N.SafeL2, verifier.SyncStatus().SafeL2, "still the same after verifier work") ++ ++ // Make a new empty L1 block with different data than there was before. ++ miner.ActL1SetFeeRecipient(common.Address{'B'}) ++ miner.ActL1StartBlock(10)(t) ++ miner.ActL1EndBlock(t) ++ reorgL1Block := miner.L1Chain().CurrentBlock() ++ ++ // Still no reorg, we need more L1 blocks first, before the reorged L1 block is forced in by sequence window ++ verifier.ActL2PipelineFull(t) ++ require.Equal(t, tip2N.SafeL2, verifier.SyncStatus().SafeL2) ++ ++ for miner.L1Chain().CurrentBlock().Number.Uint64() < sd.RollupCfg.SeqWindowSize*2 { ++ miner.ActL1StartBlock(10)(t) ++ miner.ActL1EndBlock(t) ++ } ++ ++ // workaround: in L1Traversal we only recognize the reorg once we see origin N+1, we don't reorg to shorter L1 chains ++ miner.ActL1StartBlock(10)(t) ++ miner.ActL1EndBlock(t) ++ ++ // Now it will reorg ++ verifier.ActL2PipelineFull(t) ++ ++ got := miner.L1Chain().GetBlockByHash(miner.L1Chain().GetBlockByHash(verifier.SyncStatus().SafeL2.L1Origin.Hash).Hash()) ++ require.Equal(t, reorgL1Block.Hash(), got.Hash(), "must have reorged L2 chain to the new L1 chain") ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+47
+
-67
+ +
+ +
+
+
diff --git OP/op-e2e/actions/reorg_test.go CELO/op-e2e/actions/derivation/reorg_test.go +rename from op-e2e/actions/reorg_test.go +rename to op-e2e/actions/derivation/reorg_test.go +index 4036d9fb131cd08eb2c0f3743c3f7da846fb3bd6..6551b314c1ea6909d2438e49b126566c3a2df340 100644 +--- OP/op-e2e/actions/reorg_test.go ++++ CELO/op-e2e/actions/derivation/reorg_test.go +@@ -1,4 +1,4 @@ +-package actions ++package derivation +  + import ( + "math/big" +@@ -6,6 +6,8 @@ "math/rand" + "path" + "testing" +  ++ actionsHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" ++ upgradesHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/upgrades/helpers" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core/types" +@@ -16,34 +18,12 @@ "github.com/stretchr/testify/require" +  + altda "github.com/ethereum-optimism/optimism/op-alt-da" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" +- "github.com/ethereum-optimism/optimism/op-node/rollup/sync" + "github.com/ethereum-optimism/optimism/op-service/client" + "github.com/ethereum-optimism/optimism/op-service/eth" + "github.com/ethereum-optimism/optimism/op-service/sources" + "github.com/ethereum-optimism/optimism/op-service/testlog" + ) +  +-func setupReorgTest(t Testing, config *e2eutils.TestParams, deltaTimeOffset *hexutil.Uint64) (*e2eutils.SetupData, *e2eutils.DeployParams, *L1Miner, *L2Sequencer, *L2Engine, *L2Verifier, *L2Engine, *L2Batcher) { +- dp := e2eutils.MakeDeployParams(t, config) +- applyDeltaTimeOffset(dp, deltaTimeOffset) +- +- sd := e2eutils.Setup(t, dp, defaultAlloc) +- log := testlog.Logger(t, log.LevelDebug) +- +- return setupReorgTestActors(t, dp, sd, log) +-} +- +-func setupReorgTestActors(t Testing, dp *e2eutils.DeployParams, sd *e2eutils.SetupData, log log.Logger) (*e2eutils.SetupData, *e2eutils.DeployParams, *L1Miner, *L2Sequencer, *L2Engine, *L2Verifier, *L2Engine, *L2Batcher) { +- miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) +- miner.ActL1SetFeeRecipient(common.Address{'A'}) +- sequencer.ActL2PipelineFull(t) +- verifEngine, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) +- rollupSeqCl := sequencer.RollupClient() +- batcher := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp), +- rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) +- return sd, dp, miner, sequencer, seqEngine, verifier, verifEngine, batcher +-} +- + // TestReorgBatchType run each reorg-related test case in singular batch mode and span batch mode. + func TestReorgBatchType(t *testing.T) { + tests := []struct { +@@ -74,8 +54,8 @@ } + } +  + func ReorgOrphanBlock(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { +- t := NewDefaultTesting(gt) +- sd, _, miner, sequencer, _, verifier, verifierEng, batcher := setupReorgTest(t, defaultRollupTestParams, deltaTimeOffset) ++ t := actionsHelpers.NewDefaultTesting(gt) ++ sd, _, miner, sequencer, _, verifier, verifierEng, batcher := actionsHelpers.SetupReorgTest(t, actionsHelpers.DefaultRollupTestParams, deltaTimeOffset) + verifEngClient := verifierEng.EngineClient(t, sd.RollupCfg) +  + sequencer.ActL2PipelineFull(t) +@@ -94,7 +74,7 @@ + // new L1 block with L2 batch + miner.ActL1StartBlock(12)(t) + miner.ActL1IncludeTx(sd.RollupCfg.Genesis.SystemConfig.BatcherAddr)(t) +- batchTx := miner.l1Transactions[0] ++ batchTx := miner.L1Transactions[0] + miner.ActL1EndBlock(t) +  + // verifier picks up the L2 chain that was submitted +@@ -123,7 +103,7 @@ miner.ActL1StartBlock(12)(t) + miner.ActL1SetFeeRecipient(common.Address{'C'}) + // note: the geth tx pool reorgLoop is too slow (responds to chain head events, but async), + // and there's no way to manually trigger runReorg, so we re-insert it ourselves. +- require.NoError(t, miner.eth.TxPool().Add([]*types.Transaction{batchTx}, true, true)[0]) ++ require.NoError(t, miner.Eth.TxPool().Add([]*types.Transaction{batchTx}, true, true)[0]) + // need to re-insert previously included tx into the block + miner.ActL1IncludeTx(sd.RollupCfg.Genesis.SystemConfig.BatcherAddr)(t) + miner.ActL1EndBlock(t) +@@ -142,8 +122,8 @@ require.Equal(t, verifier.L2Safe(), sequencer.L2Safe(), "verifier and sequencer see same safe L2 block, while only verifier dealt with the orphan and replay") + } +  + func ReorgFlipFlop(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { +- t := NewDefaultTesting(gt) +- sd, _, miner, sequencer, _, verifier, verifierEng, batcher := setupReorgTest(t, defaultRollupTestParams, deltaTimeOffset) ++ t := actionsHelpers.NewDefaultTesting(gt) ++ sd, _, miner, sequencer, _, verifier, verifierEng, batcher := actionsHelpers.SetupReorgTest(t, actionsHelpers.DefaultRollupTestParams, deltaTimeOffset) + minerCl := miner.L1Client(t, sd.RollupCfg) + verifEngClient := verifierEng.EngineClient(t, sd.RollupCfg) + checkVerifEngine := func() { +@@ -172,7 +152,7 @@ // new L1 block A1 with L2 batch + miner.ActL1SetFeeRecipient(common.Address{'A', 1}) + miner.ActL1StartBlock(12)(t) + miner.ActL1IncludeTx(sd.RollupCfg.Genesis.SystemConfig.BatcherAddr)(t) +- batchTxA := miner.l1Transactions[0] ++ batchTxA := miner.L1Transactions[0] + miner.ActL1EndBlock(t) +  + // verifier picks up the L2 chain that was submitted +@@ -195,7 +175,7 @@ + // re-include the batch tx that submitted L2 chain data that pointed to A0, in the new block B1 + miner.ActL1SetFeeRecipient(common.Address{'B', 1}) + miner.ActL1StartBlock(12)(t) +- require.NoError(t, miner.eth.TxPool().Add([]*types.Transaction{batchTxA}, true, true)[0]) ++ require.NoError(t, miner.Eth.TxPool().Add([]*types.Transaction{batchTxA}, true, true)[0]) + miner.ActL1IncludeTx(sd.RollupCfg.Genesis.SystemConfig.BatcherAddr)(t) + miner.ActL1EndBlock(t) +  +@@ -219,7 +199,7 @@ } else { + // after delta hard fork + require.Zero(t, verifier.L2Safe().Number, "safe head is at genesis block because span batch referenced reorged L1 chain is not accepted") + require.Equal(t, verifier.L2Unsafe().ID(), sequencer.L2Unsafe().ParentID(), "head is at the highest unsafe block that references canonical L1 chain(genesis block)") +- batcher.l2BufferedBlock = eth.L2BlockRef{} // must reset batcher to resubmit blocks included in the last batch ++ batcher.L2BufferedBlock = eth.L2BlockRef{} // must reset batcher to resubmit blocks included in the last batch + } + checkVerifEngine() +  +@@ -260,7 +240,7 @@ miner.ActEmptyBlock(t) +  + miner.ActL1SetFeeRecipient(common.Address{'A', 2}) + miner.ActL1StartBlock(12)(t) +- require.NoError(t, miner.eth.TxPool().Add([]*types.Transaction{batchTxA}, true, true)[0]) // replay chain A batches, but now in A2 instead of A1 ++ require.NoError(t, miner.Eth.TxPool().Add([]*types.Transaction{batchTxA}, true, true)[0]) // replay chain A batches, but now in A2 instead of A1 + miner.ActL1IncludeTx(sd.RollupCfg.Genesis.SystemConfig.BatcherAddr)(t) + miner.ActL1EndBlock(t) +  +@@ -356,10 +336,10 @@ // Verifier + // - Unsafe head is 62 + // - Safe head is 42 + func DeepReorg(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { +- t := NewDefaultTesting(gt) ++ t := actionsHelpers.NewDefaultTesting(gt) +  + // Create actor and verification engine client +- sd, dp, miner, sequencer, seqEngine, verifier, verifierEng, batcher := setupReorgTest(t, &e2eutils.TestParams{ ++ sd, dp, miner, sequencer, seqEngine, verifier, verifierEng, batcher := actionsHelpers.SetupReorgTest(t, &e2eutils.TestParams{ + MaxSequencerDrift: 40, + SequencerWindowSize: 20, + ChannelTimeout: 120, +@@ -377,13 +357,13 @@ + // Set up alice + log := testlog.Logger(t, log.LevelDebug) + addresses := e2eutils.CollectAddresses(sd, dp) +- l2UserEnv := &BasicUserEnv[*L2Bindings]{ ++ l2UserEnv := &actionsHelpers.BasicUserEnv[*actionsHelpers.L2Bindings]{ + EthCl: l2Client, + Signer: types.LatestSigner(sd.L2Cfg.Config), + AddressCorpora: addresses, +- Bindings: NewL2Bindings(t, l2Client, seqEngine.GethClient()), ++ Bindings: actionsHelpers.NewL2Bindings(t, l2Client, seqEngine.GethClient()), + } +- alice := NewCrossLayerUser(log, dp.Secrets.Alice, rand.New(rand.NewSource(0xa57b))) ++ alice := actionsHelpers.NewCrossLayerUser(log, dp.Secrets.Alice, rand.New(rand.NewSource(0xa57b))) + alice.L2.SetUserEnv(l2UserEnv) +  + // Run one iteration of the L2 derivation pipeline +@@ -593,29 +573,29 @@ + // RestartOpGeth tests that the sequencer can restart its execution engine without rollup-node restart, + // including recovering the finalized/safe state of L2 chain without reorging. + func RestartOpGeth(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { +- t := NewDefaultTesting(gt) ++ t := actionsHelpers.NewDefaultTesting(gt) + dbPath := path.Join(t.TempDir(), "testdb") + dbOption := func(_ *ethconfig.Config, nodeCfg *node.Config) error { + nodeCfg.DataDir = dbPath + return nil + } +- dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) +- applyDeltaTimeOffset(dp, deltaTimeOffset) +- sd := e2eutils.Setup(t, dp, defaultAlloc) ++ dp := e2eutils.MakeDeployParams(t, actionsHelpers.DefaultRollupTestParams) ++ upgradesHelpers.ApplyDeltaTimeOffset(dp, deltaTimeOffset) ++ sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) + log := testlog.Logger(t, log.LevelDebug) + jwtPath := e2eutils.WriteDefaultJWT(t) + // L1 +- miner := NewL1Miner(t, log, sd.L1Cfg) ++ miner := actionsHelpers.NewL1Miner(t, log, sd.L1Cfg) + l1F, err := sources.NewL1Client(miner.RPCClient(), log, nil, sources.L1ClientDefaultConfig(sd.RollupCfg, false, sources.RPCKindStandard)) + require.NoError(t, err) + // Sequencer +- seqEng := NewL2Engine(t, log, sd.L2Cfg, sd.RollupCfg.Genesis.L1, jwtPath, dbOption) ++ seqEng := actionsHelpers.NewL2Engine(t, log, sd.L2Cfg, sd.RollupCfg.Genesis.L1, jwtPath, dbOption) + engRpc := &rpcWrapper{seqEng.RPCClient()} + l2Cl, err := sources.NewEngineClient(engRpc, log, nil, sources.EngineClientDefaultConfig(sd.RollupCfg)) + require.NoError(t, err) +- sequencer := NewL2Sequencer(t, log, l1F, miner.BlobStore(), altda.Disabled, l2Cl, sd.RollupCfg, 0) ++ sequencer := actionsHelpers.NewL2Sequencer(t, log, l1F, miner.BlobStore(), altda.Disabled, l2Cl, sd.RollupCfg, 0, nil) +  +- batcher := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp), ++ batcher := actionsHelpers.NewL2Batcher(log, sd.RollupCfg, actionsHelpers.DefaultBatcherCfg(dp), + sequencer.RollupClient(), miner.EthClient(), seqEng.EthClient(), seqEng.EngineClient(t, sd.RollupCfg)) +  + // start +@@ -664,7 +644,7 @@ + // close the sequencer engine + require.NoError(t, seqEng.Close()) + // and start a new one with same db path +- seqEngNew := NewL2Engine(t, log, sd.L2Cfg, sd.RollupCfg.Genesis.L1, jwtPath, dbOption) ++ seqEngNew := actionsHelpers.NewL2Engine(t, log, sd.L2Cfg, sd.RollupCfg.Genesis.L1, jwtPath, dbOption) + // swap in the new rpc. This is as close as we can get to reconnecting to a new in-memory rpc connection + engRpc.RPC = seqEngNew.RPCClient() +  +@@ -686,35 +666,35 @@ // ConflictingL2Blocks tests that a second copy of the sequencer stack cannot introduce an alternative + // L2 block (compared to something already secured by the first sequencer): + // the alt block is not synced by the verifier, in unsafe and safe sync modes. + func ConflictingL2Blocks(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { +- t := NewDefaultTesting(gt) +- dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) +- applyDeltaTimeOffset(dp, deltaTimeOffset) +- sd := e2eutils.Setup(t, dp, defaultAlloc) ++ t := actionsHelpers.NewDefaultTesting(gt) ++ dp := e2eutils.MakeDeployParams(t, actionsHelpers.DefaultRollupTestParams) ++ upgradesHelpers.ApplyDeltaTimeOffset(dp, deltaTimeOffset) ++ sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) + log := testlog.Logger(t, log.LevelDebug) +  +- sd, _, miner, sequencer, seqEng, verifier, _, batcher := setupReorgTestActors(t, dp, sd, log) ++ sd, _, miner, sequencer, seqEng, verifier, _, batcher := actionsHelpers.SetupReorgTestActors(t, dp, sd, log) +  + // Extra setup: a full alternative sequencer, sequencer engine, and batcher + jwtPath := e2eutils.WriteDefaultJWT(t) +- altSeqEng := NewL2Engine(t, log, sd.L2Cfg, sd.RollupCfg.Genesis.L1, jwtPath) ++ altSeqEng := actionsHelpers.NewL2Engine(t, log, sd.L2Cfg, sd.RollupCfg.Genesis.L1, jwtPath) + altSeqEngCl, err := sources.NewEngineClient(altSeqEng.RPCClient(), log, nil, sources.EngineClientDefaultConfig(sd.RollupCfg)) + require.NoError(t, err) + l1F, err := sources.NewL1Client(miner.RPCClient(), log, nil, sources.L1ClientDefaultConfig(sd.RollupCfg, false, sources.RPCKindStandard)) + require.NoError(t, err) +- altSequencer := NewL2Sequencer(t, log, l1F, miner.BlobStore(), altda.Disabled, altSeqEngCl, sd.RollupCfg, 0) +- altBatcher := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp), ++ altSequencer := actionsHelpers.NewL2Sequencer(t, log, l1F, miner.BlobStore(), altda.Disabled, altSeqEngCl, sd.RollupCfg, 0, nil) ++ altBatcher := actionsHelpers.NewL2Batcher(log, sd.RollupCfg, actionsHelpers.DefaultBatcherCfg(dp), + altSequencer.RollupClient(), miner.EthClient(), altSeqEng.EthClient(), altSeqEng.EngineClient(t, sd.RollupCfg)) +  + // And set up user Alice, using the alternative sequencer endpoint + l2Cl := altSeqEng.EthClient() + addresses := e2eutils.CollectAddresses(sd, dp) +- l2UserEnv := &BasicUserEnv[*L2Bindings]{ ++ l2UserEnv := &actionsHelpers.BasicUserEnv[*actionsHelpers.L2Bindings]{ + EthCl: l2Cl, + Signer: types.LatestSigner(sd.L2Cfg.Config), + AddressCorpora: addresses, +- Bindings: NewL2Bindings(t, l2Cl, altSeqEng.GethClient()), ++ Bindings: actionsHelpers.NewL2Bindings(t, l2Cl, altSeqEng.GethClient()), + } +- alice := NewCrossLayerUser(log, dp.Secrets.Alice, rand.New(rand.NewSource(1234))) ++ alice := actionsHelpers.NewCrossLayerUser(log, dp.Secrets.Alice, rand.New(rand.NewSource(1234))) + alice.L2.SetUserEnv(l2UserEnv) +  + sequencer.ActL2PipelineFull(t) +@@ -756,7 +736,7 @@ alice.L2.ActMakeTx(t) + altSeqEng.ActL2IncludeTx(alice.Address())(t) + altSequencer.ActL2EndBlock(t) +  +- conflictBlock := seqEng.l2Chain.GetBlockByNumber(altSequencer.L2Unsafe().Number) ++ conflictBlock := seqEng.L2Chain().GetBlockByNumber(altSequencer.L2Unsafe().Number) + require.NotEqual(t, conflictBlock.Hash(), altSequencer.L2Unsafe().Hash, "alt sequencer has built a conflicting block") +  + // give the unsafe block to the verifier, and see if it reorgs because of any unsafe inputs +@@ -776,7 +756,7 @@ // include it in L1 + miner.ActL1StartBlock(12)(t) + miner.ActL1IncludeTx(sd.RollupCfg.Genesis.SystemConfig.BatcherAddr)(t) + miner.ActL1EndBlock(t) +- l1Number := miner.l1Chain.CurrentHeader().Number.Uint64() ++ l1Number := miner.L1Chain().CurrentHeader().Number.Uint64() +  + // show latest L1 block with new batch data to verifier, and make it sync. + verifier.ActL1HeadSignal(t) +@@ -793,24 +773,24 @@ require.Equal(t, sequencer.L2Unsafe(), altSequencer.L2Unsafe(), "and gets back in harmony with original sequencer") + } +  + func SyncAfterReorg(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { +- t := NewDefaultTesting(gt) ++ t := actionsHelpers.NewDefaultTesting(gt) + testingParams := e2eutils.TestParams{ + MaxSequencerDrift: 60, + SequencerWindowSize: 4, + ChannelTimeout: 2, + L1BlockTime: 12, + } +- sd, dp, miner, sequencer, seqEngine, verifier, _, batcher := setupReorgTest(t, &testingParams, deltaTimeOffset) ++ sd, dp, miner, sequencer, seqEngine, verifier, _, batcher := actionsHelpers.SetupReorgTest(t, &testingParams, deltaTimeOffset) + l2Client := seqEngine.EthClient() + log := testlog.Logger(t, log.LevelDebug) + addresses := e2eutils.CollectAddresses(sd, dp) +- l2UserEnv := &BasicUserEnv[*L2Bindings]{ ++ l2UserEnv := &actionsHelpers.BasicUserEnv[*actionsHelpers.L2Bindings]{ + EthCl: l2Client, + Signer: types.LatestSigner(sd.L2Cfg.Config), + AddressCorpora: addresses, +- Bindings: NewL2Bindings(t, l2Client, seqEngine.GethClient()), ++ Bindings: actionsHelpers.NewL2Bindings(t, l2Client, seqEngine.GethClient()), + } +- alice := NewCrossLayerUser(log, dp.Secrets.Alice, rand.New(rand.NewSource(0xa57b))) ++ alice := actionsHelpers.NewCrossLayerUser(log, dp.Secrets.Alice, rand.New(rand.NewSource(0xa57b))) + alice.L2.SetUserEnv(l2UserEnv) +  + sequencer.ActL2PipelineFull(t) +@@ -820,11 +800,11 @@ // build empty L1 block: A0 + miner.ActL1SetFeeRecipient(common.Address{'A', 0}) + miner.ActEmptyBlock(t) + sequencer.ActL1HeadSignal(t) +- for sequencer.engine.UnsafeL2Head().L1Origin.Number < sequencer.syncStatus.L1Head().Number { ++ for sequencer.L2Unsafe().L1Origin.Number < sequencer.SyncStatus().HeadL1.Number { + // build L2 blocks until the L1 origin is the current L1 head(A0) + sequencer.ActL2PipelineFull(t) + sequencer.ActL2StartBlock(t) +- if sequencer.engine.UnsafeL2Head().Number == 11 { ++ if sequencer.L2Unsafe().Number == 11 { + // include a user tx at L2 block #12 to make a state transition + alice.L2.ActResetTxOpts(t) + alice.L2.ActSetTxToAddr(&dp.Addresses.Bob)(t)
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+34
+
-32
+ +
+ +
+
+
diff --git OP/op-e2e/actions/system_config_test.go CELO/op-e2e/actions/derivation/system_config_test.go +rename from op-e2e/actions/system_config_test.go +rename to op-e2e/actions/derivation/system_config_test.go +index 452d5dbc300b4035ad9c9da568ecd3d7813a3e58..bb62001de4a2083dfc1640fa9d7ee5b0f25e3f1b 100644 +--- OP/op-e2e/actions/system_config_test.go ++++ CELO/op-e2e/actions/derivation/system_config_test.go +@@ -1,10 +1,12 @@ +-package actions ++package derivation +  + import ( + "math/big" + "math/rand" + "testing" +  ++ actionsHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" ++ upgradesHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/upgrades/helpers" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" +@@ -49,27 +51,27 @@ + // BatcherKeyRotation tests that batcher A can operate, then be replaced with batcher B, then ignore old batcher A, + // and that the change to batcher B is reverted properly upon reorg of L1. + func BatcherKeyRotation(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { +- t := NewDefaultTesting(gt) ++ t := actionsHelpers.NewDefaultTesting(gt) +  +- dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) ++ dp := e2eutils.MakeDeployParams(t, actionsHelpers.DefaultRollupTestParams) + dp.DeployConfig.L2BlockTime = 2 +- applyDeltaTimeOffset(dp, deltaTimeOffset) +- sd := e2eutils.Setup(t, dp, defaultAlloc) ++ upgradesHelpers.ApplyDeltaTimeOffset(dp, deltaTimeOffset) ++ sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) + log := testlog.Logger(t, log.LevelDebug) +- miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) ++ miner, seqEngine, sequencer := actionsHelpers.SetupSequencerTest(t, sd, log) + miner.ActL1SetFeeRecipient(common.Address{'A'}) + sequencer.ActL2PipelineFull(t) +- _, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) ++ _, verifier := actionsHelpers.SetupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) + rollupSeqCl := sequencer.RollupClient() +  + // the default batcher +- batcherA := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp), ++ batcherA := actionsHelpers.NewL2Batcher(log, sd.RollupCfg, actionsHelpers.DefaultBatcherCfg(dp), + rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) +  + // a batcher with a new key +- altCfg := *DefaultBatcherCfg(dp) ++ altCfg := *actionsHelpers.DefaultBatcherCfg(dp) + altCfg.BatcherKey = dp.Secrets.Bob +- batcherB := NewL2Batcher(log, sd.RollupCfg, &altCfg, ++ batcherB := actionsHelpers.NewL2Batcher(log, sd.RollupCfg, &altCfg, + rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) +  + sequencer.ActL2PipelineFull(t) +@@ -114,7 +116,7 @@ + receipt, err := miner.EthClient().TransactionReceipt(t.Ctx(), tx.Hash()) + require.NoError(t, err) +  +- cfgChangeL1BlockNum := miner.l1Chain.CurrentBlock().Number.Uint64() ++ cfgChangeL1BlockNum := miner.L1Chain().CurrentBlock().Number.Uint64() + require.Equal(t, cfgChangeL1BlockNum, receipt.BlockNumber.Uint64()) +  + // sequence L2 blocks, and submit with new batcher +@@ -225,9 +227,9 @@ + // GPOParamsChange tests that the GPO params can be updated to adjust fees of L2 transactions, + // and that the L1 data fees to the L2 transaction are applied correctly before, during and after the GPO update in L2. + func GPOParamsChange(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { +- t := NewDefaultTesting(gt) +- dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) +- applyDeltaTimeOffset(dp, deltaTimeOffset) ++ t := actionsHelpers.NewDefaultTesting(gt) ++ dp := e2eutils.MakeDeployParams(t, actionsHelpers.DefaultRollupTestParams) ++ upgradesHelpers.ApplyDeltaTimeOffset(dp, deltaTimeOffset) +  + // activating Delta only, not Ecotone and further: + // the GPO change assertions here all apply only for the Delta transition. +@@ -236,14 +238,14 @@ dp.DeployConfig.L2GenesisEcotoneTimeOffset = nil + dp.DeployConfig.L2GenesisFjordTimeOffset = nil + dp.DeployConfig.L2GenesisGraniteTimeOffset = nil +  +- sd := e2eutils.Setup(t, dp, defaultAlloc) ++ sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) + log := testlog.Logger(t, log.LevelDebug) +- miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) +- batcher := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp), ++ miner, seqEngine, sequencer := actionsHelpers.SetupSequencerTest(t, sd, log) ++ batcher := actionsHelpers.NewL2Batcher(log, sd.RollupCfg, actionsHelpers.DefaultBatcherCfg(dp), + sequencer.RollupClient(), miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) +  +- alice := NewBasicUser[any](log, dp.Secrets.Alice, rand.New(rand.NewSource(1234))) +- alice.SetUserEnv(&BasicUserEnv[any]{ ++ alice := actionsHelpers.NewBasicUser[any](log, dp.Secrets.Alice, rand.New(rand.NewSource(1234))) ++ alice.SetUserEnv(&actionsHelpers.BasicUserEnv[any]{ + EthCl: seqEngine.EthClient(), + Signer: types.LatestSigner(sd.L2Cfg.Config), + }) +@@ -254,7 +256,7 @@ // new L1 block, with new L2 chain + miner.ActEmptyBlock(t) + sequencer.ActL1HeadSignal(t) + sequencer.ActBuildToL1Head(t) +- basefee := miner.l1Chain.CurrentBlock().BaseFee ++ basefee := miner.L1Chain().CurrentBlock().BaseFee +  + // alice makes a L2 tx, sequencer includes it + alice.ActResetTxOpts(t) +@@ -299,7 +301,7 @@ // include the GPO change tx in L1 + miner.ActL1StartBlock(12)(t) + miner.ActL1IncludeTx(dp.Addresses.SysCfgOwner)(t) + miner.ActL1EndBlock(t) +- basefeeGPOUpdate := miner.l1Chain.CurrentBlock().BaseFee ++ basefeeGPOUpdate := miner.L1Chain().CurrentBlock().BaseFee +  + // build empty L2 chain, up to but excluding the L2 block with the L1 origin that processes the GPO change + sequencer.ActL1HeadSignal(t) +@@ -336,7 +338,7 @@ require.Equal(t, "2.3", receipt.FeeScalar.String(), "2_300_000 divided by 6 decimals = float(2.3)") +  + // build more L2 blocks, with new L1 origin + miner.ActEmptyBlock(t) +- basefee = miner.l1Chain.CurrentBlock().BaseFee ++ basefee = miner.L1Chain().CurrentBlock().BaseFee + sequencer.ActL1HeadSignal(t) + sequencer.ActBuildToL1Head(t) + // and Alice makes a tx again +@@ -360,13 +362,13 @@ // GasLimitChange tests that the gas limit can be configured to L1, + // and that the L2 changes the gas limit instantly at the exact block that adopts the L1 origin with + // the gas limit change event. And checks if a verifier node can reproduce the same gas limit change. + func GasLimitChange(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { +- t := NewDefaultTesting(gt) +- dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) +- applyDeltaTimeOffset(dp, deltaTimeOffset) +- sd := e2eutils.Setup(t, dp, defaultAlloc) ++ t := actionsHelpers.NewDefaultTesting(gt) ++ dp := e2eutils.MakeDeployParams(t, actionsHelpers.DefaultRollupTestParams) ++ upgradesHelpers.ApplyDeltaTimeOffset(dp, deltaTimeOffset) ++ sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) + log := testlog.Logger(t, log.LevelDebug) +- miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) +- batcher := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp), ++ miner, seqEngine, sequencer := actionsHelpers.SetupSequencerTest(t, sd, log) ++ batcher := actionsHelpers.NewL2Batcher(log, sd.RollupCfg, actionsHelpers.DefaultBatcherCfg(dp), + sequencer.RollupClient(), miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) +  + sequencer.ActL2PipelineFull(t) +@@ -374,7 +376,7 @@ miner.ActEmptyBlock(t) + sequencer.ActL1HeadSignal(t) + sequencer.ActBuildToL1Head(t) +  +- oldGasLimit := seqEngine.l2Chain.CurrentBlock().GasLimit ++ oldGasLimit := seqEngine.L2Chain().CurrentBlock().GasLimit + require.Equal(t, oldGasLimit, uint64(dp.DeployConfig.L2GenesisBlockGasLimit)) +  + // change gas limit on L1 to triple what it was +@@ -396,12 +398,12 @@ // build to latest L1, excluding the block that adopts the L1 block with the gaslimit change + sequencer.ActL1HeadSignal(t) + sequencer.ActBuildToL1HeadExcl(t) +  +- require.Equal(t, oldGasLimit, seqEngine.l2Chain.CurrentBlock().GasLimit) ++ require.Equal(t, oldGasLimit, seqEngine.L2Chain().CurrentBlock().GasLimit) + require.Equal(t, uint64(1), sequencer.SyncStatus().UnsafeL2.L1Origin.Number) +  + // now include the L1 block with the gaslimit change, and see if it changes as expected + sequencer.ActBuildToL1Head(t) +- require.Equal(t, oldGasLimit*3, seqEngine.l2Chain.CurrentBlock().GasLimit) ++ require.Equal(t, oldGasLimit*3, seqEngine.L2Chain().CurrentBlock().GasLimit) + require.Equal(t, uint64(2), sequencer.SyncStatus().UnsafeL2.L1Origin.Number) +  + // now submit all this to L1, and see if a verifier can sync and reproduce it +@@ -410,7 +412,7 @@ miner.ActL1StartBlock(12)(t) + miner.ActL1IncludeTx(dp.Addresses.Batcher)(t) + miner.ActL1EndBlock(t) +  +- _, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) ++ _, verifier := actionsHelpers.SetupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) + verifier.ActL2PipelineFull(t) +  + require.Equal(t, sequencer.L2Unsafe(), verifier.L2Safe(), "verifier stays in sync, even with gaslimit changes")
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+1
+
-1
+ +
+ +
+
+
diff --git OP/op-e2e/actions/action.go CELO/op-e2e/actions/helpers/action.go +rename from op-e2e/actions/action.go +rename to op-e2e/actions/helpers/action.go +index 551ab58d96322d6daa7fbb57afc9dba4aedccc8d..3f8bba669242d160fa27b67bd72892deceed6c34 100644 +--- OP/op-e2e/actions/action.go ++++ CELO/op-e2e/actions/helpers/action.go +@@ -1,4 +1,4 @@ +-package actions ++package helpers +  + import ( + "context"
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+24
+
-5
+ +
+ +
+
+
diff --git OP/op-e2e/actions/garbage_channel_out.go CELO/op-e2e/actions/helpers/garbage_channel_out.go +rename from op-e2e/actions/garbage_channel_out.go +rename to op-e2e/actions/helpers/garbage_channel_out.go +index a24cca7c2c03f34c943110f31e837b607c31fef3..6d813520a10a9c83cb47aeb3d4d575fb63b3cce9 100644 +--- OP/op-e2e/actions/garbage_channel_out.go ++++ CELO/op-e2e/actions/helpers/garbage_channel_out.go +@@ -1,4 +1,4 @@ +-package actions ++package helpers +  + import ( + "bytes" +@@ -36,10 +36,29 @@ INVALID_COMPRESSION, + MALFORM_RLP, + } +  ++func (gk GarbageKind) String() string { ++ switch gk { ++ case STRIP_VERSION: ++ return "STRIP_VERSION" ++ case RANDOM: ++ return "RANDOM" ++ case TRUNCATE_END: ++ return "TRUNCATE_END" ++ case DIRTY_APPEND: ++ return "DIRTY_APPEND" ++ case INVALID_COMPRESSION: ++ return "INVALID_COMPRESSION" ++ case MALFORM_RLP: ++ return "MALFORM_RLP" ++ default: ++ return "UNKNOWN" ++ } ++} ++ + // GarbageChannelCfg is the configuration for a `GarbageChannelOut` + type GarbageChannelCfg struct { +- useInvalidCompression bool +- malformRLP bool ++ UseInvalidCompression bool ++ MalformRLP bool + } +  + // Writer is the interface shared between `zlib.Writer` and `gzip.Writer` +@@ -109,7 +128,7 @@ } +  + // Optionally use zlib or gzip compression + var compress Writer +- if cfg.useInvalidCompression { ++ if cfg.UseInvalidCompression { + compress, err = gzip.NewWriterLevel(&c.buf, gzip.BestCompression) + } else { + compress, err = zlib.NewWriterLevel(&c.buf, zlib.BestCompression) +@@ -152,7 +171,7 @@ var buf bytes.Buffer + if err := rlp.Encode(&buf, batch); err != nil { + return err + } +- if co.cfg.malformRLP { ++ if co.cfg.MalformRLP { + // Malform the RLP by incrementing the length prefix by 1. + bufBytes := buf.Bytes() + bufBytes[0] += 1
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+23
+
-18
+ +
+ +
+
+
diff --git OP/op-e2e/actions/l1_miner.go CELO/op-e2e/actions/helpers/l1_miner.go +rename from op-e2e/actions/l1_miner.go +rename to op-e2e/actions/helpers/l1_miner.go +index 9026d74db17807bf57052a4f3275264307bf02dd..5fe5c762d5c9f098874a6aeedc17417b6627e7b6 100644 +--- OP/op-e2e/actions/l1_miner.go ++++ CELO/op-e2e/actions/helpers/l1_miner.go +@@ -1,8 +1,9 @@ +-package actions ++package helpers +  + import ( + "math/big" +  ++ "github.com/ethereum-optimism/optimism/op-program/host/prefetcher" + "github.com/stretchr/testify/require" +  + "github.com/ethereum/go-ethereum/common" +@@ -17,7 +18,6 @@ "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/trie" +  + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" +- "github.com/ethereum-optimism/optimism/op-node/rollup/derive" + "github.com/ethereum-optimism/optimism/op-service/eth" + ) +  +@@ -33,9 +33,9 @@ + // L1 block building data + l1BuildingHeader *types.Header // block header that we add txs to for block building + l1BuildingState *state.StateDB // state used for block building +- l1GasPool *core.GasPool // track gas used of ongoing building ++ L1GasPool *core.GasPool // track gas used of ongoing building + pendingIndices map[common.Address]uint64 // per account, how many txs from the pool were already included in the block, since the pool is lagging behind block mining. +- l1Transactions []*types.Transaction // collects txs that were successfully included into current block build ++ L1Transactions []*types.Transaction // collects txs that were successfully included into current block build + l1Receipts []*types.Receipt // collect receipts of ongoing building + l1Building bool + l1TxFailed []*types.Transaction // log of failed transactions which could not be included +@@ -52,7 +52,11 @@ blobStore: e2eutils.NewBlobStore(), + } + } +  +-func (s *L1Miner) BlobStore() derive.L1BlobsFetcher { ++func (s *L1Miner) BlobSource() prefetcher.L1BlobSource { ++ return s.blobStore ++} ++ ++func (s *L1Miner) BlobStore() *e2eutils.BlobsStore { + return s.blobStore + } +  +@@ -120,11 +124,11 @@ s.l1Building = true + s.l1BuildingHeader = header + s.l1BuildingState = statedb + s.l1Receipts = make([]*types.Receipt, 0) +- s.l1Transactions = make([]*types.Transaction, 0) ++ s.L1Transactions = make([]*types.Transaction, 0) + s.pendingIndices = make(map[common.Address]uint64) + s.l1BuildingBlobSidecars = make([]*types.BlobTxSidecar, 0) +  +- s.l1GasPool = new(core.GasPool).AddGas(header.GasLimit) ++ s.L1GasPool = new(core.GasPool).AddGas(header.GasLimit) + } + } +  +@@ -138,7 +142,7 @@ } + getPendingIndex := func(from common.Address) uint64 { + return s.pendingIndices[from] + } +- tx := firstValidTx(t, from, getPendingIndex, s.eth.TxPool().ContentFrom, s.EthClient().NonceAt) ++ tx := firstValidTx(t, from, getPendingIndex, s.Eth.TxPool().ContentFrom, s.EthClient().NonceAt) + s.IncludeTx(t, tx) + s.pendingIndices[from] = s.pendingIndices[from] + 1 // won't retry the tx + } +@@ -151,7 +155,7 @@ if !s.l1Building { + t.InvalidAction("no tx inclusion when not building l1 block") + return + } +- tx := s.eth.TxPool().Get(txHash) ++ tx := s.Eth.TxPool().Get(txHash) + require.NotNil(t, tx, "cannot find tx %s", txHash) + s.IncludeTx(t, tx) + from, err := s.l1Signer.Sender(tx) +@@ -167,19 +171,19 @@ s.log.Info("including tx", "nonce", tx.Nonce(), "from", from, "to", tx.To()) + if tx.Gas() > s.l1BuildingHeader.GasLimit { + t.Fatalf("tx consumes %d gas, more than available in L1 block %d", tx.Gas(), s.l1BuildingHeader.GasLimit) + } +- if tx.Gas() > uint64(*s.l1GasPool) { +- t.InvalidAction("action takes too much gas: %d, only have %d", tx.Gas(), uint64(*s.l1GasPool)) ++ if tx.Gas() > uint64(*s.L1GasPool) { ++ t.InvalidAction("action takes too much gas: %d, only have %d", tx.Gas(), uint64(*s.L1GasPool)) + return + } +- s.l1BuildingState.SetTxContext(tx.Hash(), len(s.l1Transactions)) ++ s.l1BuildingState.SetTxContext(tx.Hash(), len(s.L1Transactions)) + receipt, err := core.ApplyTransaction(s.l1Cfg.Config, s.l1Chain, &s.l1BuildingHeader.Coinbase, +- s.l1GasPool, s.l1BuildingState, s.l1BuildingHeader, tx.WithoutBlobTxSidecar(), &s.l1BuildingHeader.GasUsed, *s.l1Chain.GetVMConfig()) ++ s.L1GasPool, s.l1BuildingState, s.l1BuildingHeader, tx.WithoutBlobTxSidecar(), &s.l1BuildingHeader.GasUsed, *s.l1Chain.GetVMConfig()) + if err != nil { + s.l1TxFailed = append(s.l1TxFailed, tx) +- t.Fatalf("failed to apply transaction to L1 block (tx %d): %v", len(s.l1Transactions), err) ++ t.Fatalf("failed to apply transaction to L1 block (tx %d): %v", len(s.L1Transactions), err) + } + s.l1Receipts = append(s.l1Receipts, receipt) +- s.l1Transactions = append(s.l1Transactions, tx.WithoutBlobTxSidecar()) ++ s.L1Transactions = append(s.L1Transactions, tx.WithoutBlobTxSidecar()) + if tx.Type() == types.BlobTxType { + require.True(t, s.l1Cfg.Config.IsCancun(s.l1BuildingHeader.Number, s.l1BuildingHeader.Time), "L1 must be cancun to process blob tx") + sidecar := tx.BlobTxSidecar() +@@ -205,7 +209,7 @@ return + } +  + s.l1Building = false +- s.l1BuildingHeader.GasUsed = s.l1BuildingHeader.GasLimit - uint64(*s.l1GasPool) ++ s.l1BuildingHeader.GasUsed = s.l1BuildingHeader.GasLimit - uint64(*s.L1GasPool) + s.l1BuildingHeader.Root = s.l1BuildingState.IntermediateRoot(s.l1Cfg.Config.IsEIP158(s.l1BuildingHeader.Number)) +  + var withdrawals []*types.Withdrawal +@@ -213,7 +217,7 @@ if s.l1Cfg.Config.IsShanghai(s.l1BuildingHeader.Number, s.l1BuildingHeader.Time) { + withdrawals = make([]*types.Withdrawal, 0) + } +  +- block := types.NewBlock(s.l1BuildingHeader, &types.Body{Transactions: s.l1Transactions, Withdrawals: withdrawals}, s.l1Receipts, trie.NewStackTrie(nil)) ++ block := types.NewBlock(s.l1BuildingHeader, &types.Body{Transactions: s.L1Transactions, Withdrawals: withdrawals}, s.l1Receipts, trie.NewStackTrie(nil)) + if s.l1Cfg.Config.IsCancun(s.l1BuildingHeader.Number, s.l1BuildingHeader.Time) { + parent := s.l1Chain.GetHeaderByHash(s.l1BuildingHeader.ParentHash) + var ( +@@ -240,7 +244,8 @@ // now that the blob txs are in a canonical block, flush them to the blob store + for _, sidecar := range s.l1BuildingBlobSidecars { + for i, h := range sidecar.BlobHashes() { + blob := (*eth.Blob)(&sidecar.Blobs[i]) +- s.blobStore.StoreBlob(block.Hash(), h, blob) ++ indexedHash := eth.IndexedBlobHash{Index: uint64(i), Hash: h} ++ s.blobStore.StoreBlob(block.Time(), indexedHash, blob) + } + } + _, err = s.l1Chain.InsertChain(types.Blocks{block})
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+3
+
-3
+ +
+ +
+
+
diff --git OP/op-e2e/actions/l1_miner_test.go CELO/op-e2e/actions/helpers/l1_miner_test.go +rename from op-e2e/actions/l1_miner_test.go +rename to op-e2e/actions/helpers/l1_miner_test.go +index 10e4c0c5498cda0788f1e7030ac05cba91a637fb..b102dcaf84f0e0bf3a6bd9ad252d62d5ce92cb00 100644 +--- OP/op-e2e/actions/l1_miner_test.go ++++ CELO/op-e2e/actions/helpers/l1_miner_test.go +@@ -1,4 +1,4 @@ +-package actions ++package helpers +  + import ( + "math/big" +@@ -15,8 +15,8 @@ ) +  + func TestL1Miner_BuildBlock(gt *testing.T) { + t := NewDefaultTesting(gt) +- dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) +- sd := e2eutils.Setup(t, dp, defaultAlloc) ++ dp := e2eutils.MakeDeployParams(t, DefaultRollupTestParams) ++ sd := e2eutils.Setup(t, dp, DefaultAlloc) + log := testlog.Logger(t, log.LevelDebug) + miner := NewL1Miner(t, log, sd.L1Cfg) + t.Cleanup(func() {
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+13
+
-3
+ +
+ +
+
+
diff --git OP/op-e2e/actions/l1_replica.go CELO/op-e2e/actions/helpers/l1_replica.go +rename from op-e2e/actions/l1_replica.go +rename to op-e2e/actions/helpers/l1_replica.go +index fb042757065e2138096294045aa9fd594fae085d..7b089a4f7fa98fa88f71e4895898fb41fda083d8 100644 +--- OP/op-e2e/actions/l1_replica.go ++++ CELO/op-e2e/actions/helpers/l1_replica.go +@@ -1,4 +1,4 @@ +-package actions ++package helpers +  + import ( + "errors" +@@ -38,7 +38,7 @@ type L1Replica struct { + log log.Logger +  + node *node.Node +- eth *eth.Ethereum ++ Eth *eth.Ethereum +  + // L1 evm / chain + l1Chain *core.BlockChain +@@ -67,6 +67,8 @@ nodeCfg := &node.Config{ + Name: "l1-geth", + WSHost: "127.0.0.1", + WSPort: 0, ++ HTTPHost: "127.0.0.1", ++ HTTPPort: 0, + WSModules: []string{"debug", "admin", "eth", "txpool", "net", "rpc", "web3", "personal"}, + HTTPModules: []string{"debug", "admin", "eth", "txpool", "net", "rpc", "web3", "personal"}, + DataDir: "", // in-memory +@@ -90,7 +92,7 @@ require.NoError(t, n.Start(), "failed to start L1 geth node") + return &L1Replica{ + log: log, + node: n, +- eth: backend, ++ Eth: backend, + l1Chain: backend.BlockChain(), + l1Database: backend.ChainDb(), + l1Cfg: genesis, +@@ -168,6 +170,10 @@ return fn() + } + } +  ++func (s *L1Replica) HTTPEndpoint() string { ++ return s.node.HTTPEndpoint() ++} ++ + func (s *L1Replica) EthClient() *ethclient.Client { + cl := s.node.Attach() + return ethclient.NewClient(cl) +@@ -190,6 +196,10 @@ func (s *L1Replica) L1Client(t Testing, cfg *rollup.Config) *sources.L1Client { + l1F, err := sources.NewL1Client(s.RPCClient(), s.log, nil, sources.L1ClientDefaultConfig(cfg, false, sources.RPCKindStandard)) + require.NoError(t, err) + return l1F ++} ++ ++func (s *L1Replica) L1Chain() *core.BlockChain { ++ return s.l1Chain + } +  + func (s *L1Replica) UnsafeNum() uint64 {
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+5
+
-14
+ +
+ +
+
+
diff --git OP/op-e2e/actions/l1_replica_test.go CELO/op-e2e/actions/helpers/l1_replica_test.go +rename from op-e2e/actions/l1_replica_test.go +rename to op-e2e/actions/helpers/l1_replica_test.go +index ab918a619644e2895d9d7fce406c360b95e8c60e..5bfe2212f59e84532823482ec795586f4db7b2bd 100644 +--- OP/op-e2e/actions/l1_replica_test.go ++++ CELO/op-e2e/actions/helpers/l1_replica_test.go +@@ -1,4 +1,4 @@ +-package actions ++package helpers +  + import ( + "encoding/binary" +@@ -21,20 +21,11 @@ "github.com/ethereum-optimism/optimism/op-service/sources" + "github.com/ethereum-optimism/optimism/op-service/testlog" + ) +  +-var defaultRollupTestParams = &e2eutils.TestParams{ +- MaxSequencerDrift: 40, +- SequencerWindowSize: 120, +- ChannelTimeout: 120, +- L1BlockTime: 15, +-} +- +-var defaultAlloc = &e2eutils.AllocParams{PrefundTestUsers: true} +- + // Test if we can mock an RPC failure + func TestL1Replica_ActL1RPCFail(gt *testing.T) { + t := NewDefaultTesting(gt) +- dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) +- sd := e2eutils.Setup(t, dp, defaultAlloc) ++ dp := e2eutils.MakeDeployParams(t, DefaultRollupTestParams) ++ sd := e2eutils.Setup(t, dp, DefaultAlloc) + log := testlog.Logger(t, log.LevelDebug) + replica := NewL1Replica(t, log, sd.L1Cfg) + t.Cleanup(func() { +@@ -55,9 +46,9 @@ + // Test if we can make the replica sync an artificial L1 chain, rewind it, and reorg it + func TestL1Replica_ActL1Sync(gt *testing.T) { + t := NewDefaultTesting(gt) +- dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) ++ dp := e2eutils.MakeDeployParams(t, DefaultRollupTestParams) + dp.DeployConfig.L1CancunTimeOffset = nil +- sd := e2eutils.Setup(t, dp, defaultAlloc) ++ sd := e2eutils.Setup(t, dp, DefaultAlloc) + log := testlog.Logger(t, log.LevelDebug) + genesisBlock := sd.L1Cfg.ToBlock() + consensus := beacon.New(ethash.NewFaker())
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+72
+
-85
+ +
+ +
+
+
diff --git OP/op-e2e/actions/l2_batcher.go CELO/op-e2e/actions/helpers/l2_batcher.go +rename from op-e2e/actions/l2_batcher.go +rename to op-e2e/actions/helpers/l2_batcher.go +index 42fe7c8b2bcdbf2fe72fad0f49d36cfc77aafc8e..e9dfe4887f1096c5b6e5c07f45b245755dbe59c7 100644 +--- OP/op-e2e/actions/l2_batcher.go ++++ CELO/op-e2e/actions/helpers/l2_batcher.go +@@ -1,4 +1,4 @@ +-package actions ++package helpers +  + import ( + "bytes" +@@ -106,12 +106,12 @@ engCl L2BlockRefs +  + l1Signer types.Signer +  +- l2ChannelOut ChannelOutIface ++ L2ChannelOut ChannelOutIface + l2Submitting bool // when the channel out is being submitted, and not safe to write to without resetting +- l2BufferedBlock eth.L2BlockRef ++ L2BufferedBlock eth.L2BlockRef + l2SubmittedBlock eth.L2BlockRef + l2BatcherCfg *BatcherCfg +- batcherAddr common.Address ++ BatcherAddr common.Address +  + LastSubmitted *types.Transaction + } +@@ -126,7 +126,7 @@ l2: l2, + engCl: engCl, + l2BatcherCfg: batcherCfg, + l1Signer: types.LatestSignerForChainID(rollupCfg.L1ChainID), +- batcherAddr: crypto.PubkeyToAddress(batcherCfg.BatcherKey.PublicKey), ++ BatcherAddr: crypto.PubkeyToAddress(batcherCfg.BatcherKey.PublicKey), + } + } +  +@@ -136,15 +136,25 @@ func (s *L2Batcher) SubmittingData() bool { + return s.l2Submitting + } +  ++// Reset the batcher state, clearing any buffered data. ++func (s *L2Batcher) Reset() { ++ s.L2ChannelOut = nil ++ s.l2Submitting = false ++ s.L2BufferedBlock = eth.L2BlockRef{} ++ s.l2SubmittedBlock = eth.L2BlockRef{} ++} ++ + // ActL2BatchBuffer adds the next L2 block to the batch buffer. + // If the buffer is being submitted, the buffer is wiped. + func (s *L2Batcher) ActL2BatchBuffer(t Testing) { + require.NoError(t, s.Buffer(t), "failed to add block to channel") + } +  +-func (s *L2Batcher) Buffer(t Testing) error { ++type BlockModifier = func(block *types.Block) ++ ++func (s *L2Batcher) Buffer(t Testing, opts ...BlockModifier) error { + if s.l2Submitting { // break ongoing submitting work if necessary +- s.l2ChannelOut = nil ++ s.L2ChannelOut = nil + s.l2Submitting = false + } + syncStatus, err := s.syncStatusAPI.SyncStatus(t.Ctx()) +@@ -153,38 +163,45 @@ // If we just started, start at safe-head + if s.l2SubmittedBlock == (eth.L2BlockRef{}) { + s.log.Info("Starting batch-submitter work at safe-head", "safe", syncStatus.SafeL2) + s.l2SubmittedBlock = syncStatus.SafeL2 +- s.l2BufferedBlock = syncStatus.SafeL2 +- s.l2ChannelOut = nil ++ s.L2BufferedBlock = syncStatus.SafeL2 ++ s.L2ChannelOut = nil + } + // If it's lagging behind, catch it up. + if s.l2SubmittedBlock.Number < syncStatus.SafeL2.Number { + s.log.Warn("last submitted block lagged behind L2 safe head: batch submission will continue from the safe head now", "last", s.l2SubmittedBlock, "safe", syncStatus.SafeL2) + s.l2SubmittedBlock = syncStatus.SafeL2 +- s.l2BufferedBlock = syncStatus.SafeL2 +- s.l2ChannelOut = nil ++ s.L2BufferedBlock = syncStatus.SafeL2 ++ s.L2ChannelOut = nil + } + // Add the next unsafe block to the channel +- if s.l2BufferedBlock.Number >= syncStatus.UnsafeL2.Number { +- if s.l2BufferedBlock.Number > syncStatus.UnsafeL2.Number || s.l2BufferedBlock.Hash != syncStatus.UnsafeL2.Hash { ++ if s.L2BufferedBlock.Number >= syncStatus.UnsafeL2.Number { ++ if s.L2BufferedBlock.Number > syncStatus.UnsafeL2.Number || s.L2BufferedBlock.Hash != syncStatus.UnsafeL2.Hash { + s.log.Error("detected a reorg in L2 chain vs previous buffered information, resetting to safe head now", "safe_head", syncStatus.SafeL2) + s.l2SubmittedBlock = syncStatus.SafeL2 +- s.l2BufferedBlock = syncStatus.SafeL2 +- s.l2ChannelOut = nil ++ s.L2BufferedBlock = syncStatus.SafeL2 ++ s.L2ChannelOut = nil + } else { + s.log.Info("nothing left to submit") + return nil + } + } +- block, err := s.l2.BlockByNumber(t.Ctx(), big.NewInt(int64(s.l2BufferedBlock.Number+1))) ++ ++ block, err := s.l2.BlockByNumber(t.Ctx(), big.NewInt(int64(s.L2BufferedBlock.Number+1))) + require.NoError(t, err, "need l2 block %d from sync status", s.l2SubmittedBlock.Number+1) +- if block.ParentHash() != s.l2BufferedBlock.Hash { ++ if block.ParentHash() != s.L2BufferedBlock.Hash { + s.log.Error("detected a reorg in L2 chain vs previous submitted information, resetting to safe head now", "safe_head", syncStatus.SafeL2) + s.l2SubmittedBlock = syncStatus.SafeL2 +- s.l2BufferedBlock = syncStatus.SafeL2 +- s.l2ChannelOut = nil ++ s.L2BufferedBlock = syncStatus.SafeL2 ++ s.L2ChannelOut = nil + } ++ ++ // Apply modifications to the block ++ for _, f := range opts { ++ f(block) ++ } ++ + // Create channel if we don't have one yet +- if s.l2ChannelOut == nil { ++ if s.L2ChannelOut == nil { + var ch ChannelOutIface + if s.l2BatcherCfg.GarbageCfg != nil { + ch, err = NewGarbageChannelOut(s.l2BatcherCfg.GarbageCfg) +@@ -202,7 +219,7 @@ } else { + chainSpec := rollup.NewChainSpec(s.rollupCfg) + // use span batch if we're forcing it or if we're at/beyond delta + if s.l2BatcherCfg.ForceSubmitSpanBatch || s.rollupCfg.IsDelta(block.Time()) { +- ch, err = derive.NewSpanChannelOut(s.rollupCfg.Genesis.L2Time, s.rollupCfg.L2ChainID, target, derive.Zlib, chainSpec) ++ ch, err = derive.NewSpanChannelOut(target, derive.Zlib, chainSpec) + // use singular batches in all other cases + } else { + ch, err = derive.NewSingularChannelOut(c, chainSpec) +@@ -210,53 +227,60 @@ } + } + } + require.NoError(t, err, "failed to create channel") +- s.l2ChannelOut = ch ++ s.L2ChannelOut = ch + } +- if err := s.l2ChannelOut.AddBlock(s.rollupCfg, block); err != nil { ++ if err := s.L2ChannelOut.AddBlock(s.rollupCfg, block); err != nil { + return err + } + ref, err := s.engCl.L2BlockRefByHash(t.Ctx(), block.Hash()) + require.NoError(t, err, "failed to get L2BlockRef") +- s.l2BufferedBlock = ref ++ s.L2BufferedBlock = ref + return nil + } +  + func (s *L2Batcher) ActL2ChannelClose(t Testing) { + // Don't run this action if there's no data to submit +- if s.l2ChannelOut == nil { ++ if s.L2ChannelOut == nil { + t.InvalidAction("need to buffer data first, cannot batch submit with empty buffer") + return + } +- require.NoError(t, s.l2ChannelOut.Close(), "must close channel before submitting it") ++ require.NoError(t, s.L2ChannelOut.Close(), "must close channel before submitting it") + } +  +-// ActL2BatchSubmit constructs a batch tx from previous buffered L2 blocks, and submits it to L1 +-func (s *L2Batcher) ActL2BatchSubmit(t Testing, txOpts ...func(tx *types.DynamicFeeTx)) { ++func (s *L2Batcher) ReadNextOutputFrame(t Testing) []byte { + // Don't run this action if there's no data to submit +- if s.l2ChannelOut == nil { ++ if s.L2ChannelOut == nil { + t.InvalidAction("need to buffer data first, cannot batch submit with empty buffer") +- return ++ return nil + } + // Collect the output frame + data := new(bytes.Buffer) + data.WriteByte(derive.DerivationVersion0) + // subtract one, to account for the version byte +- if _, err := s.l2ChannelOut.OutputFrame(data, s.l2BatcherCfg.MaxL1TxSize-1); err == io.EOF { +- s.l2ChannelOut = nil ++ if _, err := s.L2ChannelOut.OutputFrame(data, s.l2BatcherCfg.MaxL1TxSize-1); err == io.EOF { ++ s.L2ChannelOut = nil + s.l2Submitting = false + } else if err != nil { + s.l2Submitting = false + t.Fatalf("failed to output channel data to frame: %v", err) + } +  +- payload := data.Bytes() ++ return data.Bytes() ++} ++ ++// ActL2BatchSubmit constructs a batch tx from previous buffered L2 blocks, and submits it to L1 ++func (s *L2Batcher) ActL2BatchSubmit(t Testing, txOpts ...func(tx *types.DynamicFeeTx)) { ++ s.ActL2BatchSubmitRaw(t, s.ReadNextOutputFrame(t), txOpts...) ++} ++ ++func (s *L2Batcher) ActL2BatchSubmitRaw(t Testing, payload []byte, txOpts ...func(tx *types.DynamicFeeTx)) { + if s.l2BatcherCfg.UseAltDA { + comm, err := s.l2BatcherCfg.AltDA.SetInput(t.Ctx(), payload) + require.NoError(t, err, "failed to set input for altda") + payload = comm.TxData() + } +  +- nonce, err := s.l1.PendingNonceAt(t.Ctx(), s.batcherAddr) ++ nonce, err := s.l1.PendingNonceAt(t.Ctx(), s.BatcherAddr) + require.NoError(t, err, "need batcher nonce") +  + gasTipCap := big.NewInt(2 * params.GWei) +@@ -278,7 +302,7 @@ for _, opt := range txOpts { + opt(rawTx) + } +  +- gas, err := core.IntrinsicGas(rawTx.Data, nil, false, true, true, false) ++ gas, err := core.IntrinsicGas(rawTx.Data, nil, false, true, true, false, nil, nil) + require.NoError(t, err, "need to compute intrinsic gas") + rawTx.Gas = gas + txData = rawTx +@@ -327,7 +351,7 @@ t.InvalidAction("invalid number of blobs %d, must be within [1,6]", numBlobs) + } +  + // Don't run this action if there's no data to submit +- if s.l2ChannelOut == nil { ++ if s.L2ChannelOut == nil { + t.InvalidAction("need to buffer data first, cannot batch submit with empty buffer") + return + } +@@ -344,12 +368,12 @@ // write remaining channel to last frame + // subtract one, to account for the version byte + l = s.l2BatcherCfg.MaxL1TxSize - 1 + } +- if _, err := s.l2ChannelOut.OutputFrame(data, l); err == io.EOF { ++ if _, err := s.L2ChannelOut.OutputFrame(data, l); err == io.EOF { + s.l2Submitting = false + if i < numBlobs-1 { + t.Fatalf("failed to fill up %d blobs, only filled %d", numBlobs, i+1) + } +- s.l2ChannelOut = nil ++ s.L2ChannelOut = nil + } else if err != nil { + s.l2Submitting = false + t.Fatalf("failed to output channel data to frame: %v", err) +@@ -359,7 +383,7 @@ blobs[i] = new(eth.Blob) + require.NoError(t, blobs[i].FromData(data.Bytes()), "must turn data into blob") + } +  +- nonce, err := s.l1.PendingNonceAt(t.Ctx(), s.batcherAddr) ++ nonce, err := s.l1.PendingNonceAt(t.Ctx(), s.BatcherAddr) + require.NoError(t, err, "need batcher nonce") +  + gasTipCap := big.NewInt(2 * params.GWei) +@@ -401,27 +425,14 @@ // ActL2BatchSubmitGarbage constructs a malformed channel frame and submits it to the + // batch inbox. This *should* cause the batch inbox to reject the blocks + // encoded within the frame, even if the blocks themselves are valid. + func (s *L2Batcher) ActL2BatchSubmitGarbage(t Testing, kind GarbageKind) { +- // Don't run this action if there's no data to submit +- if s.l2ChannelOut == nil { +- t.InvalidAction("need to buffer data first, cannot batch submit with empty buffer") +- return +- } +- +- // Collect the output frame +- data := new(bytes.Buffer) +- data.WriteByte(derive.DerivationVersion0) +- +- // subtract one, to account for the version byte +- if _, err := s.l2ChannelOut.OutputFrame(data, s.l2BatcherCfg.MaxL1TxSize-1); err == io.EOF { +- s.l2ChannelOut = nil +- s.l2Submitting = false +- } else if err != nil { +- s.l2Submitting = false +- t.Fatalf("failed to output channel data to frame: %v", err) +- } ++ outputFrame := s.ReadNextOutputFrame(t) ++ s.ActL2BatchSubmitGarbageRaw(t, outputFrame, kind) ++} +  +- outputFrame := data.Bytes() +- ++// ActL2BatchSubmitGarbageRaw constructs a malformed channel frame from `outputFrame` and submits it to the ++// batch inbox. This *should* cause the batch inbox to reject the blocks ++// encoded within the frame, even if the blocks themselves are valid. ++func (s *L2Batcher) ActL2BatchSubmitGarbageRaw(t Testing, outputFrame []byte, kind GarbageKind) { + // Malform the output frame + switch kind { + // Strip the derivation version byte from the output frame +@@ -453,37 +464,13 @@ default: + t.Fatalf("Unexpected garbage kind: %v", kind) + } +  +- nonce, err := s.l1.PendingNonceAt(t.Ctx(), s.batcherAddr) +- require.NoError(t, err, "need batcher nonce") +- +- gasTipCap := big.NewInt(2 * params.GWei) +- pendingHeader, err := s.l1.HeaderByNumber(t.Ctx(), big.NewInt(-1)) +- require.NoError(t, err, "need l1 pending header for gas price estimation") +- gasFeeCap := new(big.Int).Add(gasTipCap, new(big.Int).Mul(pendingHeader.BaseFee, big.NewInt(2))) +- +- rawTx := &types.DynamicFeeTx{ +- ChainID: s.rollupCfg.L1ChainID, +- Nonce: nonce, +- To: &s.rollupCfg.BatchInboxAddress, +- GasTipCap: gasTipCap, +- GasFeeCap: gasFeeCap, +- Data: outputFrame, +- } +- gas, err := core.IntrinsicGas(rawTx.Data, nil, false, true, true, false) +- require.NoError(t, err, "need to compute intrinsic gas") +- rawTx.Gas = gas +- +- tx, err := types.SignNewTx(s.l2BatcherCfg.BatcherKey, s.l1Signer, rawTx) +- require.NoError(t, err, "need to sign tx") +- +- err = s.l1.SendTransaction(t.Ctx(), tx) +- require.NoError(t, err, "need to send tx") ++ s.ActL2BatchSubmitRaw(t, outputFrame) + } +  + func (s *L2Batcher) ActBufferAll(t Testing) { + stat, err := s.syncStatusAPI.SyncStatus(t.Ctx()) + require.NoError(t, err) +- for s.l2BufferedBlock.Number < stat.UnsafeL2.Number { ++ for s.L2BufferedBlock.Number < stat.UnsafeL2.Number { + s.ActL2BatchBuffer(t) + } + }
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+25
+
-15
+ +
+ +
+
+
diff --git OP/op-e2e/actions/l2_engine.go CELO/op-e2e/actions/helpers/l2_engine.go +rename from op-e2e/actions/l2_engine.go +rename to op-e2e/actions/helpers/l2_engine.go +index 54267ee9da58990d6cc7d50619c129ad5ebfdefc..5839a20798d31a361fdaa7e09fa1620ffc3be000 100644 +--- OP/op-e2e/actions/l2_engine.go ++++ CELO/op-e2e/actions/helpers/l2_engine.go +@@ -1,4 +1,4 @@ +-package actions ++package helpers +  + import ( + "errors" +@@ -35,7 +35,7 @@ type L2Engine struct { + log log.Logger +  + node *node.Node +- eth *geth.Ethereum ++ Eth *geth.Ethereum +  + rollupGenesis *rollup.Genesis +  +@@ -43,9 +43,9 @@ // L2 evm / chain + l2Chain *core.BlockChain + l2Signer types.Signer +  +- engineApi *engineapi.L2EngineAPI ++ EngineApi *engineapi.L2EngineAPI +  +- failL2RPC func(call []rpc.BatchElem) error // mock error ++ FailL2RPC func(call []rpc.BatchElem) error // mock error + } +  + type EngineOption func(ethCfg *ethconfig.Config, nodeCfg *node.Config) error +@@ -58,7 +58,7 @@ genesisBlock := chain.Genesis() + eng := &L2Engine{ + log: log, + node: n, +- eth: ethBackend, ++ Eth: ethBackend, + rollupGenesis: &rollup.Genesis{ + L1: rollupGenesisL1, + L2: eth.BlockID{Hash: genesisBlock.Hash(), Number: genesisBlock.NumberU64()}, +@@ -66,14 +66,14 @@ L2Time: genesis.Timestamp, + }, + l2Chain: chain, + l2Signer: types.LatestSigner(genesis.Config), +- engineApi: engineApi, ++ EngineApi: engineApi, + } + // register the custom engine API, so we can serve engine requests while having more control + // over sequencing of individual txs. + n.RegisterAPIs([]rpc.API{ + { + Namespace: "engine", +- Service: eng.engineApi, ++ Service: eng.EngineApi, + Authenticated: true, + }, + }) +@@ -93,6 +93,8 @@ nodeCfg := &node.Config{ + Name: "l2-geth", + WSHost: "127.0.0.1", + WSPort: 0, ++ HTTPHost: "127.0.0.1", ++ HTTPPort: 0, + AuthAddr: "127.0.0.1", + AuthPort: 0, + WSModules: []string{"debug", "admin", "eth", "txpool", "net", "rpc", "web3", "personal"}, +@@ -133,6 +135,10 @@ } +  + func (e *engineApiBackend) Genesis() *core.Genesis { + return e.genesis ++} ++ ++func (s *L2Engine) L2Chain() *core.BlockChain { ++ return s.l2Chain + } +  + func (s *L2Engine) Enode() *enode.Node { +@@ -149,6 +155,10 @@ func (s *L2Engine) PeerCount() int { + return s.node.Server().PeerCount() + } +  ++func (s *L2Engine) HTTPEndpoint() string { ++ return s.node.HTTPEndpoint() ++} ++ + func (s *L2Engine) EthClient() *ethclient.Client { + cl := s.node.Attach() + return ethclient.NewClient(cl) +@@ -164,10 +174,10 @@ cl := e.node.Attach() + return testutils.RPCErrFaker{ + RPC: client.NewBaseRPCClient(cl), + ErrFn: func(call []rpc.BatchElem) error { +- if e.failL2RPC == nil { ++ if e.FailL2RPC == nil { + return nil + } +- return e.failL2RPC(call) ++ return e.FailL2RPC(call) + }, + } + } +@@ -180,12 +190,12 @@ } +  + // ActL2RPCFail makes the next L2 RPC request fail with given error + func (e *L2Engine) ActL2RPCFail(t Testing, err error) { +- if e.failL2RPC != nil { // already set to fail? ++ if e.FailL2RPC != nil { // already set to fail? + t.InvalidAction("already set a mock L2 rpc error") + return + } +- e.failL2RPC = func(call []rpc.BatchElem) error { +- e.failL2RPC = nil ++ e.FailL2RPC = func(call []rpc.BatchElem) error { ++ e.FailL2RPC = nil + return err + } + } +@@ -193,13 +203,13 @@ + // ActL2IncludeTx includes the next transaction from the given address in the block that is being built + func (e *L2Engine) ActL2IncludeTx(from common.Address) Action { + return func(t Testing) { +- if e.engineApi.ForcedEmpty() { ++ if e.EngineApi.ForcedEmpty() { + e.log.Info("Skipping including a transaction because e.L2ForceEmpty is true") + return + } +  +- tx := firstValidTx(t, from, e.engineApi.PendingIndices, e.eth.TxPool().ContentFrom, e.EthClient().NonceAt) +- err := e.engineApi.IncludeTx(tx, from) ++ tx := firstValidTx(t, from, e.EngineApi.PendingIndices, e.Eth.TxPool().ContentFrom, e.EthClient().NonceAt) ++ err := e.EngineApi.IncludeTx(tx, from) + if errors.Is(err, engineapi.ErrNotBuildingBlock) { + t.InvalidAction(err.Error()) + } else if errors.Is(err, engineapi.ErrUsesTooMuchGas) {
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+9
+
-9
+ +
+ +
+
+
diff --git OP/op-e2e/actions/l2_engine_test.go CELO/op-e2e/actions/helpers/l2_engine_test.go +rename from op-e2e/actions/l2_engine_test.go +rename to op-e2e/actions/helpers/l2_engine_test.go +index 5d7a537b5d03bebf99a3b11e829bcbe44330d7bf..d74595d3162133e35a710853e85c4c07bf1f079c 100644 +--- OP/op-e2e/actions/l2_engine_test.go ++++ CELO/op-e2e/actions/helpers/l2_engine_test.go +@@ -1,4 +1,4 @@ +-package actions ++package helpers +  + import ( + "encoding/binary" +@@ -31,8 +31,8 @@ + func TestL2EngineAPI(gt *testing.T) { + t := NewDefaultTesting(gt) + jwtPath := e2eutils.WriteDefaultJWT(t) +- dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) +- sd := e2eutils.Setup(t, dp, defaultAlloc) ++ dp := e2eutils.MakeDeployParams(t, DefaultRollupTestParams) ++ sd := e2eutils.Setup(t, dp, DefaultAlloc) + log := testlog.Logger(t, log.LevelDebug) + genesisBlock := sd.L2Cfg.ToBlock() + consensus := beacon.New(ethash.NewFaker()) +@@ -107,8 +107,8 @@ + func TestL2EngineAPIBlockBuilding(gt *testing.T) { + t := NewDefaultTesting(gt) + jwtPath := e2eutils.WriteDefaultJWT(t) +- dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) +- sd := e2eutils.Setup(t, dp, defaultAlloc) ++ dp := e2eutils.MakeDeployParams(t, DefaultRollupTestParams) ++ sd := e2eutils.Setup(t, dp, DefaultAlloc) + log := testlog.Logger(t, log.LevelDebug) + genesisBlock := sd.L2Cfg.ToBlock() + db := rawdb.NewMemoryDatabase() +@@ -208,8 +208,8 @@ + func TestL2EngineAPIFail(gt *testing.T) { + t := NewDefaultTesting(gt) + jwtPath := e2eutils.WriteDefaultJWT(t) +- dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) +- sd := e2eutils.Setup(t, dp, defaultAlloc) ++ dp := e2eutils.MakeDeployParams(t, DefaultRollupTestParams) ++ sd := e2eutils.Setup(t, dp, DefaultAlloc) + log := testlog.Logger(t, log.LevelDebug) + engine := NewL2Engine(t, log, sd.L2Cfg, sd.RollupCfg.Genesis.L1, jwtPath) + // mock an RPC failure +@@ -228,8 +228,8 @@ + func TestEngineAPITests(t *testing.T) { + test.RunEngineAPITests(t, func(t *testing.T) engineapi.EngineBackend { + jwtPath := e2eutils.WriteDefaultJWT(t) +- dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) +- sd := e2eutils.Setup(t, dp, defaultAlloc) ++ dp := e2eutils.MakeDeployParams(t, DefaultRollupTestParams) ++ sd := e2eutils.Setup(t, dp, DefaultAlloc) + n, _, apiBackend := newBackend(t, sd.L2Cfg, jwtPath, nil) + err := n.Start() + require.NoError(t, err)
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+9
+
-1
+ +
+ +
+
+
diff --git OP/op-e2e/actions/l2_proposer.go CELO/op-e2e/actions/helpers/l2_proposer.go +rename from op-e2e/actions/l2_proposer.go +rename to op-e2e/actions/helpers/l2_proposer.go +index 9298548f0abf072fb56afa77ee264f1ec223cc45..f1a0c4d0d6344b7f77f1964c8e94870b11372c05 100644 +--- OP/op-e2e/actions/l2_proposer.go ++++ CELO/op-e2e/actions/helpers/l2_proposer.go +@@ -1,4 +1,4 @@ +-package actions ++package helpers +  + import ( + "context" +@@ -69,6 +69,10 @@ func (f fakeTxMgr) Send(_ context.Context, _ txmgr.TxCandidate) (*types.Receipt, error) { + panic("unimplemented") + } +  ++func (f fakeTxMgr) SendAsync(ctx context.Context, candidate txmgr.TxCandidate, ch chan txmgr.SendResponse) { ++ panic("unimplemented") ++} ++ + func (f fakeTxMgr) Close() { + } +  +@@ -77,6 +81,10 @@ return false + } +  + func (f fakeTxMgr) API() rpc.API { ++ panic("unimplemented") ++} ++ ++func (f fakeTxMgr) SuggestGasPriceCaps(context.Context) (*big.Int, *big.Int, *big.Int, error) { + panic("unimplemented") + } +
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+12
+
-10
+ +
+ +
+
+
diff --git OP/op-e2e/actions/l2_sequencer.go CELO/op-e2e/actions/helpers/l2_sequencer.go +rename from op-e2e/actions/l2_sequencer.go +rename to op-e2e/actions/helpers/l2_sequencer.go +index 7211537bc50ccea2d3783071c8e2bc7582b734b9..98becdcc87a4aa66c6889611e91d5f980d59fb0b 100644 +--- OP/op-e2e/actions/l2_sequencer.go ++++ CELO/op-e2e/actions/helpers/l2_sequencer.go +@@ -1,4 +1,4 @@ +-package actions ++package helpers +  + import ( + "context" +@@ -19,6 +19,7 @@ "github.com/ethereum-optimism/optimism/op-node/rollup/derive" + "github.com/ethereum-optimism/optimism/op-node/rollup/driver" + "github.com/ethereum-optimism/optimism/op-node/rollup/engine" + "github.com/ethereum-optimism/optimism/op-node/rollup/event" ++ "github.com/ethereum-optimism/optimism/op-node/rollup/interop" + "github.com/ethereum-optimism/optimism/op-node/rollup/sequencing" + "github.com/ethereum-optimism/optimism/op-node/rollup/sync" + "github.com/ethereum-optimism/optimism/op-service/eth" +@@ -50,8 +51,9 @@ mockL1OriginSelector *MockL1OriginSelector + } +  + func NewL2Sequencer(t Testing, log log.Logger, l1 derive.L1Fetcher, blobSrc derive.L1BlobsFetcher, +- altDASrc driver.AltDAIface, eng L2API, cfg *rollup.Config, seqConfDepth uint64) *L2Sequencer { +- ver := NewL2Verifier(t, log, l1, blobSrc, altDASrc, eng, cfg, &sync.Config{}, safedb.Disabled) ++ altDASrc driver.AltDAIface, eng L2API, cfg *rollup.Config, seqConfDepth uint64, ++ interopBackend interop.InteropBackend) *L2Sequencer { ++ ver := NewL2Verifier(t, log, l1, blobSrc, altDASrc, eng, cfg, &sync.Config{}, safedb.Disabled, interopBackend) + attrBuilder := derive.NewFetchingAttributesBuilder(cfg, l1, eng) + seqConfDepthL1 := confdepth.NewConfDepth(seqConfDepth, ver.syncStatus.L1Head, l1) + l1OriginSelector := &MockL1OriginSelector{ +@@ -87,7 +89,7 @@ } +  + // ActL2StartBlock starts building of a new L2 block on top of the head + func (s *L2Sequencer) ActL2StartBlock(t Testing) { +- if !s.l2PipelineIdle { ++ if !s.L2PipelineIdle { + t.InvalidAction("cannot start L2 build when derivation is not idle") + return + } +@@ -189,22 +191,22 @@ } + } +  + func (s *L2Sequencer) ActBuildL2ToEcotone(t Testing) { +- require.NotNil(t, s.rollupCfg.EcotoneTime, "cannot activate Ecotone when it is not scheduled") +- for s.L2Unsafe().Time < *s.rollupCfg.EcotoneTime { ++ require.NotNil(t, s.RollupCfg.EcotoneTime, "cannot activate Ecotone when it is not scheduled") ++ for s.L2Unsafe().Time < *s.RollupCfg.EcotoneTime { + s.ActL2StartBlock(t) + s.ActL2EndBlock(t) + } + } + func (s *L2Sequencer) ActBuildL2ToFjord(t Testing) { +- require.NotNil(t, s.rollupCfg.FjordTime, "cannot activate FjordTime when it is not scheduled") +- for s.L2Unsafe().Time < *s.rollupCfg.FjordTime { ++ require.NotNil(t, s.RollupCfg.FjordTime, "cannot activate FjordTime when it is not scheduled") ++ for s.L2Unsafe().Time < *s.RollupCfg.FjordTime { + s.ActL2StartBlock(t) + s.ActL2EndBlock(t) + } + } + func (s *L2Sequencer) ActBuildL2ToGranite(t Testing) { +- require.NotNil(t, s.rollupCfg.GraniteTime, "cannot activate GraniteTime when it is not scheduled") +- for s.L2Unsafe().Time < *s.rollupCfg.GraniteTime { ++ require.NotNil(t, s.RollupCfg.GraniteTime, "cannot activate GraniteTime when it is not scheduled") ++ for s.L2Unsafe().Time < *s.RollupCfg.GraniteTime { + s.ActL2StartBlock(t) + s.ActL2EndBlock(t) + }
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+36
+
-14
+ +
+ +
+
+
diff --git OP/op-e2e/actions/l2_verifier.go CELO/op-e2e/actions/helpers/l2_verifier.go +rename from op-e2e/actions/l2_verifier.go +rename to op-e2e/actions/helpers/l2_verifier.go +index 5cc09c76c4e423135aad3741c6eb4c1231de2066..1594e1eb368cf46461179b32a12d2556be7353e1 100644 +--- OP/op-e2e/actions/l2_verifier.go ++++ CELO/op-e2e/actions/helpers/l2_verifier.go +@@ -1,4 +1,4 @@ +-package actions ++package helpers +  + import ( + "context" +@@ -23,6 +23,7 @@ "github.com/ethereum-optimism/optimism/op-node/rollup/driver" + "github.com/ethereum-optimism/optimism/op-node/rollup/engine" + "github.com/ethereum-optimism/optimism/op-node/rollup/event" + "github.com/ethereum-optimism/optimism/op-node/rollup/finality" ++ "github.com/ethereum-optimism/optimism/op-node/rollup/interop" + "github.com/ethereum-optimism/optimism/op-node/rollup/status" + "github.com/ethereum-optimism/optimism/op-node/rollup/sync" + "github.com/ethereum-optimism/optimism/op-service/client" +@@ -39,7 +40,7 @@ eventSys event.System +  + log log.Logger +  +- eng L2API ++ Eng L2API +  + syncStatus driver.SyncStatusTracker +  +@@ -48,18 +49,19 @@ + drainer event.Drainer +  + // L2 rollup +- engine *engine.EngineController +- derivation *derive.DerivationPipeline ++ engine *engine.EngineController ++ derivationMetrics *testutils.TestDerivationMetrics ++ derivation *derive.DerivationPipeline +  + safeHeadListener rollup.SafeHeadListener + syncCfg *sync.Config +  + l1 derive.L1Fetcher +  +- l2PipelineIdle bool ++ L2PipelineIdle bool + l2Building bool +  +- rollupCfg *rollup.Config ++ RollupCfg *rollup.Config +  + rpc *rpc.Server +  +@@ -84,7 +86,11 @@ rollup.SafeHeadListener + node.SafeDBReader + } +  +-func NewL2Verifier(t Testing, log log.Logger, l1 derive.L1Fetcher, blobsSrc derive.L1BlobsFetcher, altDASrc driver.AltDAIface, eng L2API, cfg *rollup.Config, syncCfg *sync.Config, safeHeadListener safeDB) *L2Verifier { ++func NewL2Verifier(t Testing, log log.Logger, l1 derive.L1Fetcher, ++ blobsSrc derive.L1BlobsFetcher, altDASrc driver.AltDAIface, ++ eng L2API, cfg *rollup.Config, syncCfg *sync.Config, safeHeadListener safeDB, ++ interopBackend interop.InteropBackend, ++) *L2Verifier { + ctx, cancel := context.WithCancel(context.Background()) + t.Cleanup(cancel) +  +@@ -102,6 +108,10 @@ OnLimited: func() { + log.Warn("Hitting events rate-limit. An events code-path may be hot-looping.") + t.Fatal("Tests must not hot-loop events") + }, + } -+}` + -+const alfajoresAllocJSON = `{ -+ "456f41406B32c45D59E539e4BBA3D7898c3584dA": { -+ "balance": "103010030000000000000000000" -+ }, -+ "DD1F519F63423045F526b8c83edC0eB4BA6434a4": { -+ "balance": "10011000000000000000000" -+ }, -+ "050f34537F5b2a00B9B9C752Cb8500a3fcE3DA7d": { -+ "balance": "10011000000000000000000" -+ }, -+ "Cda518F6b5a797C3EC45D37c65b83e0b0748eDca": { -+ "balance": "10011000000000000000000" -+ }, -+ "b4e92c94A2712e98c020A81868264bdE52C188Cb": { -+ "balance": "10011000000000000000000" -+ }, -+ "Ae1ec841923811219b98ACeB1db297AADE2F46F3": { -+ "balance": "10011000000000000000000" -+ }, -+ "621843731fe33418007C06ee48CfD71e0ea828d9": { -+ "balance": "10011000000000000000000" -+ }, -+ "2A43f97f8BF959E31F69A894ebD80A88572C8553": { -+ "balance": "10011000000000000000000" -+ }, -+ "AD682035bE6Ab6f06e478D2BDab0EAb6477B460E": { -+ "balance": "10011000000000000000000" -+ }, -+ "30D060F129817c4DE5fBc1366d53e19f43c8c64f": { -+ "balance": "10011000000000000000000" -+ }, -+ "22579CA45eE22E2E16dDF72D955D6cf4c767B0eF": { -+ "balance": "10011000000000000000000" -+ }, -+ "1173C5A50bf025e8356823a068E396ccF2bE696C": { -+ "balance": "10011000000000000000000" -+ }, -+ "40F71B525A96baa8d14Eaa7Bcd19929782659c64": { -+ "balance": "10011000000000000000000" -+ }, -+ "b923626C6f1d237252793FB2aA12BA21328C51BC": { -+ "balance": "10011000000000000000000" -+ }, -+ "B70f9ABf41F36B3ab60cc9aE1a85Ddda3C88D261": { -+ "balance": "10011000000000000000000" -+ }, -+ "d4369DB59eaDc4Cfa089c0a3c1004ceAb1b318D8": { -+ "balance": "10011000000000000000000" -+ }, -+ "2fd430d3a96eadc38cc1B38b6685C5f52Cf7a083": { -+ "balance": "10011000000000000000000" -+ }, -+ "Fecc71C8f33Ca5952534fd346ADdeDC38DBb9cb7": { -+ "balance": "10011000000000000000000" -+ }, -+ "0de78C89e7BF5060f28dd3f820C15C4A6A81AFB5": { -+ "balance": "10011000000000000000000" -+ }, -+ "75411b92fcE120C1e7fd171b1c2bF802f2E3CF48": { -+ "balance": "10011000000000000000000" -+ }, -+ "563433bD8357b06982Fe001df20B2b43393d21d2": { -+ "balance": "10011000000000000000000" -+ }, -+ "79dfB9d2367E7921d4139D7841d24ED82F48907F": { -+ "balance": "10011000000000000000000" -+ }, -+ "5809369FC5121a071eE67659a975e88ae40fBE3b": { -+ "balance": "10011000000000000000000" -+ }, -+ "7517E54a456bcc6c5c695B5d9f97EBc05d29a824": { -+ "balance": "10011000000000000000000" -+ }, -+ "B0a1A5Ffcb34E6Fa278D2b40613f0AE1042d32f8": { -+ "balance": "10011000000000000000000" -+ }, -+ "EeE9f4DDf49976251E84182AbfD3300Ee58D12aa": { -+ "balance": "10011000000000000000000" -+ }, -+ "Eb5Fd57f87a4e1c7bAa53ec1c0d021bb1710B743": { -+ "balance": "10011000000000000000000" -+ }, -+ "B7Dd51bFb73c5753778e5Af56f1D9669BCe6777F": { -+ "balance": "10011000000000000000000" -+ }, -+ "33C222BB13C63295AF32D6C91278AA34b573e776": { -+ "balance": "10011000000000000000000" -+ }, -+ "83c58603bF72DA067D7f6238E7bF390d91B2f531": { -+ "balance": "10011000000000000000000" -+ }, -+ "6651112198C0da05921355642a2B8dF1fA3Ede93": { -+ "balance": "10011000000000000000000" -+ }, -+ "4EE72A98549eA7CF774C3E2E1b39fF166b4b68BE": { -+ "balance": "10011000000000000000000" -+ }, -+ "840b32F30e1a3b2E8b9E6C0972eBa0148E22B847": { -+ "balance": "100000000000000000000" -+ }, -+ "000000000000000000000000000000000000ce10": { -+ "code": "0x60806040526004361061004a5760003560e01c806303386ba3146101e757806342404e0714610280578063bb913f41146102d7578063d29d44ee14610328578063f7e6af8014610379575b6000600160405180807f656970313936372e70726f78792e696d706c656d656e746174696f6e00000000815250601c019050604051809103902060001c0360001b9050600081549050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610136576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f4e6f20496d706c656d656e746174696f6e20736574000000000000000000000081525060200191505060405180910390fd5b61013f816103d0565b6101b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f496e76616c696420636f6e74726163742061646472657373000000000000000081525060200191505060405180910390fd5b60405136810160405236600082376000803683855af43d604051818101604052816000823e82600081146101e3578282f35b8282fd5b61027e600480360360408110156101fd57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019064010000000081111561023a57600080fd5b82018360208201111561024c57600080fd5b8035906020019184600183028401116401000000008311171561026e57600080fd5b909192939192939050505061041b565b005b34801561028c57600080fd5b506102956105c1565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156102e357600080fd5b50610326600480360360208110156102fa57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061060d565b005b34801561033457600080fd5b506103776004803603602081101561034b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506107bd565b005b34801561038557600080fd5b5061038e610871565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b60008060007fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47060001b9050833f915080821415801561041257506000801b8214155b92505050919050565b610423610871565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146104c3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f73656e64657220776173206e6f74206f776e657200000000000000000000000081525060200191505060405180910390fd5b6104cc8361060d565b600060608473ffffffffffffffffffffffffffffffffffffffff168484604051808383808284378083019250505092505050600060405180830381855af49150503d8060008114610539576040519150601f19603f3d011682016040523d82523d6000602084013e61053e565b606091505b508092508193505050816105ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f696e697469616c697a6174696f6e2063616c6c6261636b206661696c6564000081525060200191505060405180910390fd5b5050505050565b600080600160405180807f656970313936372e70726f78792e696d706c656d656e746174696f6e00000000815250601c019050604051809103902060001c0360001b9050805491505090565b610615610871565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146106b5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f73656e64657220776173206e6f74206f776e657200000000000000000000000081525060200191505060405180910390fd5b6000600160405180807f656970313936372e70726f78792e696d706c656d656e746174696f6e00000000815250601c019050604051809103902060001c0360001b9050610701826103d0565b610773576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f496e76616c696420636f6e74726163742061646472657373000000000000000081525060200191505060405180910390fd5b8181558173ffffffffffffffffffffffffffffffffffffffff167fab64f92ab780ecbf4f3866f57cee465ff36c89450dcce20237ca7a8d81fb7d1360405160405180910390a25050565b6107c5610871565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610865576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f73656e64657220776173206e6f74206f776e657200000000000000000000000081525060200191505060405180910390fd5b61086e816108bd565b50565b600080600160405180807f656970313936372e70726f78792e61646d696e000000000000000000000000008152506013019050604051809103902060001c0360001b9050805491505090565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610960576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f6f776e65722063616e6e6f74206265203000000000000000000000000000000081525060200191505060405180910390fd5b6000600160405180807f656970313936372e70726f78792e61646d696e000000000000000000000000008152506013019050604051809103902060001c0360001b90508181558173ffffffffffffffffffffffffffffffffffffffff167f50146d0e3c60aa1d17a70635b05494f864e86144a2201275021014fbf08bafe260405160405180910390a2505056fea165627a7a723058202dbb6037e4381b4ad95015ed99441a23345cc2ae52ef27e2e91d34fb0acd277b0029", -+ "storage": { -+ "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "456f41406B32c45D59E539e4BBA3D7898c3584dA" -+ }, -+ "balance": "0" -+ } -+}` ++ if interopBackend != nil { ++ sys.Register("interop", interop.NewInteropDeriver(log, cfg, ctx, interopBackend, eng), opts) + } +  + metrics := &testutils.TestDerivationMetrics{} +@@ -152,17 +162,18 @@ + rollupNode := &L2Verifier{ + eventSys: sys, + log: log, +- eng: eng, ++ Eng: eng, + engine: ec, ++ derivationMetrics: metrics, + derivation: pipeline, + safeHeadListener: safeHeadListener, + syncCfg: syncCfg, + drainer: executor, + l1: l1, + syncStatus: syncStatusTracker, +- l2PipelineIdle: true, ++ L2PipelineIdle: true, + l2Building: false, +- rollupCfg: cfg, ++ RollupCfg: cfg, + rpc: rpc.NewServer(), + synchronousEvents: testActionEmitter, + } +@@ -197,7 +208,7 @@ verifier *L2Verifier + } +  + func (s *l2VerifierBackend) BlockRefWithStatus(ctx context.Context, num uint64) (eth.L2BlockRef, *eth.SyncStatus, error) { +- ref, err := s.verifier.eng.L2BlockRefByNumber(ctx, num) ++ ref, err := s.verifier.Eng.L2BlockRefByNumber(ctx, num) + return ref, s.verifier.SyncStatus(), err + } +  +@@ -228,6 +239,10 @@ } +  + func (s *l2VerifierBackend) OnUnsafeL2Payload(ctx context.Context, envelope *eth.ExecutionPayloadEnvelope) error { + return nil ++} + -+const mainnetAllocJSON = "{\"0x11901cf7eEae1E2644995FB2E47Ce46bC7F33246\":{\"balance\":\"120000000000000000000000000\"},\"0xC1cDA18694F5B86cFB80c1B4f8Cc046B0d7E6326\":{\"balance\":\"20000000000000000000000000\"},\"0xa5d40D93b01AfBafec84E20018Aff427628F645E\":{\"balance\":\"20000000000000000000000000\"},\"0x8d485780E84E23437f8F6938D96B964645529127\":{\"balance\":\"20000000000000000000000000\"},\"0x5F857c501b73ddFA804234f1f1418D6f75554076\":{\"balance\":\"20000000000000000000000000\"},\"0xaa9064F57F8d7de4b3e08c35561E21Afd6341390\":{\"balance\":\"20000000000000000000000000\"},\"0x7FA26b50b3e9a2eC8AD1850a4c4FBBF94D806E95\":{\"balance\":\"20000000000000000000000000\"},\"0x08960Ce6b58BE32FBc6aC1489d04364B4f7dC216\":{\"balance\":\"20000000000000000000000000\"},\"0x77B68B2e7091D4F242a8Af89F200Af941433C6d8\":{\"balance\":\"20000000000000000000000000\"},\"0x75Bb69C002C43f5a26a2A620518775795Fd45ecf\":{\"balance\":\"20000000000000000000000000\"},\"0x19992AE48914a178Bf138665CffDD8CD79b99513\":{\"balance\":\"20000000000000000000000000\"},\"0xE23a4c6615669526Ab58E9c37088bee4eD2b2dEE\":{\"balance\":\"20000000000000000000000\"},\"0xDe22679dCA843B424FD0BBd70A22D5F5a4B94fe4\":{\"balance\":\"10200014000000000000000000\"},\"0x743D80810fe10c5C3346D2940997cC9647035B13\":{\"balance\":\"20513322000000000000000000\"},\"0x8e1c4355307F1A59E7eD4Ae057c51368b9338C38\":{\"balance\":\"7291740000000000000000000\"},\"0x417fe63186C388812e342c85FF87187Dc584C630\":{\"balance\":\"20000062000000000000000000\"},\"0xF5720c180a6Fa14ECcE82FB1bB060A39E93A263c\":{\"balance\":\"30000061000000000000000000\"},\"0xB80d1e7F9CEbe4b5E1B1Acf037d3a44871105041\":{\"balance\":\"9581366833333333333333335\"},\"0xf8ed78A113cD2a34dF451Ba3D540FFAE66829AA0\":{\"balance\":\"11218686833333333333333333\"},\"0x9033ff75af27222c8f36a148800c7331581933F3\":{\"balance\":\"11218686833333333333333333\"},\"0x8A07541C2eF161F4e3f8de7c7894718dA26626B2\":{\"balance\":\"11218686833333333333333333\"},\"0xB2fe7AFe178335CEc3564d7671EEbD7634C626B0\":{\"balance\":\"11218686833333333333333333\"},\"0xc471776eA02705004C451959129bF09423B56526\":{\"balance\":\"11218686833333333333333333\"},\"0xeF283eca68DE87E051D427b4be152A7403110647\":{\"balance\":\"14375000000000000000000000\"},\"0x7cf091C954ed7E9304452d31fd59999505Ddcb7a\":{\"balance\":\"14375000000000000000000000\"},\"0xa5d2944C32a8D7b284fF0b84c20fDcc46937Cf64\":{\"balance\":\"14375000000000000000000000\"},\"0xFC89C17525f08F2Bc9bA8cb77BcF05055B1F7059\":{\"balance\":\"14375000000000000000000000\"},\"0x3Fa7C646599F3174380BD9a7B6efCde90b5d129d\":{\"balance\":\"14375000000000000000000000\"},\"0x989e1a3B344A43911e02cCC609D469fbc15AB1F1\":{\"balance\":\"14375000000000000000000000\"},\"0xAe1d640648009DbE0Aa4485d3BfBB68C37710924\":{\"balance\":\"20025000000000000000000000\"},\"0x1B6C64779F42BA6B54C853Ab70171aCd81b072F7\":{\"balance\":\"20025000000000000000000000\"},\"000000000000000000000000000000000000ce10\":{\"code\":\"0x60806040526004361061004a5760003560e01c806303386ba3146101e757806342404e0714610280578063bb913f41146102d7578063d29d44ee14610328578063f7e6af8014610379575b6000600160405180807f656970313936372e70726f78792e696d706c656d656e746174696f6e00000000815250601c019050604051809103902060001c0360001b9050600081549050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610136576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f4e6f20496d706c656d656e746174696f6e20736574000000000000000000000081525060200191505060405180910390fd5b61013f816103d0565b6101b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f496e76616c696420636f6e74726163742061646472657373000000000000000081525060200191505060405180910390fd5b60405136810160405236600082376000803683855af43d604051818101604052816000823e82600081146101e3578282f35b8282fd5b61027e600480360360408110156101fd57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019064010000000081111561023a57600080fd5b82018360208201111561024c57600080fd5b8035906020019184600183028401116401000000008311171561026e57600080fd5b909192939192939050505061041b565b005b34801561028c57600080fd5b506102956105c1565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156102e357600080fd5b50610326600480360360208110156102fa57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061060d565b005b34801561033457600080fd5b506103776004803603602081101561034b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506107bd565b005b34801561038557600080fd5b5061038e610871565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b60008060007fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47060001b9050833f915080821415801561041257506000801b8214155b92505050919050565b610423610871565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146104c3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f73656e64657220776173206e6f74206f776e657200000000000000000000000081525060200191505060405180910390fd5b6104cc8361060d565b600060608473ffffffffffffffffffffffffffffffffffffffff168484604051808383808284378083019250505092505050600060405180830381855af49150503d8060008114610539576040519150601f19603f3d011682016040523d82523d6000602084013e61053e565b606091505b508092508193505050816105ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f696e697469616c697a6174696f6e2063616c6c6261636b206661696c6564000081525060200191505060405180910390fd5b5050505050565b600080600160405180807f656970313936372e70726f78792e696d706c656d656e746174696f6e00000000815250601c019050604051809103902060001c0360001b9050805491505090565b610615610871565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146106b5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f73656e64657220776173206e6f74206f776e657200000000000000000000000081525060200191505060405180910390fd5b6000600160405180807f656970313936372e70726f78792e696d706c656d656e746174696f6e00000000815250601c019050604051809103902060001c0360001b9050610701826103d0565b610773576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260188152602001807f496e76616c696420636f6e74726163742061646472657373000000000000000081525060200191505060405180910390fd5b8181558173ffffffffffffffffffffffffffffffffffffffff167fab64f92ab780ecbf4f3866f57cee465ff36c89450dcce20237ca7a8d81fb7d1360405160405180910390a25050565b6107c5610871565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610865576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f73656e64657220776173206e6f74206f776e657200000000000000000000000081525060200191505060405180910390fd5b61086e816108bd565b50565b600080600160405180807f656970313936372e70726f78792e61646d696e000000000000000000000000008152506013019050604051809103902060001c0360001b9050805491505090565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610960576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f6f776e65722063616e6e6f74206265203000000000000000000000000000000081525060200191505060405180910390fd5b6000600160405180807f656970313936372e70726f78792e61646d696e000000000000000000000000008152506013019050604051809103902060001c0360001b90508181558173ffffffffffffffffffffffffffffffffffffffff167f50146d0e3c60aa1d17a70635b05494f864e86144a2201275021014fbf08bafe260405160405180910390a2505056fea165627a7a723058206808dd43e7d765afca53fe439122bc5eac16d708ce7d463451be5042426f101f0029\",\"storage\":{\"0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103\":\"0xE23a4c6615669526Ab58E9c37088bee4eD2b2dEE\"},\"balance\":\"0\"}}" ++func (s *L2Verifier) DerivationMetricsTracer() *testutils.TestDerivationMetrics { ++ return s.derivationMetrics + } +  + func (s *L2Verifier) L2Finalized() eth.L2BlockRef { +@@ -316,6 +331,13 @@ }, false)) + require.Equal(t, finalized, s.syncStatus.SyncStatus().FinalizedL1) + } +  ++func (s *L2Verifier) ActInteropBackendCheck(t Testing) { ++ s.synchronousEvents.Emit(engine.CrossUpdateRequestEvent{ ++ CrossUnsafe: true, ++ CrossSafe: true, ++ }) ++} + -+var celoL1GenesisAllocJSON = map[uint64]string{ -+ MainnetNetworkID: mainnetAllocJSON, -+ AlfajoresNetworkID: alfajoresAllocJSON, -+ BaklavaNetworkID: baklavaAllocJSON, + func (s *L2Verifier) OnEvent(ev event.Event) bool { + switch x := ev.(type) { + case rollup.L1TemporaryErrorEvent: +@@ -330,9 +352,9 @@ s.log.Warn("Derivation pipeline is being reset", "err", x.Err) + case rollup.CriticalErrorEvent: + panic(fmt.Errorf("derivation failed critically: %w", x.Err)) + case derive.DeriverIdleEvent: +- s.l2PipelineIdle = true ++ s.L2PipelineIdle = true + case derive.PipelineStepEvent: +- s.l2PipelineIdle = false ++ s.L2PipelineIdle = false + case driver.StepReqEvent: + s.synchronousEvents.Emit(driver.StepEvent{}) + default: +@@ -381,7 +403,7 @@ + // ActL2InsertUnsafePayload creates an action that can insert an unsafe execution payload + func (s *L2Verifier) ActL2InsertUnsafePayload(payload *eth.ExecutionPayloadEnvelope) Action { + return func(t Testing) { +- ref, err := derive.PayloadToBlockRef(s.rollupCfg, payload.ExecutionPayload) ++ ref, err := derive.PayloadToBlockRef(s.RollupCfg, payload.ExecutionPayload) + require.NoError(t, err) + err = s.engine.InsertUnsafePayload(t.Ctx(), payload, ref) + require.NoError(t, err)
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+75
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/actions/helpers/setups.go CELO/op-e2e/actions/helpers/setups.go +new file mode 100644 +index 0000000000000000000000000000000000000000..26e19eae82a055beed7b5d7ed1167798eb2d78a4 +--- /dev/null ++++ CELO/op-e2e/actions/helpers/setups.go +@@ -0,0 +1,75 @@ ++package helpers ++ ++import ( ++ altda "github.com/ethereum-optimism/optimism/op-alt-da" ++ "github.com/ethereum-optimism/optimism/op-e2e/actions/upgrades/helpers" ++ "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" ++ "github.com/ethereum-optimism/optimism/op-node/rollup/derive" ++ "github.com/ethereum-optimism/optimism/op-node/rollup/sync" ++ "github.com/ethereum-optimism/optimism/op-service/sources" ++ "github.com/ethereum-optimism/optimism/op-service/testlog" ++ "github.com/ethereum/go-ethereum/common" ++ "github.com/ethereum/go-ethereum/common/hexutil" ++ "github.com/ethereum/go-ethereum/log" ++ "github.com/stretchr/testify/require" ++) ++ ++func SetupSequencerTest(t Testing, sd *e2eutils.SetupData, log log.Logger, opts ...SequencerOpt) (*L1Miner, *L2Engine, *L2Sequencer) { ++ jwtPath := e2eutils.WriteDefaultJWT(t) ++ cfg := DefaultSequencerConfig() ++ for _, opt := range opts { ++ opt(cfg) ++ } ++ ++ miner := NewL1Miner(t, log.New("role", "l1-miner"), sd.L1Cfg) ++ ++ l1F, err := sources.NewL1Client(miner.RPCClient(), log, nil, sources.L1ClientDefaultConfig(sd.RollupCfg, false, sources.RPCKindStandard)) ++ require.NoError(t, err) ++ engine := NewL2Engine(t, log.New("role", "sequencer-engine"), sd.L2Cfg, sd.RollupCfg.Genesis.L1, jwtPath, EngineWithP2P()) ++ l2Cl, err := sources.NewEngineClient(engine.RPCClient(), log, nil, sources.EngineClientDefaultConfig(sd.RollupCfg)) ++ require.NoError(t, err) ++ ++ sequencer := NewL2Sequencer(t, log.New("role", "sequencer"), l1F, miner.BlobStore(), altda.Disabled, l2Cl, sd.RollupCfg, 0, cfg.InteropBackend) ++ return miner, engine, sequencer ++} ++ ++func SetupVerifier(t Testing, sd *e2eutils.SetupData, log log.Logger, ++ l1F derive.L1Fetcher, blobSrc derive.L1BlobsFetcher, syncCfg *sync.Config, opts ...VerifierOpt) (*L2Engine, *L2Verifier) { ++ cfg := DefaultVerifierCfg() ++ for _, opt := range opts { ++ opt(cfg) ++ } ++ jwtPath := e2eutils.WriteDefaultJWT(t) ++ engine := NewL2Engine(t, log.New("role", "verifier-engine"), sd.L2Cfg, sd.RollupCfg.Genesis.L1, jwtPath, EngineWithP2P()) ++ engCl := engine.EngineClient(t, sd.RollupCfg) ++ verifier := NewL2Verifier(t, log.New("role", "verifier"), l1F, blobSrc, altda.Disabled, engCl, sd.RollupCfg, syncCfg, cfg.SafeHeadListener, cfg.InteropBackend) ++ return engine, verifier ++} ++ ++func SetupVerifierOnlyTest(t Testing, sd *e2eutils.SetupData, log log.Logger) (*L1Miner, *L2Engine, *L2Verifier) { ++ miner := NewL1Miner(t, log, sd.L1Cfg) ++ l1Cl := miner.L1Client(t, sd.RollupCfg) ++ engine, verifier := SetupVerifier(t, sd, log, l1Cl, miner.BlobStore(), &sync.Config{}) ++ return miner, engine, verifier ++} ++ ++func SetupReorgTest(t Testing, config *e2eutils.TestParams, deltaTimeOffset *hexutil.Uint64) (*e2eutils.SetupData, *e2eutils.DeployParams, *L1Miner, *L2Sequencer, *L2Engine, *L2Verifier, *L2Engine, *L2Batcher) { ++ dp := e2eutils.MakeDeployParams(t, config) ++ helpers.ApplyDeltaTimeOffset(dp, deltaTimeOffset) ++ ++ sd := e2eutils.Setup(t, dp, DefaultAlloc) ++ log := testlog.Logger(t, log.LevelDebug) ++ ++ return SetupReorgTestActors(t, dp, sd, log) ++} ++ ++func SetupReorgTestActors(t Testing, dp *e2eutils.DeployParams, sd *e2eutils.SetupData, log log.Logger) (*e2eutils.SetupData, *e2eutils.DeployParams, *L1Miner, *L2Sequencer, *L2Engine, *L2Verifier, *L2Engine, *L2Batcher) { ++ miner, seqEngine, sequencer := SetupSequencerTest(t, sd, log) ++ miner.ActL1SetFeeRecipient(common.Address{'A'}) ++ sequencer.ActL2PipelineFull(t) ++ verifEngine, verifier := SetupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) ++ rollupSeqCl := sequencer.RollupClient() ++ batcher := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp), ++ rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) ++ return sd, dp, miner, sequencer, seqEngine, verifier, verifEngine, batcher ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+1
+
-1
+ +
+ +
+
+
diff --git OP/op-e2e/actions/tx_helper.go CELO/op-e2e/actions/helpers/tx_helper.go +rename from op-e2e/actions/tx_helper.go +rename to op-e2e/actions/helpers/tx_helper.go +index e63c1a224822316dba017b987ebd9fa44773d051..8174563102c81934bd9d5911fdff976bbc98cb74 100644 +--- OP/op-e2e/actions/tx_helper.go ++++ CELO/op-e2e/actions/helpers/tx_helper.go +@@ -1,4 +1,4 @@ +-package actions ++package helpers +  + import ( + "context"
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+16
+
-8
+ +
+ +
+
+
diff --git OP/op-e2e/actions/user.go CELO/op-e2e/actions/helpers/user.go +rename from op-e2e/actions/user.go +rename to op-e2e/actions/helpers/user.go +index dabc9c1d898029caf35b38a4af1d0bb371617846..2acd6ccaf8e72b14e29520aef231f64cc84612fe 100644 +--- OP/op-e2e/actions/user.go ++++ CELO/op-e2e/actions/helpers/user.go +@@ -1,4 +1,4 @@ +-package actions ++package helpers +  + import ( + "context" +@@ -24,10 +24,10 @@ "github.com/ethereum/go-ethereum/params" + "github.com/stretchr/testify/require" +  + "github.com/ethereum-optimism/optimism/op-chain-ops/crossdomain" +- e2e "github.com/ethereum-optimism/optimism/op-e2e" + legacybindings "github.com/ethereum-optimism/optimism/op-e2e/bindings" + "github.com/ethereum-optimism/optimism/op-e2e/config" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" ++ e2ehelpers "github.com/ethereum-optimism/optimism/op-e2e/system/helpers" + "github.com/ethereum-optimism/optimism/op-node/bindings" + bindingspreview "github.com/ethereum-optimism/optimism/op-node/bindings/preview" + "github.com/ethereum-optimism/optimism/op-node/rollup/derive" +@@ -130,6 +130,10 @@ func (s *BasicUser[B]) SetUserEnv(env *BasicUserEnv[B]) { + s.env = env + } +  ++func (s *BasicUser[B]) Signer() types.Signer { ++ return s.env.Signer +} + -+// GetCeloL1GenesisAlloc returns the legacy Celo L1 genesis allocation JSON for the given network ID. -+func GetCeloL1GenesisAlloc(config *params.ChainConfig) ([]byte, error) { -+ chainID := config.ChainID.Uint64() -+ allocJSON, ok := celoL1GenesisAllocJSON[chainID] -+ if !ok { -+ return nil, fmt.Errorf("no genesis allocation JSON found for network ID %d", chainID) -+ } -+ return []byte(allocJSON), nil + func (s *BasicUser[B]) signerFn(address common.Address, tx *types.Transaction) (*types.Transaction, error) { + if address != s.address { + return nil, bind.ErrNotAuthorized +@@ -231,9 +235,7 @@ require.NoError(t, err) + return receipt + } +  +-// ActMakeTx makes a tx with the predetermined contents (see randomization and other actions) +-// and sends it to the tx pool +-func (s *BasicUser[B]) ActMakeTx(t Testing) { ++func (s *BasicUser[B]) MakeTransaction(t Testing) *types.Transaction { + gas, err := s.env.EthCl.EstimateGas(t.Ctx(), ethereum.CallMsg{ + From: s.address, + To: s.txToAddr, +@@ -243,7 +245,7 @@ Value: s.TxValue(), + Data: s.txCallData, + }) + require.NoError(t, err, "gas estimation should pass") +- tx := types.MustSignNewTx(s.account, s.env.Signer, &types.DynamicFeeTx{ ++ return types.MustSignNewTx(s.account, s.env.Signer, &types.DynamicFeeTx{ + To: s.txToAddr, + GasFeeCap: s.txOpts.GasFeeCap, + GasTipCap: s.txOpts.GasTipCap, +@@ -253,7 +255,13 @@ Nonce: s.PendingNonce(t), + Gas: gas, + Data: s.txCallData, + }) +- err = s.env.EthCl.SendTransaction(t.Ctx(), tx) +} + -+// BuildGenesis creates a genesis block from the given parameters. -+func BuildGenesis(config *params.ChainConfig, allocs, extraData []byte, timestamp uint64) (*core.Genesis, error) { -+ genesisAlloc := &types.GenesisAlloc{} -+ if err := genesisAlloc.UnmarshalJSON(allocs); err != nil { -+ return nil, err -+ } -+ return &core.Genesis{ -+ Config: config, -+ Timestamp: timestamp, -+ ExtraData: extraData, -+ Alloc: *genesisAlloc, -+ }, nil -+}
++// ActMakeTx makes a tx with the predetermined contents (see randomization and other actions) ++// and sends it to the tx pool ++func (s *BasicUser[B]) ActMakeTx(t Testing) { ++ tx := s.MakeTransaction(t) ++ err := s.env.EthCl.SendTransaction(t.Ctx(), tx) + require.NoError(t, err, "must send tx") + s.lastTxHash = tx.Hash() + // reset the calldata +@@ -449,7 +457,7 @@ } +  + header, err := s.L2.env.EthCl.HeaderByNumber(t.Ctx(), l2OutputBlockNr) + require.NoError(t, err) +- params, err := e2e.ProveWithdrawalParameters(t.Ctx(), s.L2.env.Bindings.ProofClient, s.L2.env.EthCl, s.L2.env.EthCl, s.lastL2WithdrawalTxHash, header, &s.L1.env.Bindings.L2OutputOracle.L2OutputOracleCaller, &s.L1.env.Bindings.DisputeGameFactory.DisputeGameFactoryCaller, &s.L1.env.Bindings.OptimismPortal2.OptimismPortal2Caller) ++ params, err := e2ehelpers.ProveWithdrawalParameters(t.Ctx(), s.L2.env.Bindings.ProofClient, s.L2.env.EthCl, s.L2.env.EthCl, s.lastL2WithdrawalTxHash, header, &s.L1.env.Bindings.L2OutputOracle.L2OutputOracleCaller, &s.L1.env.Bindings.DisputeGameFactory.DisputeGameFactoryCaller, &s.L1.env.Bindings.OptimismPortal2.OptimismPortal2Caller) + require.NoError(t, err) +  + return &params, nil
@@ -14300,472 +63680,1040 @@
-
+454
+
+6
+
-6
+ +
+ +
+
+
diff --git OP/op-e2e/actions/user_test.go CELO/op-e2e/actions/helpers/user_test.go +rename from op-e2e/actions/user_test.go +rename to op-e2e/actions/helpers/user_test.go +index 3a0b079cb3e4c4a10b39ce33dfdeddc62f2142c0..8ee60aa680e3d16aaab8a5bca363bdf856010c4c 100644 +--- OP/op-e2e/actions/user_test.go ++++ CELO/op-e2e/actions/helpers/user_test.go +@@ -1,4 +1,4 @@ +-package actions ++package helpers +  + import ( + "fmt" +@@ -109,7 +109,7 @@ } +  + func runCrossLayerUserTest(gt *testing.T, test hardforkScheduledTest) { + t := NewDefaultTesting(gt) +- dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) ++ dp := e2eutils.MakeDeployParams(t, DefaultRollupTestParams) + // This overwrites all deploy-config settings, + // so even when the deploy-config defaults change, we test the right transitions. + dp.DeployConfig.L2GenesisRegolithTimeOffset = test.regolithTime +@@ -125,13 +125,13 @@ if test.ecotoneTime != nil { + require.Zero(t, uint64(*test.ecotoneTime)%uint64(dp.DeployConfig.L2BlockTime), "ecotone fork must be aligned") + } +  +- sd := e2eutils.Setup(t, dp, defaultAlloc) ++ sd := e2eutils.Setup(t, dp, DefaultAlloc) + log := testlog.Logger(t, log.LevelDebug) +  + require.Equal(t, dp.Secrets.Addresses().Batcher, dp.DeployConfig.BatchSenderAddress) + require.Equal(t, dp.Secrets.Addresses().Proposer, dp.DeployConfig.L2OutputOracleProposer) +  +- miner, seqEngine, seq := setupSequencerTest(t, sd, log) ++ miner, seqEngine, seq := SetupSequencerTest(t, sd, log) + batcher := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp), + seq.RollupClient(), miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) +  +@@ -199,7 +199,7 @@ infoTx, err := l2Cl.TransactionInBlock(t.Ctx(), seq.L2Unsafe().Hash, 0) + require.NoError(t, err) + require.True(t, infoTx.IsDepositTx()) + // Should only be a system tx if regolith is not enabled +- require.Equal(t, !seq.rollupCfg.IsRegolith(seq.L2Unsafe().Time), infoTx.IsSystemTx()) ++ require.Equal(t, !seq.RollupCfg.IsRegolith(seq.L2Unsafe().Time), infoTx.IsSystemTx()) +  + // regular L2 tx, in new L2 block + alice.L2.ActResetTxOpts(t) +@@ -320,5 +320,5 @@ infoTx, err = l2Cl.TransactionInBlock(t.Ctx(), seq.L2Unsafe().Hash, 0) + require.NoError(t, err) + require.True(t, infoTx.IsDepositTx()) + // Should only be a system tx if regolith is not enabled +- require.Equal(t, !seq.rollupCfg.IsRegolith(seq.L2Unsafe().Time), infoTx.IsSystemTx()) ++ require.Equal(t, !seq.RollupCfg.IsRegolith(seq.L2Unsafe().Time), infoTx.IsSystemTx()) + }
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+79
-0
-
diff --git OP/op-chain-ops/cmd/celo-migrate/main.go CELO/op-chain-ops/cmd/celo-migrate/main.go +
diff --git OP/op-e2e/actions/helpers/utils.go CELO/op-e2e/actions/helpers/utils.go new file mode 100644 -index 0000000000000000000000000000000000000000..b23f2461adc53b6f5bc422adaa687235ccf2ba93 +index 0000000000000000000000000000000000000000..f4f1b812cbaa93e59aa88969bb6ee0ea195ff380 --- /dev/null -+++ CELO/op-chain-ops/cmd/celo-migrate/main.go -@@ -0,0 +1,454 @@ -+package main ++++ CELO/op-e2e/actions/helpers/utils.go +@@ -0,0 +1,79 @@ ++package helpers + +import ( -+ "context" -+ "errors" -+ "fmt" -+ "math/big" -+ "os" -+ "os/exec" -+ "runtime/debug" -+ "time" -+ -+ "log/slog" ++ "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" ++ "github.com/ethereum-optimism/optimism/op-node/node/safedb" ++ "github.com/ethereum-optimism/optimism/op-node/rollup/interop" ++ "github.com/ethereum/go-ethereum/crypto" ++ "github.com/ethereum/go-ethereum/eth/ethconfig" ++ "github.com/ethereum/go-ethereum/node" ++ "github.com/ethereum/go-ethereum/p2p" ++) + -+ "github.com/ethereum-optimism/optimism/op-chain-ops/foundry" -+ "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" -+ "github.com/ethereum-optimism/optimism/op-service/jsonutil" -+ oplog "github.com/ethereum-optimism/optimism/op-service/log" -+ "github.com/mattn/go-isatty" ++var DefaultRollupTestParams = &e2eutils.TestParams{ ++ MaxSequencerDrift: 40, ++ SequencerWindowSize: 120, ++ ChannelTimeout: 120, ++ L1BlockTime: 15, ++} + -+ "github.com/urfave/cli/v2" ++var DefaultAlloc = &e2eutils.AllocParams{PrefundTestUsers: true} + -+ "github.com/ethereum/go-ethereum/core/rawdb" -+ "github.com/ethereum/go-ethereum/core/types" -+ "github.com/ethereum/go-ethereum/ethclient" -+ "github.com/ethereum/go-ethereum/log" -+ "github.com/ethereum/go-ethereum/rpc" ++type VerifierCfg struct { ++ SafeHeadListener safeDB ++ InteropBackend interop.InteropBackend ++} + -+ "golang.org/x/sync/errgroup" -+) ++type VerifierOpt func(opts *VerifierCfg) + -+var ( -+ deployConfigFlag = &cli.PathFlag{ -+ Name: "deploy-config", -+ Usage: "Path to the JSON file that was used for the bedrock contracts deployment. A test example can be found here 'op-chain-ops/genesis/testdata/test-deploy-config-full.json' and documentation for the fields is at https://docs.optimism.io/builders/chain-operators/management/configuration", -+ Required: true, -+ } -+ l1DeploymentsFlag = &cli.PathFlag{ -+ Name: "l1-deployments", -+ Usage: "Path to L1 deployments JSON file, the output of running the bedrock contracts deployment for the given 'deploy-config'", -+ Required: true, -+ } -+ l1RPCFlag = &cli.StringFlag{ -+ Name: "l1-rpc", -+ Usage: "RPC URL for a node of the L1 defined in the 'deploy-config'", -+ Required: true, -+ } -+ l2AllocsFlag = &cli.PathFlag{ -+ Name: "l2-allocs", -+ Usage: "Path to L2 genesis allocs file. You can find instructions on how to generate this file in the README", -+ Required: true, -+ } -+ outfileRollupConfigFlag = &cli.PathFlag{ -+ Name: "outfile.rollup-config", -+ Usage: "Path to write the rollup config JSON file, to be provided to op-node with the 'rollup.config' flag", -+ Required: true, -+ } -+ outfileGenesisFlag = &cli.PathFlag{ -+ Name: "outfile.genesis", -+ Usage: "Path to write the genesis JSON file, to be used to sync new nodes", -+ Required: true, -+ } -+ migrationBlockNumberFlag = &cli.Uint64Flag{ -+ Name: "migration-block-number", -+ Usage: "Specifies the migration block number. If the source db is not synced exactly to the block immediately before this number (i.e. migration-block-number - 1), the migration will fail.", -+ Required: true, -+ } -+ migrationBlockTimeFlag = &cli.Uint64Flag{ -+ Name: "migration-block-time", -+ Usage: "Specifies a unix timestamp to use for the migration block. This should be set to the same timestamp as was used for the sequencer migration. If performing the sequencer migration, this should set to a time in the future around when the migration script is expected to complete.", -+ Required: true, -+ } -+ oldDBPathFlag = &cli.PathFlag{ -+ Name: "old-db", -+ Usage: "Path to the old Celo chaindata dir, can be found at '<datadir>/celo/chaindata'", -+ Required: true, -+ } -+ newDBPathFlag = &cli.PathFlag{ -+ Name: "new-db", -+ Usage: "Path to write migrated Celo chaindata, note the new node implementation expects to find this chaindata at the following path '<datadir>/geth/chaindata", -+ Required: true, -+ } -+ batchSizeFlag = &cli.Uint64Flag{ -+ Name: "batch-size", -+ Usage: "Batch size to use for block migration, larger batch sizes can speed up migration but require more memory. If increasing the batch size consider also increasing the memory-limit", -+ Value: 50000, // TODO(Alec) optimize default parameters -+ } -+ bufferSizeFlag = &cli.Uint64Flag{ -+ Name: "buffer-size", -+ Usage: "Buffer size to use for ancient block migration channels. Defaults to 0. Included to facilitate testing for performance improvements.", -+ Value: 0, -+ } -+ memoryLimitFlag = &cli.Int64Flag{ -+ Name: "memory-limit", -+ Usage: "Memory limit in MiB, should be set lower than the available amount of memory in your system to prevent out of memory errors", -+ Value: 7500, -+ } -+ reset = &cli.BoolFlag{ -+ Name: "reset", -+ Usage: "Delete everything in the destination directory aside from /ancients. This is useful if you need to re-run the full migration but do not want to repeat the lengthy ancients migration. If you'd like to reset the entire destination directory, you can delete it manually.", -+ Value: false, ++func WithSafeHeadListener(l safeDB) VerifierOpt { ++ return func(opts *VerifierCfg) { ++ opts.SafeHeadListener = l + } ++} + -+ preMigrationFlags = []cli.Flag{ -+ oldDBPathFlag, -+ newDBPathFlag, -+ batchSizeFlag, -+ bufferSizeFlag, -+ memoryLimitFlag, -+ reset, ++func WithInteropBackend(b interop.InteropBackend) VerifierOpt { ++ return func(opts *VerifierCfg) { ++ opts.InteropBackend = b + } -+ fullMigrationFlags = append( -+ preMigrationFlags, -+ deployConfigFlag, -+ l1DeploymentsFlag, -+ l1RPCFlag, -+ l2AllocsFlag, -+ outfileRollupConfigFlag, -+ outfileGenesisFlag, -+ migrationBlockTimeFlag, -+ migrationBlockNumberFlag, -+ ) -+) -+ -+type preMigrationOptions struct { -+ oldDBPath string -+ newDBPath string -+ batchSize uint64 -+ bufferSize uint64 -+ memoryLimit int64 -+ resetNonAncients bool +} + -+type stateMigrationOptions struct { -+ deployConfig string -+ l1Deployments string -+ l1RPC string -+ l2AllocsPath string -+ outfileRollupConfig string -+ outfileGenesis string -+ migrationBlockTime uint64 ++func DefaultVerifierCfg() *VerifierCfg { ++ return &VerifierCfg{ ++ SafeHeadListener: safedb.Disabled, ++ } +} + -+type fullMigrationOptions struct { -+ preMigrationOptions -+ stateMigrationOptions -+ migrationBlockNumber uint64 ++func EngineWithP2P() EngineOption { ++ return func(ethCfg *ethconfig.Config, nodeCfg *node.Config) error { ++ p2pKey, err := crypto.GenerateKey() ++ if err != nil { ++ return err ++ } ++ nodeCfg.P2P = p2p.Config{ ++ MaxPeers: 100, ++ NoDiscovery: true, ++ ListenAddr: "127.0.0.1:0", ++ PrivateKey: p2pKey, ++ } ++ return nil ++ } +} + -+func parsePreMigrationOptions(ctx *cli.Context) preMigrationOptions { -+ return preMigrationOptions{ -+ oldDBPath: ctx.String(oldDBPathFlag.Name), -+ newDBPath: ctx.String(newDBPathFlag.Name), -+ batchSize: ctx.Uint64(batchSizeFlag.Name), -+ bufferSize: ctx.Uint64(bufferSizeFlag.Name), -+ memoryLimit: ctx.Int64(memoryLimitFlag.Name), -+ resetNonAncients: ctx.Bool(reset.Name), -+ } ++type SequencerCfg struct { ++ VerifierCfg +} + -+func parseStateMigrationOptions(ctx *cli.Context) stateMigrationOptions { -+ return stateMigrationOptions{ -+ deployConfig: ctx.Path(deployConfigFlag.Name), -+ l1Deployments: ctx.Path(l1DeploymentsFlag.Name), -+ l1RPC: ctx.String(l1RPCFlag.Name), -+ l2AllocsPath: ctx.Path(l2AllocsFlag.Name), -+ outfileRollupConfig: ctx.Path(outfileRollupConfigFlag.Name), -+ outfileGenesis: ctx.Path(outfileGenesisFlag.Name), -+ migrationBlockTime: ctx.Uint64(migrationBlockTimeFlag.Name), -+ } ++func DefaultSequencerConfig() *SequencerCfg { ++ return &SequencerCfg{VerifierCfg: *DefaultVerifierCfg()} +} + -+func parseFullMigrationOptions(ctx *cli.Context) fullMigrationOptions { -+ return fullMigrationOptions{ -+ preMigrationOptions: parsePreMigrationOptions(ctx), -+ stateMigrationOptions: parseStateMigrationOptions(ctx), -+ migrationBlockNumber: ctx.Uint64(migrationBlockNumberFlag.Name), ++type SequencerOpt func(opts *SequencerCfg) ++ ++func WithVerifierOpts(opts ...VerifierOpt) SequencerOpt { ++ return func(cfg *SequencerCfg) { ++ for _, opt := range opts { ++ opt(&cfg.VerifierCfg) ++ } + } ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+124
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/actions/interop/interop_test.go CELO/op-e2e/actions/interop/interop_test.go +new file mode 100644 +index 0000000000000000000000000000000000000000..4015ffa29ce956afb33d111fc8476309760e503a +--- /dev/null ++++ CELO/op-e2e/actions/interop/interop_test.go +@@ -0,0 +1,124 @@ ++package interop ++ ++import ( ++ "testing" ++ ++ "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" ++ "github.com/stretchr/testify/require" ++ ++ "github.com/ethereum/go-ethereum/log" ++ ++ "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" ++ "github.com/ethereum-optimism/optimism/op-node/rollup/interop" ++ "github.com/ethereum-optimism/optimism/op-node/rollup/sync" ++ "github.com/ethereum-optimism/optimism/op-service/testlog" ++ "github.com/ethereum-optimism/optimism/op-service/testutils" ++ "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" ++) ++ ++var _ interop.InteropBackend = (*testutils.MockInteropBackend)(nil) ++ ++func TestInteropVerifier(gt *testing.T) { ++ t := helpers.NewDefaultTesting(gt) ++ dp := e2eutils.MakeDeployParams(t, helpers.DefaultRollupTestParams) ++ sd := e2eutils.Setup(t, dp, helpers.DefaultAlloc) ++ // Temporary work-around: interop needs to be active, for cross-safety to not be instant. ++ // The state genesis in this test is pre-interop however. ++ sd.RollupCfg.InteropTime = new(uint64) ++ logger := testlog.Logger(t, log.LevelDebug) ++ seqMockBackend := &testutils.MockInteropBackend{} ++ l1Miner, seqEng, seq := helpers.SetupSequencerTest(t, sd, logger, ++ helpers.WithVerifierOpts(helpers.WithInteropBackend(seqMockBackend))) ++ ++ batcher := helpers.NewL2Batcher(logger, sd.RollupCfg, helpers.DefaultBatcherCfg(dp), ++ seq.RollupClient(), l1Miner.EthClient(), seqEng.EthClient(), seqEng.EngineClient(t, sd.RollupCfg)) ++ ++ verMockBackend := &testutils.MockInteropBackend{} ++ _, ver := helpers.SetupVerifier(t, sd, logger, ++ l1Miner.L1Client(t, sd.RollupCfg), l1Miner.BlobStore(), &sync.Config{}, ++ helpers.WithInteropBackend(verMockBackend)) ++ ++ seq.ActL2PipelineFull(t) ++ ver.ActL2PipelineFull(t) ++ ++ l2ChainID := types.ChainIDFromBig(sd.RollupCfg.L2ChainID) ++ seqMockBackend.ExpectCheckBlock(l2ChainID, 1, types.Unsafe, nil) ++ // create an unsafe L2 block ++ seq.ActL2StartBlock(t) ++ seq.ActL2EndBlock(t) ++ seq.ActL2PipelineFull(t) ++ seqMockBackend.AssertExpectations(t) ++ status := seq.SyncStatus() ++ require.Equal(t, uint64(1), status.UnsafeL2.Number) ++ require.Equal(t, uint64(0), status.CrossUnsafeL2.Number) ++ require.Equal(t, uint64(0), status.LocalSafeL2.Number) ++ require.Equal(t, uint64(0), status.SafeL2.Number) ++ ++ // promote it to cross-unsafe in the backend ++ // and see if the node picks up on it ++ seqMockBackend.ExpectCheckBlock(l2ChainID, 1, types.CrossUnsafe, nil) ++ seq.ActInteropBackendCheck(t) ++ seq.ActL2PipelineFull(t) ++ seqMockBackend.AssertExpectations(t) ++ status = seq.SyncStatus() ++ require.Equal(t, uint64(1), status.UnsafeL2.Number) ++ require.Equal(t, uint64(1), status.CrossUnsafeL2.Number, "cross unsafe now") ++ require.Equal(t, uint64(0), status.LocalSafeL2.Number) ++ require.Equal(t, uint64(0), status.SafeL2.Number) ++ ++ // submit all new L2 blocks ++ batcher.ActSubmitAll(t) ++ // new L1 block with L2 batch ++ l1Miner.ActL1StartBlock(12)(t) ++ l1Miner.ActL1IncludeTx(sd.RollupCfg.Genesis.SystemConfig.BatcherAddr)(t) ++ l1Miner.ActL1EndBlock(t) ++ ++ // Sync the L1 block, to verify the L2 block as local-safe. ++ seqMockBackend.ExpectCheckBlock(l2ChainID, 1, types.CrossUnsafe, nil) // not cross-safe yet ++ seq.ActL1HeadSignal(t) ++ seq.ActL2PipelineFull(t) ++ seqMockBackend.AssertExpectations(t) ++ ++ status = seq.SyncStatus() ++ require.Equal(t, uint64(1), status.UnsafeL2.Number) ++ require.Equal(t, uint64(1), status.CrossUnsafeL2.Number) ++ require.Equal(t, uint64(1), status.LocalSafeL2.Number, "local safe changed") ++ require.Equal(t, uint64(0), status.SafeL2.Number) ++ ++ // Now mark it as cross-safe ++ seqMockBackend.ExpectCheckBlock(l2ChainID, 1, types.CrossSafe, nil) ++ seq.ActInteropBackendCheck(t) ++ seq.ActL2PipelineFull(t) ++ seqMockBackend.AssertExpectations(t) ++ ++ status = seq.SyncStatus() ++ require.Equal(t, uint64(1), status.UnsafeL2.Number) ++ require.Equal(t, uint64(1), status.CrossUnsafeL2.Number) ++ require.Equal(t, uint64(1), status.LocalSafeL2.Number) ++ require.Equal(t, uint64(1), status.SafeL2.Number, "cross-safe reached") ++ require.Equal(t, uint64(0), status.FinalizedL2.Number) ++ ++ // The verifier might not see the L2 block that was just derived from L1 as cross-verified yet. ++ verMockBackend.ExpectCheckBlock(l2ChainID, 1, types.Unsafe, nil) // for the local unsafe check ++ verMockBackend.ExpectCheckBlock(l2ChainID, 1, types.Unsafe, nil) // for the local safe check ++ ver.ActL1HeadSignal(t) ++ ver.ActL2PipelineFull(t) ++ verMockBackend.AssertExpectations(t) ++ status = ver.SyncStatus() ++ require.Equal(t, uint64(1), status.UnsafeL2.Number, "synced the block") ++ require.Equal(t, uint64(0), status.CrossUnsafeL2.Number, "not cross-verified yet") ++ require.Equal(t, uint64(1), status.LocalSafeL2.Number, "derived from L1, thus local-safe") ++ require.Equal(t, uint64(0), status.SafeL2.Number, "not yet cross-safe") ++ require.Equal(t, uint64(0), status.FinalizedL2.Number) ++ ++ // signal that L1 finalized; the cross-safe block we have should get finalized too ++ l1Miner.ActL1SafeNext(t) ++ l1Miner.ActL1FinalizeNext(t) ++ seq.ActL1SafeSignal(t) ++ seq.ActL1FinalizedSignal(t) ++ seq.ActL2PipelineFull(t) ++ seqMockBackend.AssertExpectations(t) ++ ++ status = seq.SyncStatus() ++ require.Equal(t, uint64(1), status.FinalizedL2.Number, "finalized the block") ++}
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + (deleted) + +
+
+
+ +
+ +
+ +
+0
+
-118
+ +
+ +
+
+
diff --git OP/op-e2e/actions/l2_verifier_test.go CELO/op-e2e/actions/l2_verifier_test.go +deleted file mode 100644 +index 328801214e04aa7c1f050b41c1ad00317ce2468e..0000000000000000000000000000000000000000 +--- OP/op-e2e/actions/l2_verifier_test.go ++++ /dev/null +@@ -1,118 +0,0 @@ +-package actions +- +-import ( +- "testing" +- +- altda "github.com/ethereum-optimism/optimism/op-alt-da" +- "github.com/ethereum-optimism/optimism/op-node/node/safedb" +- "github.com/ethereum/go-ethereum/common" +- "github.com/ethereum/go-ethereum/log" +- "github.com/stretchr/testify/require" +- +- "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" +- "github.com/ethereum-optimism/optimism/op-node/rollup/derive" +- "github.com/ethereum-optimism/optimism/op-node/rollup/sync" +- "github.com/ethereum-optimism/optimism/op-service/testlog" +-) +- +-type verifierCfg struct { +- safeHeadListener safeDB +-} +- +-type VerifierOpt func(opts *verifierCfg) +- +-func WithSafeHeadListener(l safeDB) VerifierOpt { +- return func(opts *verifierCfg) { +- opts.safeHeadListener = l +- } +-} +- +-func defaultVerifierCfg() *verifierCfg { +- return &verifierCfg{ +- safeHeadListener: safedb.Disabled, +- } +-} +- +-func setupVerifier(t Testing, sd *e2eutils.SetupData, log log.Logger, l1F derive.L1Fetcher, blobSrc derive.L1BlobsFetcher, syncCfg *sync.Config, opts ...VerifierOpt) (*L2Engine, *L2Verifier) { +- cfg := defaultVerifierCfg() +- for _, opt := range opts { +- opt(cfg) +- } +- jwtPath := e2eutils.WriteDefaultJWT(t) +- engine := NewL2Engine(t, log.New("role", "verifier-engine"), sd.L2Cfg, sd.RollupCfg.Genesis.L1, jwtPath, EngineWithP2P()) +- engCl := engine.EngineClient(t, sd.RollupCfg) +- verifier := NewL2Verifier(t, log.New("role", "verifier"), l1F, blobSrc, altda.Disabled, engCl, sd.RollupCfg, syncCfg, cfg.safeHeadListener) +- return engine, verifier +-} +- +-func setupVerifierOnlyTest(t Testing, sd *e2eutils.SetupData, log log.Logger) (*L1Miner, *L2Engine, *L2Verifier) { +- miner := NewL1Miner(t, log, sd.L1Cfg) +- l1Cl := miner.L1Client(t, sd.RollupCfg) +- engine, verifier := setupVerifier(t, sd, log, l1Cl, miner.BlobStore(), &sync.Config{}) +- return miner, engine, verifier +-} +- +-func TestL2Verifier_SequenceWindow(gt *testing.T) { +- t := NewDefaultTesting(gt) +- p := &e2eutils.TestParams{ +- MaxSequencerDrift: 10, +- SequencerWindowSize: 24, +- ChannelTimeout: 10, +- L1BlockTime: 15, +- } +- dp := e2eutils.MakeDeployParams(t, p) +- sd := e2eutils.Setup(t, dp, defaultAlloc) +- log := testlog.Logger(t, log.LevelDebug) +- miner, engine, verifier := setupVerifierOnlyTest(t, sd, log) +- miner.ActL1SetFeeRecipient(common.Address{'A'}) +- +- // Make two sequence windows worth of empty L1 blocks. After we pass the first sequence window, the L2 chain should get blocks +- for miner.l1Chain.CurrentBlock().Number.Uint64() < sd.RollupCfg.SeqWindowSize*2 { +- miner.ActL1StartBlock(10)(t) +- miner.ActL1EndBlock(t) +- +- verifier.ActL2PipelineFull(t) +- +- l1Head := miner.l1Chain.CurrentBlock().Number.Uint64() +- expectedL1Origin := uint64(0) +- // as soon as we complete the sequence window, we force-adopt the L1 origin +- if l1Head >= sd.RollupCfg.SeqWindowSize { +- expectedL1Origin = l1Head - sd.RollupCfg.SeqWindowSize +- } +- require.Equal(t, expectedL1Origin, verifier.SyncStatus().SafeL2.L1Origin.Number, "L1 origin is forced in, given enough L1 blocks pass by") +- require.LessOrEqual(t, miner.l1Chain.GetBlockByNumber(expectedL1Origin).Time(), engine.l2Chain.CurrentBlock().Time, "L2 time higher than L1 origin time") +- } +- tip2N := verifier.SyncStatus() +- +- // Do a deep L1 reorg as deep as a sequence window, this should affect the safe L2 chain +- miner.ActL1RewindDepth(sd.RollupCfg.SeqWindowSize)(t) +- +- // Without new L1 block, the L1 appears to not be synced, and the node shouldn't reorg +- verifier.ActL2PipelineFull(t) +- require.Equal(t, tip2N.SafeL2, verifier.SyncStatus().SafeL2, "still the same after verifier work") +- +- // Make a new empty L1 block with different data than there was before. +- miner.ActL1SetFeeRecipient(common.Address{'B'}) +- miner.ActL1StartBlock(10)(t) +- miner.ActL1EndBlock(t) +- reorgL1Block := miner.l1Chain.CurrentBlock() +- +- // Still no reorg, we need more L1 blocks first, before the reorged L1 block is forced in by sequence window +- verifier.ActL2PipelineFull(t) +- require.Equal(t, tip2N.SafeL2, verifier.SyncStatus().SafeL2) +- +- for miner.l1Chain.CurrentBlock().Number.Uint64() < sd.RollupCfg.SeqWindowSize*2 { +- miner.ActL1StartBlock(10)(t) +- miner.ActL1EndBlock(t) +- } +- +- // workaround: in L1Traversal we only recognize the reorg once we see origin N+1, we don't reorg to shorter L1 chains +- miner.ActL1StartBlock(10)(t) +- miner.ActL1EndBlock(t) +- +- // Now it will reorg +- verifier.ActL2PipelineFull(t) +- +- got := miner.l1Chain.GetBlockByHash(miner.l1Chain.GetBlockByHash(verifier.SyncStatus().SafeL2.L1Origin.Hash).Hash()) +- require.Equal(t, reorgL1Block.Hash(), got.Hash(), "must have reorged L2 chain to the new L1 chain") +-}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+174
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/actions/proofs/bad_tx_in_batch_test.go CELO/op-e2e/actions/proofs/bad_tx_in_batch_test.go +new file mode 100644 +index 0000000000000000000000000000000000000000..f67e216f76cb0554a26787d1e77608a38f41d03f +--- /dev/null ++++ CELO/op-e2e/actions/proofs/bad_tx_in_batch_test.go +@@ -0,0 +1,174 @@ ++package proofs ++ ++import ( ++ "testing" ++ ++ actionsHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" ++ "github.com/ethereum-optimism/optimism/op-e2e/actions/proofs/helpers" ++ "github.com/ethereum-optimism/optimism/op-program/client/claim" ++ "github.com/ethereum/go-ethereum/common" ++ "github.com/ethereum/go-ethereum/core/types" ++ "github.com/stretchr/testify/require" ++) ++ ++func runBadTxInBatchTest(gt *testing.T, testCfg *helpers.TestCfg[any]) { ++ t := actionsHelpers.NewDefaultTesting(gt) ++ env := helpers.NewL2FaultProofEnv(t, testCfg, helpers.NewTestParams(), helpers.NewBatcherCfg()) ++ ++ // Build a block on L2 with 1 tx. ++ env.Alice.L2.ActResetTxOpts(t) ++ env.Alice.L2.ActSetTxToAddr(&env.Dp.Addresses.Bob) ++ env.Alice.L2.ActMakeTx(t) ++ ++ env.Sequencer.ActL2StartBlock(t) ++ env.Engine.ActL2IncludeTx(env.Alice.Address())(t) ++ env.Sequencer.ActL2EndBlock(t) ++ env.Alice.L2.ActCheckReceiptStatusOfLastTx(true)(t) ++ ++ // Instruct the batcher to submit a faulty channel, with an invalid tx. ++ err := env.Batcher.Buffer(t, func(block *types.Block) { ++ // Replace the tx with one that has a bad signature. ++ txs := block.Transactions() ++ newTx, err := txs[1].WithSignature(env.Alice.L2.Signer(), make([]byte, 65)) ++ txs[1] = newTx ++ require.NoError(t, err) ++ }) ++ require.NoError(t, err) ++ env.Batcher.ActL2ChannelClose(t) ++ env.Batcher.ActL2BatchSubmit(t) ++ ++ // Include the batcher transaction. ++ env.Miner.ActL1StartBlock(12)(t) ++ env.Miner.ActL1IncludeTxByHash(env.Batcher.LastSubmitted.Hash())(t) ++ env.Miner.ActL1EndBlock(t) ++ env.Miner.ActL1SafeNext(t) ++ ++ // Instruct the sequencer to derive the L2 chain from the data on L1 that the batcher just posted. ++ env.Sequencer.ActL1HeadSignal(t) ++ env.Sequencer.ActL2PipelineFull(t) ++ ++ // Ensure the safe head has not advanced - the batch is invalid. ++ l2SafeHead := env.Engine.L2Chain().CurrentSafeBlock() ++ require.Equal(t, uint64(0), l2SafeHead.Number.Uint64()) ++ ++ // Reset the batcher and submit a valid batch. ++ env.Batcher.Reset() ++ env.Batcher.ActSubmitAll(t) ++ env.Miner.ActL1StartBlock(12)(t) ++ env.Miner.ActL1IncludeTxByHash(env.Batcher.LastSubmitted.Hash())(t) ++ env.Miner.ActL1EndBlock(t) ++ env.Miner.ActL1SafeNext(t) ++ ++ // Instruct the sequencer to derive the L2 chain from the data on L1 that the batcher just posted. ++ env.Sequencer.ActL1HeadSignal(t) ++ env.Sequencer.ActL2PipelineFull(t) ++ ++ // Ensure the safe head has advanced. ++ l1Head := env.Miner.L1Chain().CurrentBlock() ++ l2SafeHead = env.Engine.L2Chain().CurrentSafeBlock() ++ require.Equal(t, uint64(2), l1Head.Number.Uint64()) ++ require.Equal(t, uint64(1), l2SafeHead.Number.Uint64()) ++ ++ env.RunFaultProofProgram(t, l2SafeHead.Number.Uint64(), testCfg.CheckResult, testCfg.InputParams...) +} + -+func main() { ++func runBadTxInBatch_ResubmitBadFirstFrame_Test(gt *testing.T, testCfg *helpers.TestCfg[any]) { ++ t := actionsHelpers.NewDefaultTesting(gt) ++ env := helpers.NewL2FaultProofEnv(t, testCfg, helpers.NewTestParams(), helpers.NewBatcherCfg()) + -+ color := isatty.IsTerminal(os.Stderr.Fd()) -+ handler := log.NewTerminalHandlerWithLevel(os.Stderr, slog.LevelInfo, color) -+ oplog.SetGlobalLogHandler(handler) ++ // Build 2 blocks on L2 with 1 tx each. ++ for i := 0; i < 2; i++ { ++ env.Alice.L2.ActResetTxOpts(t) ++ env.Alice.L2.ActSetTxToAddr(&env.Dp.Addresses.Bob) ++ env.Alice.L2.ActMakeTx(t) + -+ app := &cli.App{ -+ Name: "celo-migrate", -+ Usage: "Migrate Celo block and state data to a CeL2 DB", -+ Commands: []*cli.Command{ -+ { -+ Name: "pre", -+ Usage: "Perform a pre-migration of ancient blocks and copy over all other data without transforming it. This should be run a day before the full migration command is run to minimize downtime.", -+ Flags: preMigrationFlags, -+ Action: func(ctx *cli.Context) error { -+ if _, _, err := runPreMigration(parsePreMigrationOptions(ctx)); err != nil { -+ return fmt.Errorf("failed to run pre-migration: %w", err) -+ } -+ log.Info("Finished pre migration successfully!") -+ return nil -+ }, -+ }, -+ { -+ Name: "full", -+ Usage: "Perform a full migration of both block and state data to a CeL2 DB", -+ Flags: fullMigrationFlags, -+ Action: func(ctx *cli.Context) error { -+ if err := runFullMigration(parseFullMigrationOptions(ctx)); err != nil { -+ return fmt.Errorf("failed to run full migration: %w", err) -+ } -+ log.Info("Finished full migration successfully!") -+ return nil -+ }, -+ }, -+ }, -+ OnUsageError: func(ctx *cli.Context, err error, isSubcommand bool) error { -+ if isSubcommand { -+ return err -+ } -+ _ = cli.ShowAppHelp(ctx) -+ return fmt.Errorf("please provide a valid command") -+ }, ++ env.Sequencer.ActL2StartBlock(t) ++ env.Engine.ActL2IncludeTx(env.Alice.Address())(t) ++ env.Sequencer.ActL2EndBlock(t) ++ env.Alice.L2.ActCheckReceiptStatusOfLastTx(true)(t) + } + -+ if err := app.Run(os.Args); err != nil { -+ log.Crit("error in migration", "err", err) -+ } ++ // Instruct the batcher to submit a faulty channel, with an invalid tx in the second block ++ // within the span batch. ++ env.Batcher.ActL2BatchBuffer(t) ++ err := env.Batcher.Buffer(t, func(block *types.Block) { ++ // Replace the tx with one that has a bad signature. ++ txs := block.Transactions() ++ newTx, err := txs[1].WithSignature(env.Alice.L2.Signer(), make([]byte, 65)) ++ txs[1] = newTx ++ require.NoError(t, err) ++ }) ++ require.NoError(t, err) ++ env.Batcher.ActL2ChannelClose(t) ++ env.Batcher.ActL2BatchSubmit(t) ++ ++ // Include the batcher transaction. ++ env.Miner.ActL1StartBlock(12)(t) ++ env.Miner.ActL1IncludeTxByHash(env.Batcher.LastSubmitted.Hash())(t) ++ env.Miner.ActL1EndBlock(t) ++ env.Miner.ActL1SafeNext(t) ++ ++ // Instruct the sequencer to derive the L2 chain from the data on L1 that the batcher just posted. ++ env.Sequencer.ActL1HeadSignal(t) ++ env.Sequencer.ActL2PipelineFull(t) ++ ++ // Ensure the safe head has not advanced - the batch is invalid. ++ l2SafeHead := env.Engine.L2Chain().CurrentSafeBlock() ++ require.Equal(t, uint64(0), l2SafeHead.Number.Uint64()) ++ ++ // Reset the batcher and submit a valid batch. ++ env.Batcher.Reset() ++ env.Batcher.ActSubmitAll(t) ++ env.Miner.ActL1StartBlock(12)(t) ++ env.Miner.ActL1IncludeTxByHash(env.Batcher.LastSubmitted.Hash())(t) ++ env.Miner.ActL1EndBlock(t) ++ env.Miner.ActL1SafeNext(t) ++ ++ // Instruct the sequencer to derive the L2 chain from the data on L1 that the batcher just posted. ++ env.Sequencer.ActL1HeadSignal(t) ++ env.Sequencer.ActL2PipelineFull(t) ++ ++ // Ensure the safe head has advanced. ++ l1Head := env.Miner.L1Chain().CurrentBlock() ++ l2SafeHead = env.Engine.L2Chain().CurrentSafeBlock() ++ require.Equal(t, uint64(2), l1Head.Number.Uint64()) ++ require.Equal(t, uint64(2), l2SafeHead.Number.Uint64()) ++ ++ env.RunFaultProofProgram(t, l2SafeHead.Number.Uint64()-1, testCfg.CheckResult, testCfg.InputParams...) +} + -+func runFullMigration(opts fullMigrationOptions) error { -+ defer timer("full migration")() ++func Test_ProgramAction_BadTxInBatch(gt *testing.T) { ++ matrix := helpers.NewMatrix[any]() ++ defer matrix.Run(gt) ++ ++ matrix.AddTestCase( ++ "HonestClaim", ++ nil, ++ helpers.LatestForkOnly, ++ runBadTxInBatchTest, ++ helpers.ExpectNoError(), ++ ) ++ matrix.AddTestCase( ++ "JunkClaim", ++ nil, ++ helpers.LatestForkOnly, ++ runBadTxInBatchTest, ++ helpers.ExpectError(claim.ErrClaimNotValid), ++ helpers.WithL2Claim(common.HexToHash("0xdeadbeef")), ++ ) ++ matrix.AddTestCase( ++ "ResubmitBadFirstFrame-HonestClaim", ++ nil, ++ helpers.LatestForkOnly, ++ runBadTxInBatch_ResubmitBadFirstFrame_Test, ++ helpers.ExpectNoError(), ++ ) ++ matrix.AddTestCase( ++ "ResubmitBadFirstFrame-JunkClaim", ++ nil, ++ helpers.LatestForkOnly, ++ runBadTxInBatch_ResubmitBadFirstFrame_Test, ++ helpers.ExpectError(claim.ErrClaimNotValid), ++ helpers.WithL2Claim(common.HexToHash("0xdeadbeef")), ++ ) ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+250
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/actions/proofs/channel_timeout_test.go CELO/op-e2e/actions/proofs/channel_timeout_test.go +new file mode 100644 +index 0000000000000000000000000000000000000000..09ff333922abf4e0d7bc428197e49ed3d280473e +--- /dev/null ++++ CELO/op-e2e/actions/proofs/channel_timeout_test.go +@@ -0,0 +1,250 @@ ++package proofs ++ ++import ( ++ "testing" + -+ log.Info("Full Migration Started", "oldDBPath", opts.oldDBPath, "newDBPath", opts.newDBPath) ++ actionsHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" ++ "github.com/ethereum-optimism/optimism/op-e2e/actions/proofs/helpers" ++ "github.com/ethereum-optimism/optimism/op-program/client/claim" ++ "github.com/ethereum/go-ethereum/common" ++ "github.com/stretchr/testify/require" ++) + -+ head, err := getHeadHeader(opts.oldDBPath) -+ if err != nil { -+ return fmt.Errorf("failed to get head header: %w", err) -+ } -+ if head.Number.Uint64() != opts.migrationBlockNumber-1 { -+ return fmt.Errorf("old-db head block number not synced to the block immediately before the migration block number: %d != %d", head.Number.Uint64(), opts.migrationBlockNumber-1) -+ } ++// Run a test that submits the first channel frame, times out the channel, and then resubmits the full channel. ++func runChannelTimeoutTest(gt *testing.T, testCfg *helpers.TestCfg[any]) { ++ t := actionsHelpers.NewDefaultTesting(gt) ++ tp := helpers.NewTestParams() ++ env := helpers.NewL2FaultProofEnv(t, testCfg, tp, helpers.NewBatcherCfg()) ++ channelTimeout := env.Sd.ChainSpec.ChannelTimeout(0) + -+ log.Info("Source db is synced to correct height", "head", head.Number.Uint64(), "migrationBlock", opts.migrationBlockNumber) ++ var timedOutChannels uint ++ env.Sequencer.DerivationMetricsTracer().FnRecordChannelTimedOut = func() { ++ timedOutChannels++ ++ } + -+ var numAncients uint64 -+ var strayAncientBlocks []*rawdb.NumberHash ++ const NumL2Blocks = 10 + -+ if strayAncientBlocks, numAncients, err = runPreMigration(opts.preMigrationOptions); err != nil { -+ return fmt.Errorf("failed to run pre-migration: %w", err) ++ // Build NumL2Blocks empty blocks on L2 ++ for i := 0; i < NumL2Blocks; i++ { ++ env.Sequencer.ActL2StartBlock(t) ++ env.Sequencer.ActL2EndBlock(t) + } + -+ if err = runNonAncientMigration(opts.newDBPath, strayAncientBlocks, opts.batchSize, numAncients); err != nil { -+ return fmt.Errorf("failed to run non-ancient migration: %w", err) -+ } -+ if err = runStateMigration(opts.newDBPath, opts.stateMigrationOptions); err != nil { -+ return fmt.Errorf("failed to run state migration: %w", err) ++ // Buffer the first half of L2 blocks in the batcher, and submit it. ++ for i := 0; i < NumL2Blocks/2; i++ { ++ env.Batcher.ActL2BatchBuffer(t) + } ++ firstFrame := env.Batcher.ReadNextOutputFrame(t) ++ env.Batcher.ActL2BatchSubmitRaw(t, firstFrame) + -+ log.Info("Full Migration Finished", "oldDBPath", opts.oldDBPath, "newDBPath", opts.newDBPath) ++ // Include the batcher transaction. ++ env.Miner.ActL1StartBlock(12)(t) ++ env.Miner.ActL1IncludeTxByHash(env.Batcher.LastSubmitted.Hash())(t) ++ env.Miner.ActL1EndBlock(t) + -+ return nil -+} ++ // Finalize the block with the first channel frame on L1. ++ env.Miner.ActL1SafeNext(t) + -+func runPreMigration(opts preMigrationOptions) ([]*rawdb.NumberHash, uint64, error) { -+ defer timer("pre-migration")() ++ // Instruct the sequencer to derive the L2 chain from the data on L1 that the batcher just posted. ++ env.Sequencer.ActL1HeadSignal(t) ++ env.Sequencer.ActL2PipelineFull(t) + -+ log.Info("Pre-Migration Started", "oldDBPath", opts.oldDBPath, "newDBPath", opts.newDBPath, "batchSize", opts.batchSize, "memoryLimit", opts.memoryLimit) ++ // Ensure that the safe head has not advanced - the channel is incomplete. ++ l2SafeHead := env.Engine.L2Chain().CurrentSafeBlock() ++ require.Equal(t, uint64(0), l2SafeHead.Number.Uint64()) + -+ // Check that `rsync` command is available. We use this to copy the db excluding ancients, which we will copy separately -+ if _, err := exec.LookPath("rsync"); err != nil { -+ return nil, 0, fmt.Errorf("please install `rsync` to run block migration") ++ // Time out the channel by mining `channelTimeout + 1` empty blocks on L1. ++ for i := uint64(0); i < channelTimeout+1; i++ { ++ env.Miner.ActEmptyBlock(t) ++ env.Miner.ActL1SafeNext(t) + } + -+ debug.SetMemoryLimit(opts.memoryLimit * 1 << 20) // Set memory limit, converting from MiB to bytes ++ // Instruct the sequencer to derive the L2 chain - the channel should now be timed out. ++ env.Sequencer.ActL1HeadSignal(t) ++ env.Sequencer.ActL2PipelineFull(t) + -+ var err error ++ // Ensure the safe head has still not advanced. ++ l2SafeHead = env.Engine.L2Chain().CurrentSafeBlock() ++ require.Equal(t, uint64(0), l2SafeHead.Number.Uint64()) + -+ if err = createNewDbPathIfNotExists(opts.newDBPath); err != nil { -+ return nil, 0, fmt.Errorf("failed to create new db path: %w", err) -+ } ++ // Ensure that the channel was timed out. ++ require.EqualValues(t, 1, timedOutChannels) + -+ if opts.resetNonAncients { -+ if err = cleanupNonAncientDb(opts.newDBPath); err != nil { -+ return nil, 0, fmt.Errorf("failed to cleanup non-ancient db: %w", err) ++ // Instruct the batcher to submit the blocks to L1 in a new channel, ++ // submitted across 2 transactions. ++ for i := 0; i < 2; i++ { ++ if i == 0 { ++ // Re-submit the first frame ++ env.Batcher.ActL2BatchSubmitRaw(t, firstFrame) ++ } else { ++ // Buffer half of the L2 chain's blocks. ++ for j := 0; j < NumL2Blocks/2; j++ { ++ env.Batcher.ActL2BatchBuffer(t) ++ } ++ env.Batcher.ActL2ChannelClose(t) ++ env.Batcher.ActL2BatchSubmit(t) + } -+ } + -+ var numAncientsNewBefore uint64 -+ var numAncientsNewAfter uint64 -+ var strayAncientBlocks []*rawdb.NumberHash -+ g, ctx := errgroup.WithContext(context.Background()) -+ g.Go(func() error { -+ if numAncientsNewBefore, numAncientsNewAfter, err = migrateAncientsDb(ctx, opts.oldDBPath, opts.newDBPath, opts.batchSize, opts.bufferSize); err != nil { -+ return fmt.Errorf("failed to migrate ancients database: %w", err) -+ } -+ // Scanning for stray ancient blocks is slow, so we do it as soon as we can after the lock on oldDB is released by migrateAncientsDb -+ // Doing this in parallel with copyDbExceptAncients still saves time if ancients have already been pre-migrated -+ if strayAncientBlocks, err = getStrayAncientBlocks(opts.oldDBPath); err != nil { -+ return fmt.Errorf("failed to get stray ancient blocks: %w", err) -+ } -+ return nil -+ }) -+ g.Go(func() error { -+ // By doing this once during the premigration, we get a speedup when we run it again in a full migration. -+ return copyDbExceptAncients(opts.oldDBPath, opts.newDBPath) -+ }) ++ env.Miner.ActL1StartBlock(12)(t) ++ env.Miner.ActL1IncludeTxByHash(env.Batcher.LastSubmitted.Hash())(t) ++ env.Miner.ActL1EndBlock(t) + -+ if err = g.Wait(); err != nil { -+ return nil, 0, fmt.Errorf("failed to migrate blocks: %w", err) ++ // Finalize the block with the frame data on L1. ++ env.Miner.ActL1SafeNext(t) + } + -+ log.Info("Pre-Migration Finished", "oldDBPath", opts.oldDBPath, "newDBPath", opts.newDBPath, "migratedAncients", numAncientsNewAfter-numAncientsNewBefore, "strayAncientBlocks", len(strayAncientBlocks)) ++ // Instruct the sequencer to derive the L2 chain. ++ env.Sequencer.ActL1HeadSignal(t) ++ env.Sequencer.ActL2PipelineFull(t) + -+ return strayAncientBlocks, numAncientsNewAfter, nil ++ // Ensure the safe head has still advanced to L2 block # NumL2Blocks. ++ l2SafeHead = env.Engine.L2Chain().CurrentSafeBlock() ++ require.EqualValues(t, NumL2Blocks, l2SafeHead.Number.Uint64()) ++ ++ // Run the FPP on L2 block # NumL2Blocks/2. ++ env.RunFaultProofProgram(t, NumL2Blocks/2, testCfg.CheckResult, testCfg.InputParams...) +} + -+func runNonAncientMigration(newDBPath string, strayAncientBlocks []*rawdb.NumberHash, batchSize, numAncients uint64) error { -+ defer timer("non-ancient migration")() ++func runChannelTimeoutTest_CloseChannelLate(gt *testing.T, testCfg *helpers.TestCfg[any]) { ++ t := actionsHelpers.NewDefaultTesting(gt) ++ tp := helpers.NewTestParams() ++ env := helpers.NewL2FaultProofEnv(t, testCfg, tp, helpers.NewBatcherCfg()) ++ channelTimeout := env.Sd.ChainSpec.ChannelTimeout(0) + -+ newDB, err := openDBWithoutFreezer(newDBPath, false) -+ if err != nil { -+ return fmt.Errorf("failed to open new database: %w", err) ++ var timedOutChannels uint ++ env.Sequencer.DerivationMetricsTracer().FnRecordChannelTimedOut = func() { ++ timedOutChannels++ + } -+ defer newDB.Close() + -+ // get the last block number -+ hash := rawdb.ReadHeadHeaderHash(newDB) -+ lastBlock := *rawdb.ReadHeaderNumber(newDB, hash) -+ lastAncient := numAncients - 1 ++ const NumL2Blocks = 10 + -+ log.Info("Non-Ancient Block Migration Started", "process", "non-ancients", "newDBPath", newDBPath, "batchSize", batchSize, "startBlock", numAncients, "endBlock", lastBlock, "count", lastBlock-lastAncient, "lastAncientBlock", lastAncient) -+ -+ var numNonAncients uint64 -+ if numNonAncients, err = migrateNonAncientsDb(newDB, lastBlock, numAncients, batchSize); err != nil { -+ return fmt.Errorf("failed to migrate non-ancients database: %w", err) ++ // Build NumL2Blocks empty blocks on L2 ++ for i := 0; i < NumL2Blocks; i++ { ++ env.Sequencer.ActL2StartBlock(t) ++ env.Sequencer.ActL2EndBlock(t) + } + -+ err = removeBlocks(newDB, strayAncientBlocks) -+ if err != nil { -+ return fmt.Errorf("failed to remove stray ancient blocks: %w", err) ++ // Buffer the first half of L2 blocks in the batcher, and submit it. ++ for i := 0; i < NumL2Blocks/2; i++ { ++ env.Batcher.ActL2BatchBuffer(t) + } -+ log.Info("Removed stray ancient blocks still in leveldb", "process", "non-ancients", "removedBlocks", len(strayAncientBlocks)) ++ firstFrame := env.Batcher.ReadNextOutputFrame(t) ++ env.Batcher.ActL2BatchSubmitRaw(t, firstFrame) + -+ log.Info("Non-Ancient Block Migration Completed", "process", "non-ancients", "migratedNonAncients", numNonAncients) ++ // Instruct the batcher to submit the first channel frame to L1, and include the transaction. ++ env.Miner.ActL1StartBlock(12)(t) ++ env.Miner.ActL1IncludeTxByHash(env.Batcher.LastSubmitted.Hash())(t) ++ env.Miner.ActL1EndBlock(t) + -+ return nil -+} ++ // Finalize the block with the first channel frame on L1. ++ env.Miner.ActL1SafeNext(t) + -+func runStateMigration(newDBPath string, opts stateMigrationOptions) error { -+ defer timer("state migration")() ++ // Instruct the sequencer to derive the L2 chain from the data on L1 that the batcher just posted. ++ env.Sequencer.ActL1HeadSignal(t) ++ env.Sequencer.ActL2PipelineFull(t) + -+ log.Info("State Migration Started", "newDBPath", newDBPath, "deployConfig", opts.deployConfig, "l1Deployments", opts.l1Deployments, "l1RPC", opts.l1RPC, "l2AllocsPath", opts.l2AllocsPath, "outfileRollupConfig", opts.outfileRollupConfig) ++ // Ensure that the safe head has not advanced - the channel is incomplete. ++ l2SafeHead := env.Engine.L2Chain().CurrentSafeBlock() ++ require.Equal(t, uint64(0), l2SafeHead.Number.Uint64()) + -+ // Read deployment configuration -+ config, err := genesis.NewDeployConfig(opts.deployConfig) -+ if err != nil { -+ return err ++ // Time out the channel by mining `channelTimeout + 1` empty blocks on L1. ++ for i := uint64(0); i < channelTimeout+1; i++ { ++ env.Miner.ActEmptyBlock(t) ++ env.Miner.ActL1SafeNext(t) + } + -+ if config.DeployCeloContracts { -+ return errors.New("DeployCeloContracts is not supported in migration") -+ } -+ if config.FundDevAccounts { -+ return errors.New("FundDevAccounts is not supported in migration") -+ } ++ // Instruct the sequencer to derive the L2 chain. ++ env.Sequencer.ActL1HeadSignal(t) ++ env.Sequencer.ActL2PipelineFull(t) + -+ // Try reading the L1 deployment information -+ deployments, err := genesis.NewL1Deployments(opts.l1Deployments) -+ if err != nil { -+ return fmt.Errorf("cannot read L1 deployments at %s: %w", opts.l1Deployments, err) -+ } -+ config.SetDeployments(deployments) ++ // Ensure the safe head has still not advanced. ++ l2SafeHead = env.Engine.L2Chain().CurrentSafeBlock() ++ require.Equal(t, uint64(0), l2SafeHead.Number.Uint64()) + -+ // Get latest block information from L1 -+ var l1StartBlock *types.Block -+ client, err := ethclient.Dial(opts.l1RPC) -+ if err != nil { -+ return fmt.Errorf("cannot dial %s: %w", opts.l1RPC, err) -+ } ++ // Ensure that the channel was timed out. ++ require.EqualValues(t, 1, timedOutChannels) + -+ if config.L1StartingBlockTag == nil { -+ l1StartBlock, err = client.BlockByNumber(context.Background(), nil) -+ if err != nil { -+ return fmt.Errorf("cannot fetch latest block: %w", err) -+ } -+ tag := rpc.BlockNumberOrHashWithHash(l1StartBlock.Hash(), true) -+ config.L1StartingBlockTag = (*genesis.MarshalableRPCBlockNumberOrHash)(&tag) -+ } else if config.L1StartingBlockTag.BlockHash != nil { -+ l1StartBlock, err = client.BlockByHash(context.Background(), *config.L1StartingBlockTag.BlockHash) -+ if err != nil { -+ return fmt.Errorf("cannot fetch block by hash: %w", err) -+ } -+ } else if config.L1StartingBlockTag.BlockNumber != nil { -+ l1StartBlock, err = client.BlockByNumber(context.Background(), big.NewInt(config.L1StartingBlockTag.BlockNumber.Int64())) -+ if err != nil { -+ return fmt.Errorf("cannot fetch block by number: %w", err) -+ } ++ // Cache the second and final frame of the channel from the batcher, but do not submit it yet. ++ for i := 0; i < NumL2Blocks/2; i++ { ++ env.Batcher.ActL2BatchBuffer(t) + } ++ env.Batcher.ActL2ChannelClose(t) ++ finalFrame := env.Batcher.ReadNextOutputFrame(t) + -+ // Ensure that there is a starting L1 block -+ if l1StartBlock == nil { -+ return fmt.Errorf("no starting L1 block") -+ } ++ // Submit the final frame of the timed out channel, now that the channel has timed out. ++ env.Batcher.ActL2BatchSubmitRaw(t, finalFrame) + -+ // Sanity check the config. Do this after filling in the L1StartingBlockTag -+ // if it is not defined. -+ if err := config.Check(log.New()); err != nil { -+ return err -+ } ++ // Instruct the batcher to submit the second channel frame to L1, and include the transaction. ++ env.Miner.ActL1StartBlock(12)(t) ++ env.Miner.ActL1IncludeTxByHash(env.Batcher.LastSubmitted.Hash())(t) ++ env.Miner.ActL1EndBlock(t) + -+ log.Info("Using L1 Start Block", "number", l1StartBlock.Number(), "hash", l1StartBlock.Hash().Hex()) ++ // Finalize the block with the second channel frame on L1. ++ env.Miner.ActL1SafeNext(t) + -+ // Build the L2 genesis block -+ l2Allocs, err := foundry.LoadForgeAllocs(opts.l2AllocsPath) -+ if err != nil { -+ return err -+ } ++ // Instruct the sequencer to derive the L2 chain from the data on L1 that the batcher just posted. ++ env.Sequencer.ActL1HeadSignal(t) ++ env.Sequencer.ActL2PipelineFull(t) + -+ l2Genesis, err := genesis.BuildL2Genesis(config, l2Allocs, l1StartBlock) -+ if err != nil { -+ return fmt.Errorf("error creating l2 genesis: %w", err) -+ } ++ // Ensure the safe head has still not advanced. ++ l2SafeHead = env.Engine.L2Chain().CurrentSafeBlock() ++ require.Equal(t, uint64(0), l2SafeHead.Number.Uint64()) + -+ // Write changes to state to actual state database -+ cel2Header, err := applyStateMigrationChanges(config, l2Genesis.Alloc, newDBPath, opts.outfileGenesis, opts.migrationBlockTime, l1StartBlock) -+ if err != nil { -+ return err -+ } -+ log.Info("Updated Cel2 state") ++ // Instruct the batcher to submit the blocks to L1 in a new channel. ++ for _, frame := range [][]byte{firstFrame, finalFrame} { ++ env.Batcher.ActL2BatchSubmitRaw(t, frame) ++ env.Miner.ActL1StartBlock(12)(t) ++ env.Miner.ActL1IncludeTxByHash(env.Batcher.LastSubmitted.Hash())(t) ++ env.Miner.ActL1EndBlock(t) + -+ rollupConfig, err := config.RollupConfig(l1StartBlock, cel2Header.Hash(), cel2Header.Number.Uint64()) -+ if err != nil { -+ return err -+ } -+ if err := rollupConfig.Check(); err != nil { -+ return fmt.Errorf("generated rollup config does not pass validation: %w", err) ++ // Finalize the block with the resubmitted channel frames on L1. ++ env.Miner.ActL1SafeNext(t) + } + -+ log.Info("Writing rollup config", "file", opts.outfileRollupConfig) -+ if err := jsonutil.WriteJSON(opts.outfileRollupConfig, rollupConfig, OutFilePerm); err != nil { -+ return err -+ } ++ // Instruct the sequencer to derive the L2 chain. ++ env.Sequencer.ActL1HeadSignal(t) ++ env.Sequencer.ActL2PipelineFull(t) + -+ log.Info("State Migration Completed") ++ // Ensure the safe head has still advanced to L2 block # NumL2Blocks. ++ l2SafeHead = env.Engine.L2Chain().CurrentSafeBlock() ++ require.EqualValues(t, NumL2Blocks, l2SafeHead.Number.Uint64()) + -+ return nil ++ // Run the FPP on L2 block # NumL2Blocks/2. ++ env.RunFaultProofProgram(t, NumL2Blocks/2, testCfg.CheckResult, testCfg.InputParams...) +} + -+func timer(name string) func() { -+ start := time.Now() -+ return func() { -+ log.Info("TIMER", "process", name, "duration", time.Since(start)) -+ } ++func Test_ProgramAction_ChannelTimeout(gt *testing.T) { ++ matrix := helpers.NewMatrix[any]() ++ defer matrix.Run(gt) ++ ++ matrix.AddTestCase( ++ "HonestClaim", ++ nil, ++ helpers.LatestForkOnly, ++ runChannelTimeoutTest, ++ helpers.ExpectNoError(), ++ ) ++ matrix.AddTestCase( ++ "JunkClaim", ++ nil, ++ helpers.LatestForkOnly, ++ runChannelTimeoutTest, ++ helpers.ExpectError(claim.ErrClaimNotValid), ++ helpers.WithL2Claim(common.HexToHash("0xdeadbeef")), ++ ) ++ matrix.AddTestCase( ++ "CloseChannelLate-HonestClaim", ++ nil, ++ helpers.LatestForkOnly, ++ runChannelTimeoutTest_CloseChannelLate, ++ helpers.ExpectNoError(), ++ ) ++ matrix.AddTestCase( ++ "CloseChannelLate-JunkClaim", ++ nil, ++ helpers.LatestForkOnly, ++ runChannelTimeoutTest_CloseChannelLate, ++ helpers.ExpectError(claim.ErrClaimNotValid), ++ helpers.WithL2Claim(common.HexToHash("0xdeadbeef")), ++ ) +}
@@ -14773,9 +64721,9 @@
@@ -14800,136 +64748,141 @@
-
+118
+
+123
-0
-
diff --git OP/op-chain-ops/cmd/celo-migrate/non-ancients.go CELO/op-chain-ops/cmd/celo-migrate/non-ancients.go +
diff --git OP/op-e2e/actions/proofs/garbage_channel_test.go CELO/op-e2e/actions/proofs/garbage_channel_test.go new file mode 100644 -index 0000000000000000000000000000000000000000..5ad184e2dd248e2387b57f986fa1a7a55f0b225b +index 0000000000000000000000000000000000000000..f112a1a71bdaacd5269c367fa89ea91ee33bd5f4 --- /dev/null -+++ CELO/op-chain-ops/cmd/celo-migrate/non-ancients.go -@@ -0,0 +1,118 @@ -+package main ++++ CELO/op-e2e/actions/proofs/garbage_channel_test.go +@@ -0,0 +1,123 @@ ++package proofs + +import ( + "fmt" -+ "os" -+ "os/exec" -+ "strings" ++ "testing" + ++ actionsHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" ++ "github.com/ethereum-optimism/optimism/op-e2e/actions/proofs/helpers" ++ "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" ++ "github.com/ethereum-optimism/optimism/op-program/client/claim" + "github.com/ethereum/go-ethereum/common" -+ "github.com/ethereum/go-ethereum/core/rawdb" -+ "github.com/ethereum/go-ethereum/ethdb" -+ "github.com/ethereum/go-ethereum/log" ++ "github.com/stretchr/testify/require" +) + -+func copyDbExceptAncients(oldDbPath, newDbPath string) error { -+ defer timer("copyDbExceptAncients")() -+ -+ log.Info("Copying files from old database (excluding ancients)", "process", "non-ancients") ++// garbageKinds is a list of garbage kinds to test. We don't use `INVALID_COMPRESSION` and `MALFORM_RLP` because ++// they submit malformed frames always, and this test models a valid channel with a single invalid frame in the ++// middle. ++var garbageKinds = []actionsHelpers.GarbageKind{ ++ actionsHelpers.STRIP_VERSION, ++ actionsHelpers.RANDOM, ++ actionsHelpers.TRUNCATE_END, ++ actionsHelpers.DIRTY_APPEND, ++} + -+ // Get rsync help output -+ cmdHelp := exec.Command("rsync", "--help") -+ output, _ := cmdHelp.CombinedOutput() ++// Run a test that submits garbage channel data in the middle of a channel. ++// ++// channel format ([]Frame): ++// [f[0 - correct] f_x[1 - bad frame] f[1 - correct]] ++func runGarbageChannelTest(gt *testing.T, testCfg *helpers.TestCfg[actionsHelpers.GarbageKind]) { ++ t := actionsHelpers.NewDefaultTesting(gt) ++ tp := helpers.NewTestParams(func(tp *e2eutils.TestParams) { ++ // Set the channel timeout to 10 blocks, 12x lower than the sequencing window. ++ tp.ChannelTimeout = 10 ++ }) ++ env := helpers.NewL2FaultProofEnv(t, testCfg, tp, helpers.NewBatcherCfg()) + -+ // Convert output to string -+ outputStr := string(output) ++ includeBatchTx := func(env *helpers.L2FaultProofEnv) { ++ // Instruct the batcher to submit the first channel frame to L1, and include the transaction. ++ env.Miner.ActL1StartBlock(12)(t) ++ env.Miner.ActL1IncludeTxByHash(env.Batcher.LastSubmitted.Hash())(t) ++ env.Miner.ActL1EndBlock(t) + -+ opts := []string{"-v", "-a", "--exclude=ancient", "--checksum", "--delete"} ++ // Finalize the block with the first channel frame on L1. ++ env.Miner.ActL1SafeNext(t) ++ env.Miner.ActL1FinalizeNext(t) + -+ // Check for supported options -+ // Prefer --info=progress2 over --progress -+ if strings.Contains(outputStr, "--info") { -+ opts = append(opts, "--info=progress2") -+ } else if strings.Contains(outputStr, "--progress") { -+ opts = append(opts, "--progress") ++ // Instruct the sequencer to derive the L2 chain from the data on L1 that the batcher just posted. ++ env.Sequencer.ActL1HeadSignal(t) ++ env.Sequencer.ActL2PipelineFull(t) + } + -+ cmd := exec.Command("rsync", append(opts, oldDbPath+"/", newDbPath)...) -+ -+ // rsync copies any file with a different timestamp or size. -+ // -+ // '--exclude=ancient' excludes the ancient directory from the copy -+ // -+ // '--delete' Tells rsync to delete extraneous files from the receiving side (ones that aren’t on the sending side) -+ // -+ // '-a' archive mode; equals -rlptgoD. It is a quick way of saying you want recursion and want to preserve almost everything, including timestamps, ownerships, permissions, etc. -+ // Timestamps are important here because they are used to determine which files are newer and should be copied over. -+ // -+ // '--whole-file' This is the default when both the source and destination are specified as local paths, which they are here (oldDbPath and newDbPath). -+ // This option disables rsync’s delta-transfer algorithm, which causes all transferred files to be sent whole. The delta-transfer algorithm is normally used when the destination is a remote system. -+ // -+ // '--checksum' This forces rsync to compare the checksums of all files to determine if they are the same. This is slows down the transfer but ensures that source and destination directories end up with the same contents (excluding /ancients). ++ const NumL2Blocks = 10 + -+ log.Info("Running rsync command", "command", cmd.String()) -+ cmd.Stdout = os.Stdout -+ cmd.Stderr = os.Stderr -+ if err := cmd.Run(); err != nil { -+ return fmt.Errorf("failed to copy old database to new database: %w", err) ++ // Build NumL2Blocks empty blocks on L2 ++ for i := 0; i < NumL2Blocks; i++ { ++ env.Sequencer.ActL2StartBlock(t) ++ env.Sequencer.ActL2EndBlock(t) + } -+ return nil -+} + -+func migrateNonAncientsDb(newDB ethdb.Database, lastBlock, numAncients, batchSize uint64) (uint64, error) { -+ defer timer("migrateNonAncientsDb")() -+ -+ // The genesis block is also migrated in the ancient db migration as it is stored in both places. -+ // The genesis block is the only block that should remain stored in the non-ancient db even after it is frozen. -+ if numAncients > 0 { -+ log.Info("Migrating genesis block in non-ancient db", "process", "non-ancients") -+ if err := migrateNonAncientBlock(0, rawdb.ReadCanonicalHash(newDB, 0), newDB); err != nil { -+ return 0, err -+ } ++ // Buffer the first half of L2 blocks in the batcher, and submit it. ++ for i := 0; i < NumL2Blocks/2; i++ { ++ env.Batcher.ActL2BatchBuffer(t) + } ++ env.Batcher.ActL2BatchSubmit(t) + -+ for i := numAncients; i <= lastBlock; i += batchSize { -+ numbersHash := rawdb.ReadAllHashesInRange(newDB, i, i+batchSize-1) ++ // Include the batcher transaction. ++ includeBatchTx(env) + -+ log.Info("Processing Block Range", "process", "non-ancients", "from", i, "to(inclusve)", i+batchSize-1, "count", len(numbersHash)) -+ for _, numberHash := range numbersHash { -+ if err := migrateNonAncientBlock(numberHash.Number, numberHash.Hash, newDB); err != nil { -+ return 0, err -+ } -+ } ++ // Ensure that the safe head has not advanced - the channel is incomplete. ++ l2SafeHead := env.Engine.L2Chain().CurrentSafeBlock() ++ require.Equal(t, uint64(0), l2SafeHead.Number.Uint64()) ++ ++ // Buffer the second half of L2 blocks in the batcher. ++ for i := 0; i < NumL2Blocks/2; i++ { ++ env.Batcher.ActL2BatchBuffer(t) + } ++ env.Batcher.ActL2ChannelClose(t) ++ expectedSecondFrame := env.Batcher.ReadNextOutputFrame(t) + -+ migratedCount := lastBlock - numAncients + 1 -+ return migratedCount, nil -+} ++ // Submit a garbage frame, modified from the expected second frame. ++ env.Batcher.ActL2BatchSubmitGarbageRaw(t, expectedSecondFrame, testCfg.Custom) ++ // Include the garbage second frame tx ++ includeBatchTx(env) + -+func migrateNonAncientBlock(number uint64, hash common.Hash, newDB ethdb.Database) error { -+ // read header and body -+ header := rawdb.ReadHeaderRLP(newDB, hash, number) -+ body := rawdb.ReadBodyRLP(newDB, hash, number) ++ // Ensure that the safe head has not advanced - the channel is incomplete. ++ l2SafeHead = env.Engine.L2Chain().CurrentSafeBlock() ++ require.Equal(t, uint64(0), l2SafeHead.Number.Uint64()) + -+ // transform header and body -+ newHeader, err := transformHeader(header) -+ if err != nil { -+ return fmt.Errorf("failed to transform header: block %d - %x: %w", number, hash, err) -+ } -+ newBody, err := transformBlockBody(body) -+ if err != nil { -+ return fmt.Errorf("failed to transform body: block %d - %x: %w", number, hash, err) -+ } ++ // Submit the correct second frame. ++ env.Batcher.ActL2BatchSubmitRaw(t, expectedSecondFrame) ++ // Include the corract second frame tx. ++ includeBatchTx(env) + -+ if yes, newHash := hasSameHash(newHeader, hash[:]); !yes { -+ log.Error("Hash mismatch", "block", number, "oldHash", hash, "newHash", newHash) -+ return fmt.Errorf("hash mismatch at block %d - %x", number, hash) -+ } ++ // Ensure that the safe head has advanced - the channel is complete. ++ l2SafeHead = env.Engine.L2Chain().CurrentSafeBlock() ++ require.Equal(t, uint64(NumL2Blocks), l2SafeHead.Number.Uint64()) + -+ // write header and body -+ batch := newDB.NewBatch() -+ rawdb.WriteBodyRLP(batch, hash, number, newBody) -+ _ = batch.Put(headerKey(number, hash), newHeader) -+ if err := batch.Write(); err != nil { -+ return fmt.Errorf("failed to write header and body: block %d - %x: %w", number, hash, err) -+ } ++ // Run the FPP on L2 block # NumL2Blocks. ++ env.RunFaultProofProgram(t, NumL2Blocks, testCfg.CheckResult, testCfg.InputParams...) ++} + -+ return nil ++func Test_ProgramAction_GarbageChannel(gt *testing.T) { ++ matrix := helpers.NewMatrix[actionsHelpers.GarbageKind]() ++ defer matrix.Run(gt) ++ ++ for _, garbageKind := range garbageKinds { ++ matrix.AddTestCase( ++ fmt.Sprintf("HonestClaim-%s", garbageKind.String()), ++ garbageKind, ++ helpers.LatestForkOnly, ++ runGarbageChannelTest, ++ helpers.ExpectNoError(), ++ ) ++ matrix.AddTestCase( ++ fmt.Sprintf("JunkClaim-%s", garbageKind.String()), ++ garbageKind, ++ helpers.LatestForkOnly, ++ runGarbageChannelTest, ++ helpers.ExpectError(claim.ErrClaimNotValid), ++ helpers.WithL2Claim(common.HexToHash("0xdeadbeef")), ++ ) ++ } +}
@@ -14937,9 +64890,9 @@
@@ -14954,7 +64907,7 @@
@@ -14964,471 +64917,723 @@
-
+453
+
+257
-0
-
diff --git OP/op-chain-ops/cmd/celo-migrate/state.go CELO/op-chain-ops/cmd/celo-migrate/state.go +
diff --git OP/op-e2e/actions/proofs/helpers/env.go CELO/op-e2e/actions/proofs/helpers/env.go new file mode 100644 -index 0000000000000000000000000000000000000000..6bf998db22a3ffd2fc8d046b55b1786aae1e907f ---- /dev/null -+++ CELO/op-chain-ops/cmd/celo-migrate/state.go -@@ -0,0 +1,453 @@ -+package main -+ -+import ( -+ "encoding/json" -+ "errors" -+ "fmt" -+ "math/big" -+ "os" -+ -+ "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" -+ "github.com/ethereum-optimism/optimism/op-service/jsonutil" -+ "github.com/ethereum-optimism/optimism/op-service/predeploys" -+ "github.com/ethereum/go-ethereum/common" -+ "github.com/ethereum/go-ethereum/consensus/misc/eip1559" -+ "github.com/ethereum/go-ethereum/contracts/addresses" -+ "github.com/ethereum/go-ethereum/core/rawdb" -+ "github.com/ethereum/go-ethereum/core/state" -+ "github.com/ethereum/go-ethereum/core/tracing" -+ "github.com/ethereum/go-ethereum/core/types" -+ "github.com/ethereum/go-ethereum/core/vm" -+ "github.com/ethereum/go-ethereum/ethdb" -+ "github.com/ethereum/go-ethereum/log" -+ "github.com/ethereum/go-ethereum/params" -+ "github.com/ethereum/go-ethereum/trie" -+ -+ "github.com/holiman/uint256" -+) -+ -+const ( -+ MainnetNetworkID = uint64(42220) -+ BaklavaNetworkID = uint64(62320) -+ AlfajoresNetworkID = uint64(44787) -+ -+ OutFilePerm = os.FileMode(0o440) -+) -+ -+var ( -+ Big10 = uint256.NewInt(10) -+ Big9 = uint256.NewInt(9) -+ Big18 = uint256.NewInt(18) -+ -+ // Allowlist of accounts that are allowed to be overwritten -+ // If the value for an account is set to true, the nonce and storage will be overwritten -+ // This must be checked for each account, as this might create issues with contracts -+ // calling `CREATE` or `CREATE2` -+ accountOverwriteAllowlist = map[uint64]map[common.Address]bool{ -+ // Add any addresses that should be allowed to overwrite existing accounts here. -+ AlfajoresNetworkID: { -+ // Create2Deployer -+ // OP uses a version without an owner who can pause the contract, -+ // so we overwrite the existing contract during migration -+ common.HexToAddress("0x13b0D85CcB8bf860b6b79AF3029fCA081AE9beF2"): true, -+ -+ // Same code as in allocs file -+ // EntryPoint_v070 -+ common.HexToAddress("0x0000000071727De22E5E9d8BAf0edAc6f37da032"): false, -+ // Permit2 -+ common.HexToAddress("0x000000000022D473030F116dDEE9F6B43aC78BA3"): false, -+ // EntryPoint_v060 -+ common.HexToAddress("0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789"): false, -+ // DeterministicDeploymentProxy -+ common.HexToAddress("0x4e59b44847b379578588920cA78FbF26c0B4956C"): false, -+ // SafeL2_v130 -+ common.HexToAddress("0xfb1bffC9d739B8D520DaF37dF666da4C687191EA"): false, -+ // MultiSend_v130 -+ common.HexToAddress("0x998739BFdAAdde7C933B942a68053933098f9EDa"): false, -+ // SenderCreator_v070 -+ common.HexToAddress("0xEFC2c1444eBCC4Db75e7613d20C6a62fF67A167C"): false, -+ // SenderCreator_v060 -+ common.HexToAddress("0x7fc98430eAEdbb6070B35B39D798725049088348"): false, -+ // MultiCall3 -+ common.HexToAddress("0xcA11bde05977b3631167028862bE2a173976CA11"): false, -+ // Safe_v130 -+ common.HexToAddress("0x69f4D1788e39c87893C980c06EdF4b7f686e2938"): false, -+ // MultiSendCallOnly_v130 -+ common.HexToAddress("0xA1dabEF33b3B82c7814B6D82A79e50F4AC44102B"): false, -+ // SafeSingletonFactory -+ common.HexToAddress("0x914d7Fec6aaC8cd542e72Bca78B30650d45643d7"): false, -+ // CreateX -+ common.HexToAddress("0xba5Ed099633D3B313e4D5F7bdc1305d3c28ba5Ed"): false, -+ }, -+ } -+ unreleasedTreasuryAddressMap = map[uint64]common.Address{ -+ AlfajoresNetworkID: common.HexToAddress("0x07bf0b2461A0cb608D5CF9a82ba97dAbA850F79F"), -+ } -+ celoTokenAddressMap = map[uint64]common.Address{ -+ AlfajoresNetworkID: addresses.CeloTokenAlfajoresAddress, -+ MainnetNetworkID: addresses.CeloTokenAddress, -+ } -+) -+ -+func applyStateMigrationChanges(config *genesis.DeployConfig, l2Allocs types.GenesisAlloc, dbPath, genesisOutPath string, migrationBlockTime uint64, l1StartBlock *types.Block) (*types.Header, error) { -+ log.Info("Opening Celo database", "dbPath", dbPath) -+ -+ ldb, err := openDBWithoutFreezer(dbPath, false) -+ if err != nil { -+ return nil, fmt.Errorf("cannot open DB: %w", err) -+ } -+ log.Info("Loaded Celo L1 DB", "db", ldb) -+ -+ // Grab the hash of the tip of the legacy chain. -+ hash := rawdb.ReadHeadHeaderHash(ldb) -+ log.Info("Reading chain tip from database", "hash", hash) -+ -+ // Grab the header number. -+ num := rawdb.ReadHeaderNumber(ldb, hash) -+ if num == nil { -+ return nil, fmt.Errorf("cannot find header number for %s", hash) -+ } -+ log.Info("Reading chain tip num from database", "number", *num) -+ -+ // Grab the full header. -+ header := rawdb.ReadHeader(ldb, hash, *num) -+ log.Info("Read header from database", "header", header) -+ -+ // We need to update the chain config to set the correct hardforks. -+ genesisHash := rawdb.ReadCanonicalHash(ldb, 0) -+ cfg := rawdb.ReadChainConfig(ldb, genesisHash) -+ if cfg == nil { -+ log.Crit("chain config not found") -+ } -+ log.Info("Read chain config from database", "config", cfg) -+ -+ // Set up the backing store. -+ underlyingDB := state.NewDatabase(ldb) -+ -+ // Open up the state database. -+ db, err := state.New(header.Root, underlyingDB, nil) -+ if err != nil { -+ return nil, fmt.Errorf("cannot open StateDB: %w", err) -+ } -+ -+ // Apply the changes to the state DB. -+ err = applyAllocsToState(db, l2Allocs, accountOverwriteAllowlist[cfg.ChainID.Uint64()]) -+ if err != nil { -+ return nil, fmt.Errorf("cannot apply allocations to state: %w", err) -+ } -+ -+ // Initialize the unreleased treasury contract -+ // This uses the original config which won't enable recent hardforks (and things like the PUSH0 opcode) -+ // This is fine, as the token uses solc 0.5.x and therefore compatible bytecode -+ err = setupUnreleasedTreasury(db, cfg) -+ if err != nil { -+ // An error here shouldn't stop the migration, just log it -+ log.Warn("Error setting up unreleased treasury", "error", err) -+ } -+ -+ migrationBlockNumber := new(big.Int).Add(header.Number, common.Big1) -+ -+ // We're done messing around with the database, so we can now commit the changes to the DB. -+ // Note that this doesn't actually write the changes to disk. -+ log.Info("Committing state DB") -+ newRoot, err := db.Commit(migrationBlockNumber.Uint64(), true) -+ if err != nil { -+ return nil, err -+ } -+ -+ // Set the standard options. -+ cfg.LondonBlock = migrationBlockNumber -+ cfg.BerlinBlock = migrationBlockNumber -+ cfg.ArrowGlacierBlock = migrationBlockNumber -+ cfg.GrayGlacierBlock = migrationBlockNumber -+ cfg.MergeNetsplitBlock = migrationBlockNumber -+ cfg.TerminalTotalDifficulty = big.NewInt(0) -+ cfg.TerminalTotalDifficultyPassed = true -+ cfg.ShanghaiTime = &migrationBlockTime -+ cfg.CancunTime = &migrationBlockTime -+ -+ // Set the Optimism options. -+ cfg.Optimism = &params.OptimismConfig{ -+ EIP1559Denominator: config.EIP1559Denominator, -+ EIP1559DenominatorCanyon: &config.EIP1559DenominatorCanyon, -+ EIP1559Elasticity: config.EIP1559Elasticity, -+ } -+ -+ // Set the Celo options. -+ cfg.Celo = &params.CeloConfig{ -+ EIP1559BaseFeeFloor: config.EIP1559BaseFeeFloor, -+ } -+ -+ // Set Optimism hardforks -+ cfg.BedrockBlock = migrationBlockNumber -+ cfg.RegolithTime = &migrationBlockTime -+ cfg.CanyonTime = &migrationBlockTime -+ cfg.EcotoneTime = &migrationBlockTime -+ cfg.FjordTime = &migrationBlockTime -+ cfg.GraniteTime = &migrationBlockTime -+ cfg.Cel2Time = &migrationBlockTime -+ -+ // Calculate the base fee for the migration block. -+ baseFee := new(big.Int).SetUint64(params.InitialBaseFee) -+ if header.BaseFee != nil { -+ baseFee = eip1559.CalcBaseFee(cfg, header, migrationBlockTime) -+ } -+ -+ // If gas limit was zero at the transition point use a default of 30M. -+ // Note that in op-geth we use gasLimit==0 to indicate a pre-gingerbread -+ // block and adjust encoding appropriately, so we must make sure that -+ // gasLimit is non-zero, because L2 blocks are all post gingerbread. -+ gasLimit := header.GasLimit -+ if gasLimit == 0 { -+ gasLimit = 30e6 -+ } -+ // Create the header for the Cel2 transition block. -+ cel2Header := &types.Header{ -+ ParentHash: header.Hash(), -+ UncleHash: types.EmptyUncleHash, -+ Coinbase: predeploys.SequencerFeeVaultAddr, -+ Root: newRoot, -+ TxHash: types.EmptyTxsHash, -+ ReceiptHash: types.EmptyReceiptsHash, -+ Bloom: types.Bloom{}, -+ Difficulty: new(big.Int).Set(common.Big0), -+ Number: migrationBlockNumber, -+ GasLimit: gasLimit, -+ GasUsed: 0, -+ Time: migrationBlockTime, -+ Extra: []byte("Celo L2 migration"), -+ MixDigest: common.Hash{}, -+ Nonce: types.BlockNonce{}, -+ BaseFee: baseFee, -+ // Added during Shanghai hardfork -+ // As there're no withdrawals in L2, we set it to the empty hash -+ WithdrawalsHash: &types.EmptyWithdrawalsHash, -+ // Blobs are disabled in L2 -+ BlobGasUsed: new(uint64), -+ ExcessBlobGas: new(uint64), -+ // This is set to the ParentBeaconRoot of the L1 origin (see `PreparePayloadAttributes`) -+ // Use the L1 start block's ParentBeaconRoot -+ ParentBeaconRoot: l1StartBlock.Header().ParentBeaconRoot, -+ } -+ log.Info("Build Cel2 migration header", "header", cel2Header) +index 0000000000000000000000000000000000000000..ca670acb228d54b0457cd8328f503a55b657ddda +--- /dev/null ++++ CELO/op-e2e/actions/proofs/helpers/env.go +@@ -0,0 +1,257 @@ ++package helpers + -+ // We need to set empty withdrawals in the body, otherwise types.NewBlock will nullify the withdrawals hash in the given header. -+ b := &types.Body{ -+ Withdrawals: []*types.Withdrawal{}, -+ } -+ // Create the Cel2 transition block from the header. Note that there are no transactions, -+ // uncle blocks, or receipts in the Cel2 transition block. -+ cel2Block := types.NewBlock(cel2Header, b, nil, trie.NewStackTrie(nil)) ++import ( ++ "context" ++ "math/rand" + -+ // We did it! -+ log.Info( -+ "Built Cel2 migration block", -+ "hash", cel2Block.Hash(), -+ "root", cel2Block.Root(), -+ "number", cel2Block.NumberU64(), -+ ) ++ altda "github.com/ethereum-optimism/optimism/op-alt-da" ++ batcherFlags "github.com/ethereum-optimism/optimism/op-batcher/flags" ++ "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" ++ "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" ++ "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/fakebeacon" ++ "github.com/ethereum-optimism/optimism/op-program/host" ++ "github.com/ethereum-optimism/optimism/op-program/host/config" ++ "github.com/ethereum-optimism/optimism/op-program/host/kvstore" ++ "github.com/ethereum-optimism/optimism/op-program/host/prefetcher" ++ hostTypes "github.com/ethereum-optimism/optimism/op-program/host/types" ++ "github.com/ethereum-optimism/optimism/op-service/sources" ++ "github.com/ethereum-optimism/optimism/op-service/testlog" ++ "github.com/ethereum/go-ethereum/common" ++ "github.com/ethereum/go-ethereum/common/hexutil" ++ "github.com/ethereum/go-ethereum/core/types" ++ "github.com/ethereum/go-ethereum/log" ++ "github.com/stretchr/testify/require" ++) + -+ log.Info("Committing trie DB") -+ if err := db.Database().TrieDB().Commit(newRoot, true); err != nil { -+ return nil, err ++// L2FaultProofEnv is a test harness for a fault provable L2 chain. ++type L2FaultProofEnv struct { ++ log log.Logger ++ Batcher *helpers.L2Batcher ++ Sequencer *helpers.L2Sequencer ++ Engine *helpers.L2Engine ++ engCl *sources.EngineClient ++ Sd *e2eutils.SetupData ++ Dp *e2eutils.DeployParams ++ Miner *helpers.L1Miner ++ Alice *helpers.CrossLayerUser ++ Bob *helpers.CrossLayerUser ++} ++ ++func NewL2FaultProofEnv[c any](t helpers.Testing, testCfg *TestCfg[c], tp *e2eutils.TestParams, batcherCfg *helpers.BatcherCfg) *L2FaultProofEnv { ++ log := testlog.Logger(t, log.LvlDebug) ++ dp := NewDeployParams(t, tp, func(dp *e2eutils.DeployParams) { ++ genesisBlock := hexutil.Uint64(0) ++ ++ // Enable cancun always ++ dp.DeployConfig.L1CancunTimeOffset = &genesisBlock ++ ++ // Enable L2 feature. ++ switch testCfg.Hardfork { ++ case Regolith: ++ dp.DeployConfig.L2GenesisRegolithTimeOffset = &genesisBlock ++ case Canyon: ++ dp.DeployConfig.L2GenesisCanyonTimeOffset = &genesisBlock ++ case Delta: ++ dp.DeployConfig.L2GenesisDeltaTimeOffset = &genesisBlock ++ case Ecotone: ++ dp.DeployConfig.L2GenesisEcotoneTimeOffset = &genesisBlock ++ case Fjord: ++ dp.DeployConfig.L2GenesisFjordTimeOffset = &genesisBlock ++ case Granite: ++ dp.DeployConfig.L2GenesisGraniteTimeOffset = &genesisBlock ++ } ++ }) ++ sd := e2eutils.Setup(t, dp, helpers.DefaultAlloc) ++ ++ jwtPath := e2eutils.WriteDefaultJWT(t) ++ cfg := &helpers.SequencerCfg{VerifierCfg: *helpers.DefaultVerifierCfg()} ++ ++ miner := helpers.NewL1Miner(t, log.New("role", "l1-miner"), sd.L1Cfg) ++ ++ l1Cl, err := sources.NewL1Client(miner.RPCClient(), log, nil, sources.L1ClientDefaultConfig(sd.RollupCfg, false, sources.RPCKindStandard)) ++ require.NoError(t, err) ++ engine := helpers.NewL2Engine(t, log.New("role", "sequencer-engine"), sd.L2Cfg, sd.RollupCfg.Genesis.L1, jwtPath, helpers.EngineWithP2P()) ++ l2EngineCl, err := sources.NewEngineClient(engine.RPCClient(), log, nil, sources.EngineClientDefaultConfig(sd.RollupCfg)) ++ require.NoError(t, err) ++ ++ sequencer := helpers.NewL2Sequencer(t, log.New("role", "sequencer"), l1Cl, miner.BlobStore(), altda.Disabled, l2EngineCl, sd.RollupCfg, 0, cfg.InteropBackend) ++ miner.ActL1SetFeeRecipient(common.Address{0xCA, 0xFE, 0xBA, 0xBE}) ++ sequencer.ActL2PipelineFull(t) ++ engCl := engine.EngineClient(t, sd.RollupCfg) ++ ++ // Set the batcher key to the secret key of the batcher ++ batcherCfg.BatcherKey = dp.Secrets.Batcher ++ batcher := helpers.NewL2Batcher(log, sd.RollupCfg, batcherCfg, sequencer.RollupClient(), miner.EthClient(), engine.EthClient(), engCl) ++ ++ addresses := e2eutils.CollectAddresses(sd, dp) ++ l1EthCl := miner.EthClient() ++ l2EthCl := engine.EthClient() ++ l1UserEnv := &helpers.BasicUserEnv[*helpers.L1Bindings]{ ++ EthCl: l1EthCl, ++ Signer: types.LatestSigner(sd.L1Cfg.Config), ++ AddressCorpora: addresses, ++ Bindings: helpers.NewL1Bindings(t, l1EthCl), + } ++ l2UserEnv := &helpers.BasicUserEnv[*helpers.L2Bindings]{ ++ EthCl: l2EthCl, ++ Signer: types.LatestSigner(sd.L2Cfg.Config), ++ AddressCorpora: addresses, ++ Bindings: helpers.NewL2Bindings(t, l2EthCl, engine.GethClient()), ++ } ++ alice := helpers.NewCrossLayerUser(log, dp.Secrets.Alice, rand.New(rand.NewSource(0xa57b))) ++ alice.L1.SetUserEnv(l1UserEnv) ++ alice.L2.SetUserEnv(l2UserEnv) ++ bob := helpers.NewCrossLayerUser(log, dp.Secrets.Bob, rand.New(rand.NewSource(0xbeef))) ++ bob.L1.SetUserEnv(l1UserEnv) ++ bob.L2.SetUserEnv(l2UserEnv) ++ ++ return &L2FaultProofEnv{ ++ log: log, ++ Batcher: batcher, ++ Sequencer: sequencer, ++ Engine: engine, ++ engCl: engCl, ++ Sd: sd, ++ Dp: dp, ++ Miner: miner, ++ Alice: alice, ++ Bob: bob, ++ } ++} + -+ // Next we write the Cel2 migration block to the database. -+ rawdb.WriteTd(ldb, cel2Block.Hash(), cel2Block.NumberU64(), cel2Block.Difficulty()) -+ rawdb.WriteBlock(ldb, cel2Block) -+ rawdb.WriteReceipts(ldb, cel2Block.Hash(), cel2Block.NumberU64(), nil) -+ rawdb.WriteCanonicalHash(ldb, cel2Block.Hash(), cel2Block.NumberU64()) -+ rawdb.WriteHeadBlockHash(ldb, cel2Block.Hash()) -+ rawdb.WriteHeadFastBlockHash(ldb, cel2Block.Hash()) -+ rawdb.WriteHeadHeaderHash(ldb, cel2Block.Hash()) ++type FixtureInputParam func(f *FixtureInputs) + -+ // Mark the first CeL2 block as finalized -+ rawdb.WriteFinalizedBlockHash(ldb, cel2Block.Hash()) ++type CheckResult func(helpers.Testing, error) + -+ // Write the chain config to disk. -+ rawdb.WriteChainConfig(ldb, genesisHash, cfg) -+ marshalledConfig, err := json.Marshal(cfg) -+ if err != nil { -+ return nil, fmt.Errorf("failed to marshal chain config to JSON: %w", err) ++func ExpectNoError() CheckResult { ++ return func(t helpers.Testing, err error) { ++ require.NoError(t, err, "fault proof program should have succeeded") + } -+ log.Info("Wrote updated chain config", "config", string(marshalledConfig)) ++} + -+ // Write genesis JSON to outfile and store genesis state spec in the database. -+ if err = writeGenesis(cfg, ldb, genesisOutPath, genesisHash); err != nil { -+ return nil, err ++func ExpectError(expectedErr error) CheckResult { ++ return func(t helpers.Testing, err error) { ++ require.ErrorIs(t, err, expectedErr, "fault proof program should have failed with expected error") + } ++} + -+ // We're done! -+ log.Info( -+ "Wrote CeL2 migration block", -+ "height", cel2Header.Number, -+ "root", cel2Header.Root.String(), -+ "hash", cel2Header.Hash().String(), -+ "timestamp", cel2Header.Time, -+ ) ++func WithL2Claim(claim common.Hash) FixtureInputParam { ++ return func(f *FixtureInputs) { ++ f.L2Claim = claim ++ } ++} + -+ // Close the database handle -+ if err := ldb.Close(); err != nil { -+ return nil, err ++func (env *L2FaultProofEnv) RunFaultProofProgram(t helpers.Testing, l2ClaimBlockNum uint64, checkResult CheckResult, fixtureInputParams ...FixtureInputParam) { ++ // Fetch the pre and post output roots for the fault proof. ++ preRoot, err := env.Sequencer.RollupClient().OutputAtBlock(t.Ctx(), l2ClaimBlockNum-1) ++ require.NoError(t, err) ++ claimRoot, err := env.Sequencer.RollupClient().OutputAtBlock(t.Ctx(), l2ClaimBlockNum) ++ require.NoError(t, err) ++ l1Head := env.Miner.L1Chain().CurrentBlock() ++ ++ fixtureInputs := &FixtureInputs{ ++ L2BlockNumber: l2ClaimBlockNum, ++ L2Claim: common.Hash(claimRoot.OutputRoot), ++ L2Head: preRoot.BlockRef.Hash, ++ L2OutputRoot: common.Hash(preRoot.OutputRoot), ++ L2ChainID: env.Sd.RollupCfg.L2ChainID.Uint64(), ++ L1Head: l1Head.Hash(), ++ } ++ for _, apply := range fixtureInputParams { ++ apply(fixtureInputs) + } + -+ return cel2Header, nil ++ // Run the fault proof program from the state transition from L2 block l2ClaimBlockNum - 1 -> l2ClaimBlockNum. ++ workDir := t.TempDir() ++ if IsKonaConfigured() { ++ fakeBeacon := fakebeacon.NewBeacon( ++ env.log, ++ env.Miner.BlobStore(), ++ env.Sd.L1Cfg.Timestamp, ++ 12, ++ ) ++ require.NoError(t, fakeBeacon.Start("127.0.0.1:0")) ++ defer fakeBeacon.Close() ++ ++ err = RunKonaNative(t, workDir, env, env.Miner.HTTPEndpoint(), fakeBeacon.BeaconAddr(), env.Engine.HTTPEndpoint(), *fixtureInputs) ++ checkResult(t, err) ++ } else { ++ programCfg := NewOpProgramCfg( ++ t, ++ env, ++ fixtureInputs, ++ ) ++ withInProcessPrefetcher := host.WithPrefetcher(func(ctx context.Context, logger log.Logger, kv kvstore.KV, cfg *config.Config) (host.Prefetcher, error) { ++ // Set up in-process L1 sources ++ l1Cl := env.Miner.L1Client(t, env.Sd.RollupCfg) ++ l1BlobFetcher := env.Miner.BlobSource() ++ ++ // Set up in-process L2 source ++ l2ClCfg := sources.L2ClientDefaultConfig(env.Sd.RollupCfg, true) ++ l2RPC := env.Engine.RPCClient() ++ l2Client, err := host.NewL2Client(l2RPC, env.log, nil, &host.L2ClientConfig{L2ClientConfig: l2ClCfg, L2Head: cfg.L2Head}) ++ require.NoError(t, err, "failed to create L2 client") ++ l2DebugCl := &host.L2Source{L2Client: l2Client, DebugClient: sources.NewDebugClient(l2RPC.CallContext)} ++ ++ return prefetcher.NewPrefetcher(logger, l1Cl, l1BlobFetcher, l2DebugCl, kv), nil ++ }) ++ err = host.FaultProofProgram(t.Ctx(), env.log, programCfg, withInProcessPrefetcher) ++ checkResult(t, err) ++ } ++ tryDumpTestFixture(t, err, t.Name(), env, *fixtureInputs, workDir) +} + -+// applyAllocsToState applies the account allocations from the allocation file to the state database. -+// It creates new accounts, sets their nonce, balance, code, and storage values. -+// If an account already exists, it adds the balance of the new account to the existing balance. -+// If the code of an existing account is different from the code in the genesis block, it logs a warning. -+// This changes the state root, so `Commit` needs to be called after this function. -+func applyAllocsToState(db vm.StateDB, allocs types.GenesisAlloc, allowlist map[common.Address]bool) error { -+ log.Info("Starting to migrate OP contracts into state DB") ++type TestParam func(p *e2eutils.TestParams) + -+ copyCounter := 0 -+ overwriteCounter := 0 ++func NewTestParams(params ...TestParam) *e2eutils.TestParams { ++ dfault := helpers.DefaultRollupTestParams ++ for _, apply := range params { ++ apply(dfault) ++ } ++ return dfault ++} + -+ for k, v := range allocs { -+ // Check that the balance of the account to written is zero, -+ // as we must not create new CELO tokens -+ if v.Balance != nil && v.Balance.Cmp(big.NewInt(0)) != 0 { -+ return fmt.Errorf("account balance is not zero, would change celo supply: %s", k.Hex()) -+ } ++type DeployParam func(p *e2eutils.DeployParams) + -+ if db.Exist(k) { -+ writeNonceAndStorage := false -+ writeCode, allowed := allowlist[k] ++func NewDeployParams(t helpers.Testing, tp *e2eutils.TestParams, params ...DeployParam) *e2eutils.DeployParams { ++ dfault := e2eutils.MakeDeployParams(t, tp) ++ for _, apply := range params { ++ apply(dfault) ++ } ++ return dfault ++} + -+ // If the account is not allowed and has a non zero nonce or code size, bail out we will need to manually investigate how to handle this. -+ if !allowed && (db.GetCodeSize(k) > 0 || db.GetNonce(k) > 0) { -+ return fmt.Errorf("account exists and is not allowed, account: %s, nonce: %d, code: %d", k.Hex(), db.GetNonce(k), db.GetCode(k)) -+ } ++type BatcherCfgParam func(c *helpers.BatcherCfg) + -+ // This means that the account just has balance, in that case we wan to copy over the account -+ if db.GetCodeSize(k) == 0 && db.GetNonce(k) == 0 { -+ writeCode = true -+ writeNonceAndStorage = true -+ } ++func NewBatcherCfg(params ...BatcherCfgParam) *helpers.BatcherCfg { ++ dfault := &helpers.BatcherCfg{ ++ MinL1TxSize: 0, ++ MaxL1TxSize: 128_000, ++ DataAvailabilityType: batcherFlags.BlobsType, ++ } ++ for _, apply := range params { ++ apply(dfault) ++ } ++ return dfault ++} + -+ if writeCode { -+ overwriteCounter++ ++type OpProgramCfgParam func(p *config.Config) + -+ db.SetCode(k, v.Code) ++func NewOpProgramCfg( ++ t helpers.Testing, ++ env *L2FaultProofEnv, ++ fi *FixtureInputs, ++ params ...OpProgramCfgParam, ++) *config.Config { ++ dfault := config.NewConfig(env.Sd.RollupCfg, env.Sd.L2Cfg.Config, fi.L1Head, fi.L2Head, fi.L2OutputRoot, fi.L2Claim, fi.L2BlockNumber) + -+ if writeNonceAndStorage { -+ db.SetNonce(k, v.Nonce) -+ for key, value := range v.Storage { -+ db.SetState(k, key, value) -+ } -+ } -+ log.Info("Overwrote account", "address", k.Hex(), "writeNonceAndStorage", writeNonceAndStorage) -+ } -+ continue -+ } ++ if dumpFixtures { ++ dfault.DataDir = t.TempDir() ++ dfault.DataFormat = hostTypes.DataFormatPebble ++ } + -+ // Account does not exist, create it -+ db.CreateAccount(k) -+ db.SetCode(k, v.Code) -+ db.SetNonce(k, v.Nonce) -+ for key, value := range v.Storage { -+ db.SetState(k, key, value) -+ } ++ for _, apply := range params { ++ apply(dfault) ++ } ++ return dfault ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+135
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/actions/proofs/helpers/fixture.go CELO/op-e2e/actions/proofs/helpers/fixture.go +new file mode 100644 +index 0000000000000000000000000000000000000000..892848470897e3c994c60059b5a047cab7a7bd0b +--- /dev/null ++++ CELO/op-e2e/actions/proofs/helpers/fixture.go +@@ -0,0 +1,135 @@ ++package helpers + -+ copyCounter++ -+ log.Info("Copied account", "address", k.Hex()) ++import ( ++ "encoding/json" ++ "errors" ++ "io/fs" ++ "os" ++ "os/exec" ++ "path/filepath" ++ "regexp" ++ "strings" ++ ++ "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" ++ "github.com/ethereum-optimism/optimism/op-program/client/claim" ++ "github.com/ethereum/go-ethereum/common" ++ "github.com/naoina/toml" ++ "github.com/stretchr/testify/require" ++) ++ ++var ( ++ dumpFixtures = false ++ fixtureDir string ++) ++ ++func init() { ++ fixtureDir = os.Getenv("OP_E2E_FPP_FIXTURE_DIR") ++ if fixtureDir != "" { ++ dumpFixtures = true + } ++} + -+ log.Info("Migrated OP contracts into state DB", "totalAllocs", len(allocs), "copiedAccounts", copyCounter, "overwrittenAccounts", overwriteCounter) -+ return nil ++type TestFixture struct { ++ Name string `toml:"name"` ++ ExpectedStatus uint8 `toml:"expected-status"` ++ Inputs FixtureInputs `toml:"inputs"` +} + -+// setupUnreleasedTreasury sets up the unreleased treasury contract with the correct balance -+// The balance is set to the difference between the ceiling and the total supply of the token -+func setupUnreleasedTreasury(db *state.StateDB, config *params.ChainConfig) error { -+ log.Info("Setting up CeloUnreleasedTreasury balance") ++type FixtureInputs struct { ++ L2BlockNumber uint64 `toml:"l2-block-number"` ++ L2Claim common.Hash `toml:"l2-claim"` ++ L2Head common.Hash `toml:"l2-head"` ++ L2OutputRoot common.Hash `toml:"l2-output-root"` ++ L2ChainID uint64 `toml:"l2-chain-id"` ++ L1Head common.Hash `toml:"l1-head"` ++} + -+ celoUnreleasedTreasuryAddress, exists := unreleasedTreasuryAddressMap[config.ChainID.Uint64()] -+ if !exists { -+ return errors.New("CeloUnreleasedTreasury address not configured for this chain, skipping migration step") ++// Dumps a `fp-tests` test fixture to disk if the `OP_E2E_FPP_FIXTURE_DIR` environment variable is set. ++// ++// [fp-tests]: https://github.com/ethereum-optimism/fp-tests ++func tryDumpTestFixture( ++ t helpers.Testing, ++ result error, ++ name string, ++ env *L2FaultProofEnv, ++ inputs FixtureInputs, ++ workDir string, ++) { ++ if !dumpFixtures { ++ return + } + -+ if !db.Exist(celoUnreleasedTreasuryAddress) { -+ return errors.New("CeloUnreleasedTreasury account does not exist, skipping migration step") ++ name = convertToKebabCase(name) ++ rollupCfg := env.Sd.RollupCfg ++ l2Genesis := env.Sd.L2Cfg ++ ++ var expectedStatus uint8 ++ if result == nil { ++ expectedStatus = 0 ++ } else if errors.Is(result, claim.ErrClaimNotValid) { ++ expectedStatus = 1 ++ } else { ++ expectedStatus = 2 + } + -+ tokenAddress, exists := celoTokenAddressMap[config.ChainID.Uint64()] -+ if !exists { -+ return errors.New("celo token address not configured for this chain, skipping migration step") ++ fixture := TestFixture{ ++ Name: name, ++ ExpectedStatus: expectedStatus, ++ Inputs: inputs, + } -+ log.Info("Read contract addresses", "tokenAddress", tokenAddress, "celoUnreleasedTreasuryAddress", celoUnreleasedTreasuryAddress) + -+ // totalSupply is stored in the third slot -+ totalSupply := db.GetState(tokenAddress, common.HexToHash("0x02")).Big() ++ fixturePath := filepath.Join(fixtureDir, name) ++ ++ err := os.MkdirAll(filepath.Join(fixturePath), fs.ModePerm) ++ require.NoError(t, err, "failed to create fixture dir") ++ ++ fixtureFilePath := filepath.Join(fixturePath, "fixture.toml") ++ serFixture, err := toml.Marshal(fixture) ++ require.NoError(t, err, "failed to serialize fixture") ++ require.NoError(t, os.WriteFile(fixtureFilePath, serFixture, fs.ModePerm), "failed to write fixture") ++ ++ genesisPath := filepath.Join(fixturePath, "genesis.json") ++ serGenesis, err := l2Genesis.MarshalJSON() ++ require.NoError(t, err, "failed to serialize genesis") ++ require.NoError(t, os.WriteFile(genesisPath, serGenesis, fs.ModePerm), "failed to write genesis") ++ ++ rollupPath := filepath.Join(fixturePath, "rollup.json") ++ serRollup, err := json.Marshal(rollupCfg) ++ require.NoError(t, err, "failed to serialize rollup") ++ require.NoError(t, os.WriteFile(rollupPath, serRollup, fs.ModePerm), "failed to write rollup") ++ ++ // Copy the witness database into the fixture directory. ++ cmd := exec.Command("cp", "-r", workDir, filepath.Join(fixturePath, "witness-db")) ++ require.NoError(t, cmd.Run(), "Failed to copy witness DB") ++ ++ // Compress the genesis file. ++ cmd = exec.Command("zstd", genesisPath) ++ _ = cmd.Run() ++ require.NoError(t, os.Remove(genesisPath), "Failed to remove uncompressed genesis file") ++ ++ // Compress the witness database. ++ cmd = exec.Command( ++ "tar", ++ "--zstd", ++ "-cf", ++ filepath.Join(fixturePath, "witness-db.tar.zst"), ++ filepath.Join(fixturePath, "witness-db"), ++ ) ++ cmd.Dir = filepath.Join(fixturePath) ++ require.NoError(t, cmd.Run(), "Failed to compress witness DB") ++ require.NoError(t, os.RemoveAll(filepath.Join(fixturePath, "witness-db")), "Failed to remove uncompressed witness DB") ++} + -+ // Get total supply of celo token -+ billion := new(uint256.Int).Exp(Big10, Big9) -+ ethInWei := new(uint256.Int).Exp(Big10, Big18) ++// Convert to lower kebab case for strings containing `/` ++func convertToKebabCase(input string) string { ++ if !strings.Contains(input, "/") { ++ return input ++ } + -+ ceiling := new(uint256.Int).Mul(billion, ethInWei) ++ // Replace non-alphanumeric characters with underscores ++ re := regexp.MustCompile(`[^a-zA-Z0-9]+`) ++ snake := re.ReplaceAllString(input, "-") + -+ supplyU256 := uint256.MustFromBig(totalSupply) -+ if supplyU256.Cmp(ceiling) > 0 { -+ return fmt.Errorf("supply %s is greater than ceiling %s", totalSupply, ceiling) -+ } ++ // Convert to lower case ++ return strings.ToLower(snake) ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+78
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/actions/proofs/helpers/kona.go CELO/op-e2e/actions/proofs/helpers/kona.go +new file mode 100644 +index 0000000000000000000000000000000000000000..9d34a98dda01fdbb810c6c4ed342881754ca8623 +--- /dev/null ++++ CELO/op-e2e/actions/proofs/helpers/kona.go +@@ -0,0 +1,78 @@ ++package helpers + -+ balance := new(uint256.Int).Sub(ceiling, supplyU256) -+ // Don't discard existing balance of the account -+ balance = new(uint256.Int).Add(balance, db.GetBalance(celoUnreleasedTreasuryAddress)) -+ db.SetBalance(celoUnreleasedTreasuryAddress, balance, tracing.BalanceChangeUnspecified) ++import ( ++ "encoding/json" ++ "fmt" ++ "io/fs" ++ "math/big" ++ "os" ++ "os/exec" ++ "path/filepath" + -+ log.Info("Set up CeloUnreleasedTreasury balance", "celoUnreleasedTreasuryAddress", celoUnreleasedTreasuryAddress, "balance", balance, "total_supply", supplyU256, "ceiling", ceiling) -+ return nil ++ "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/utils" ++ "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/vm" ++ "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" ++ "github.com/ethereum-optimism/optimism/op-program/client/claim" ++ "github.com/stretchr/testify/require" ++) ++ ++var konaHostPath, konaClientPath string ++ ++func init() { ++ konaHostPath = os.Getenv("KONA_HOST_PATH") ++ konaClientPath = os.Getenv("KONA_CLIENT_PATH") +} + -+// writeGenesis writes the genesis json to --outfile.genesis and stores the genesis state spec (alloc) in the database. -+// Note that this is different than the cel2Block / migration block. Rather, this is the migrated genesis block of Celo from before the L2 transition. -+// Nodes will need the genesis json file in order to snap sync on the L2 chain. -+func writeGenesis(config *params.ChainConfig, db ethdb.Database, genesisOutPath string, genesisHash common.Hash) error { -+ // Derive the genesis object using hardcoded legacy alloc and the transformed extra data stored in the new db. -+ legacyGenesisAlloc, err := GetCeloL1GenesisAlloc(config) -+ if err != nil { -+ return err ++func IsKonaConfigured() bool { ++ return konaHostPath != "" && konaClientPath != "" ++} ++ ++func RunKonaNative( ++ t helpers.Testing, ++ workDir string, ++ env *L2FaultProofEnv, ++ l1Rpc string, ++ l1BeaconRpc string, ++ l2Rpc string, ++ fixtureInputs FixtureInputs, ++) error { ++ // Write rollup config to tempdir. ++ rollupConfigPath := filepath.Join(workDir, "rollup.json") ++ ser, err := json.Marshal(env.Sd.RollupCfg) ++ require.NoError(t, err) ++ require.NoError(t, os.WriteFile(rollupConfigPath, ser, fs.ModePerm)) ++ ++ // Run the fault proof program from the state transition from L2 block L2Blocknumber - 1 -> L2BlockNumber. ++ vmCfg := vm.Config{ ++ L1: l1Rpc, ++ L1Beacon: l1BeaconRpc, ++ L2: l2Rpc, ++ RollupConfigPath: rollupConfigPath, ++ Server: konaHostPath, + } -+ genesisHeader := rawdb.ReadHeader(db, genesisHash, 0) -+ genesis, err := BuildGenesis(config, legacyGenesisAlloc, genesisHeader.Extra, genesisHeader.Time) -+ if err != nil { -+ return err ++ inputs := utils.LocalGameInputs{ ++ L1Head: fixtureInputs.L1Head, ++ L2Head: fixtureInputs.L2Head, ++ L2OutputRoot: fixtureInputs.L2OutputRoot, ++ L2Claim: fixtureInputs.L2Claim, ++ L2BlockNumber: big.NewInt(int64(fixtureInputs.L2BlockNumber)), + } ++ hostCmd, err := vm.NewNativeKonaExecutor(konaClientPath).OracleCommand(vmCfg, workDir, inputs) ++ require.NoError(t, err) + -+ // Convert genesis to JSON byte slice -+ genesisBytes, err := json.Marshal(genesis) -+ if err != nil { -+ return fmt.Errorf("failed to marshal genesis to JSON: %w", err) -+ } ++ cmd := exec.Command(hostCmd[0], hostCmd[1:]...) ++ cmd.Dir = workDir ++ cmd.Stdout = os.Stdout ++ cmd.Stderr = os.Stdout + -+ // Unmarshal JSON byte slice to map -+ var genesisMap map[string]interface{} -+ if err := json.Unmarshal(genesisBytes, &genesisMap); err != nil { -+ return fmt.Errorf("failed to unmarshal genesis JSON to map: %w", err) ++ status := cmd.Run() ++ switch status := status.(type) { ++ case *exec.ExitError: ++ if status.ExitCode() == 1 { ++ return claim.ErrClaimNotValid ++ } ++ return fmt.Errorf("kona exited with status %d", status.ExitCode()) ++ default: ++ return status + } ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+97
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/actions/proofs/helpers/matrix.go CELO/op-e2e/actions/proofs/helpers/matrix.go +new file mode 100644 +index 0000000000000000000000000000000000000000..7f3e810e86b6c81a122804c5fa20eb06dfd6fe44 +--- /dev/null ++++ CELO/op-e2e/actions/proofs/helpers/matrix.go +@@ -0,0 +1,97 @@ ++package helpers + -+ // Delete fields that are not in Celo Legacy Genesis, otherwise genesis hashes won't match when syncing -+ delete(genesisMap, "difficulty") -+ delete(genesisMap, "gasLimit") -+ delete(genesisMap, "excessBlobGas") -+ delete(genesisMap, "blobGasUsed") -+ delete(genesisMap, "baseFeePerGas") -+ delete(genesisMap, "mixHash") -+ delete(genesisMap, "nonce") ++import ( ++ "fmt" ++ "testing" ++) + -+ // Write the modified JSON to the file -+ if err := jsonutil.WriteJSON(genesisOutPath, genesisMap, OutFilePerm); err != nil { -+ return fmt.Errorf("failed to write genesis JSON to file: %w", err) ++type RunTest[cfg any] func(t *testing.T, testCfg *TestCfg[cfg]) ++ ++type TestCfg[cfg any] struct { ++ Hardfork *Hardfork ++ CheckResult CheckResult ++ InputParams []FixtureInputParam ++ Custom cfg ++} ++ ++type TestCase[cfg any] struct { ++ Name string ++ Cfg cfg ++ ForkMatrix ForkMatrix ++ RunTest RunTest[cfg] ++ InputParams []FixtureInputParam ++ CheckResult CheckResult ++} ++ ++type TestMatrix[cfg any] struct { ++ CommonInputParams []FixtureInputParam ++ TestCases []TestCase[cfg] ++} ++ ++func (suite *TestMatrix[cfg]) Run(t *testing.T) { ++ for _, tc := range suite.TestCases { ++ for _, fork := range tc.ForkMatrix { ++ t.Run(fmt.Sprintf("%s-%s", tc.Name, fork.Name), func(t *testing.T) { ++ testCfg := &TestCfg[cfg]{ ++ Hardfork: fork, ++ CheckResult: tc.CheckResult, ++ InputParams: append(suite.CommonInputParams, tc.InputParams...), ++ Custom: tc.Cfg, ++ } ++ tc.RunTest(t, testCfg) ++ }) ++ } + } -+ log.Info("Wrote genesis file for syncing new nodes", "path", genesisOutPath) ++} + -+ // Legacy Celo did not store the genesis state spec (alloc) in the database. -+ // Write it now for forward compatibility. -+ rawdb.WriteGenesisStateSpec(db, genesisHash, legacyGenesisAlloc) -+ log.Info("Wrote genesis state spec (alloc) to database") ++func NewMatrix[cfg any]() *TestMatrix[cfg] { ++ return &TestMatrix[cfg]{} ++} + -+ return nil ++func (ts *TestMatrix[cfg]) WithCommonInputParams(params ...FixtureInputParam) *TestMatrix[cfg] { ++ ts.CommonInputParams = params ++ return ts ++} ++ ++func (ts *TestMatrix[cfg]) AddTestCase( ++ name string, ++ testCfg cfg, ++ forkMatrix ForkMatrix, ++ runTest RunTest[cfg], ++ checkResult CheckResult, ++ inputParams ...FixtureInputParam, ++) *TestMatrix[cfg] { ++ ts.TestCases = append(ts.TestCases, TestCase[cfg]{ ++ Name: name, ++ Cfg: testCfg, ++ ForkMatrix: forkMatrix, ++ RunTest: runTest, ++ InputParams: inputParams, ++ CheckResult: checkResult, ++ }) ++ return ts ++} ++ ++type Hardfork struct { ++ Name string ++ Precedence int ++} ++ ++type ForkMatrix = []*Hardfork ++ ++// Hardfork definitions ++var ( ++ Regolith = &Hardfork{Name: "Regolith", Precedence: 1} ++ Canyon = &Hardfork{Name: "Canyon", Precedence: 2} ++ Delta = &Hardfork{Name: "Delta", Precedence: 3} ++ Fjord = &Hardfork{Name: "Fjord", Precedence: 4} ++ Ecotone = &Hardfork{Name: "Ecotone", Precedence: 5} ++ Granite = &Hardfork{Name: "Granite", Precedence: 6} ++) ++var Hardforks = ForkMatrix{Regolith, Canyon, Delta, Fjord, Ecotone, Granite} ++ ++var LatestForkOnly = ForkMatrix{Hardforks[len(Hardforks)-1]} ++ ++func NewForkMatrix(forks ...*Hardfork) ForkMatrix { ++ return append(ForkMatrix{}, forks...) +}
@@ -15436,9 +65641,9 @@
@@ -15453,7 +65658,7 @@
@@ -15463,165 +65668,179 @@
-
+147
+
+161
-0
-
diff --git OP/op-chain-ops/cmd/celo-migrate/state_test.go CELO/op-chain-ops/cmd/celo-migrate/state_test.go +
diff --git OP/op-e2e/actions/proofs/l1_lookback_test.go CELO/op-e2e/actions/proofs/l1_lookback_test.go new file mode 100644 -index 0000000000000000000000000000000000000000..dbe6ce90ef4e51f31ade77933a6656b94dcad98a +index 0000000000000000000000000000000000000000..b40635ac55097300b8cc2e2e43b2c31095611c14 --- /dev/null -+++ CELO/op-chain-ops/cmd/celo-migrate/state_test.go -@@ -0,0 +1,147 @@ -+package main ++++ CELO/op-e2e/actions/proofs/l1_lookback_test.go +@@ -0,0 +1,161 @@ ++package proofs + +import ( -+ "bytes" -+ "math/big" + "testing" + ++ actionsHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" ++ "github.com/ethereum-optimism/optimism/op-e2e/actions/proofs/helpers" ++ "github.com/ethereum-optimism/optimism/op-program/client/claim" + "github.com/ethereum/go-ethereum/common" -+ "github.com/ethereum/go-ethereum/core/rawdb" -+ "github.com/ethereum/go-ethereum/core/state" -+ "github.com/ethereum/go-ethereum/core/tracing" + "github.com/ethereum/go-ethereum/core/types" -+ "github.com/holiman/uint256" -+ "github.com/stretchr/testify/assert" ++ "github.com/stretchr/testify/require" +) + -+var ( -+ contractCode = []byte{0x01, 0x02} -+ defaultBalance int64 = 123 -+ address = common.HexToAddress("a") -+) ++func runL1LookbackTest(gt *testing.T, testCfg *helpers.TestCfg[any]) { ++ t := actionsHelpers.NewDefaultTesting(gt) ++ tp := helpers.NewTestParams() ++ env := helpers.NewL2FaultProofEnv(t, testCfg, tp, helpers.NewBatcherCfg()) ++ ++ const numL2Blocks = 8 ++ for i := 0; i < numL2Blocks; i++ { ++ // Create an empty L2 block. ++ env.Sequencer.ActL2StartBlock(t) ++ env.Sequencer.ActL2EndBlock(t) ++ ++ // Buffer the L2 block in the batcher. ++ env.Batcher.ActBufferAll(t) ++ if i == numL2Blocks-1 { ++ env.Batcher.ActL2ChannelClose(t) ++ } ++ env.Batcher.ActL2BatchSubmit(t) + -+func TestApplyAllocsToState(t *testing.T) { -+ tests := []struct { -+ name string -+ existingAccount *types.Account -+ newAccount types.Account -+ allowlist map[common.Address]bool -+ wantErr bool -+ }{ -+ { -+ name: "Write to empty account", -+ newAccount: types.Account{ -+ Code: contractCode, -+ Nonce: 1, -+ }, -+ wantErr: false, -+ }, -+ { -+ name: "Copy account with non-zero balance fails", -+ existingAccount: &types.Account{ -+ Balance: big.NewInt(defaultBalance), -+ }, -+ newAccount: types.Account{ -+ Balance: big.NewInt(1), -+ }, -+ wantErr: true, -+ }, -+ { -+ name: "Write to account with only balance should overwrite and keep balance", -+ existingAccount: &types.Account{ -+ Balance: big.NewInt(defaultBalance), -+ }, -+ newAccount: types.Account{ -+ Code: contractCode, -+ Nonce: 5, -+ }, -+ wantErr: false, -+ }, -+ { -+ name: "Write to account with existing nonce fails", -+ existingAccount: &types.Account{ -+ Balance: big.NewInt(defaultBalance), -+ Nonce: 5, -+ }, -+ newAccount: types.Account{ -+ Code: contractCode, -+ Nonce: 5, -+ }, -+ wantErr: true, -+ }, -+ { -+ name: "Write to account with contract code fails", -+ existingAccount: &types.Account{ -+ Balance: big.NewInt(defaultBalance), -+ Code: bytes.Repeat([]byte{0x01}, 10), -+ }, -+ newAccount: types.Account{ -+ Code: contractCode, -+ Nonce: 5, -+ }, -+ wantErr: true, -+ }, -+ { -+ name: "Write account with allowlist overwrite, keeps nonce", -+ existingAccount: &types.Account{ -+ Balance: big.NewInt(defaultBalance), -+ Nonce: 4, -+ Code: bytes.Repeat([]byte{0x01}, 10), -+ }, -+ newAccount: types.Account{ -+ Code: contractCode, -+ Nonce: 5, -+ }, -+ allowlist: map[common.Address]bool{address: true}, -+ wantErr: false, -+ }, ++ // Include the frame on L1. ++ env.Miner.ActL1StartBlock(12)(t) ++ env.Miner.ActL1IncludeTxByHash(env.Batcher.LastSubmitted.Hash())(t) ++ env.Miner.ActL1EndBlock(t) ++ env.Miner.ActL1SafeNext(t) + } -+ for _, tt := range tests { -+ t.Run(tt.name, func(t *testing.T) { -+ db := rawdb.NewMemoryDatabase() -+ tdb := state.NewDatabase(db) -+ sdb, _ := state.New(types.EmptyRootHash, tdb, nil) + -+ if tt.existingAccount != nil { -+ sdb.CreateAccount(address) ++ // Instruct the sequencer to derive the L2 chain from the data on L1 that the batcher just posted. ++ env.Sequencer.ActL1HeadSignal(t) ++ env.Sequencer.ActL2PipelineFull(t) + -+ if tt.existingAccount.Balance != nil { -+ sdb.SetBalance(address, uint256.MustFromBig(tt.existingAccount.Balance), tracing.BalanceChangeUnspecified) -+ } -+ if tt.existingAccount.Nonce != 0 { -+ sdb.SetNonce(address, tt.existingAccount.Nonce) -+ } -+ if tt.existingAccount.Code != nil { -+ sdb.SetCode(address, tt.existingAccount.Code) -+ } -+ } ++ // Ensure that the safe head has advanced to `NumL2Blocks`. ++ l2SafeHead := env.Engine.L2Chain().CurrentSafeBlock() ++ require.EqualValues(t, numL2Blocks, l2SafeHead.Number.Uint64()) + -+ if err := applyAllocsToState(sdb, types.GenesisAlloc{address: tt.newAccount}, tt.allowlist); (err != nil) != tt.wantErr { -+ t.Errorf("applyAllocsToState() error = %v, wantErr %v", err, tt.wantErr) -+ } ++ // Run the FPP on the configured L2 block. ++ env.RunFaultProofProgram(t, numL2Blocks/2, testCfg.CheckResult, testCfg.InputParams...) ++} + -+ // Don't check account state if an error was thrown -+ if tt.wantErr { -+ return -+ } ++func runL1LookbackTest_ReopenChannel(gt *testing.T, testCfg *helpers.TestCfg[any]) { ++ t := actionsHelpers.NewDefaultTesting(gt) ++ tp := helpers.NewTestParams() ++ env := helpers.NewL2FaultProofEnv(t, testCfg, tp, helpers.NewBatcherCfg()) ++ ++ // Create an L2 block with 1 transaction. ++ env.Sequencer.ActL2StartBlock(t) ++ env.Alice.L2.ActResetTxOpts(t) ++ env.Alice.L2.ActSetTxToAddr(&env.Dp.Addresses.Bob) ++ env.Alice.L2.ActMakeTx(t) ++ env.Engine.ActL2IncludeTx(env.Alice.Address())(t) ++ env.Sequencer.ActL2EndBlock(t) ++ l2BlockBeforeDerive := env.Engine.L2Chain().CurrentBlock() ++ ++ // Buffer the L2 block in the batcher. ++ env.Batcher.ActL2BatchBuffer(t) ++ env.Batcher.ActL2BatchSubmit(t) ++ ++ // Include the frame on L1. ++ env.Miner.ActL1StartBlock(12)(t) ++ env.Miner.ActL1IncludeTxByHash(env.Batcher.LastSubmitted.Hash())(t) ++ env.Miner.ActL1EndBlock(t) ++ env.Miner.ActL1SafeNext(t) ++ ++ // Re-submit the first L2 block frame w/ different transaction data. ++ err := env.Batcher.Buffer(t, func(block *types.Block) { ++ env.Bob.L2.ActResetTxOpts(t) ++ env.Bob.L2.ActSetTxToAddr(&env.Dp.Addresses.Mallory) ++ tx := env.Bob.L2.MakeTransaction(t) ++ block.Transactions()[1] = tx ++ }) ++ require.NoError(t, err) ++ env.Batcher.ActL2BatchSubmit(t) ++ ++ // Include the duplicate frame on L1. ++ env.Miner.ActL1StartBlock(12)(t) ++ env.Miner.ActL1IncludeTxByHash(env.Batcher.LastSubmitted.Hash())(t) ++ env.Miner.ActL1EndBlock(t) ++ env.Miner.ActL1SafeNext(t) ++ ++ const numL2Blocks = 8 ++ for i := 1; i < numL2Blocks; i++ { ++ // Create an empty L2 block. ++ env.Sequencer.ActL2StartBlock(t) ++ env.Sequencer.ActL2EndBlock(t) ++ ++ // Buffer the L2 block in the batcher. ++ env.Batcher.ActBufferAll(t) ++ if i == numL2Blocks-1 { ++ env.Batcher.ActL2ChannelClose(t) ++ } ++ env.Batcher.ActL2BatchSubmit(t) ++ ++ // Include the frame on L1. ++ env.Miner.ActL1StartBlock(12)(t) ++ env.Miner.ActL1IncludeTxByHash(env.Batcher.LastSubmitted.Hash())(t) ++ env.Miner.ActL1EndBlock(t) ++ env.Miner.ActL1SafeNext(t) ++ } + -+ if !sdb.Exist(address) { -+ t.Errorf("account does not exists as expected: %v", address.Hex()) -+ } ++ // Instruct the sequencer to derive the L2 chain from the data on L1 that the batcher just posted. ++ env.Sequencer.ActL1HeadSignal(t) ++ env.Sequencer.ActL2PipelineFull(t) + -+ assert.Equal(t, tt.newAccount.Code, sdb.GetCode(address)) ++ // Ensure that the correct block was derived. ++ l2BlockAfterDerive := env.Engine.L2Chain().GetBlockByNumber(1) ++ require.EqualValues(t, l2BlockAfterDerive.Hash(), l2BlockBeforeDerive.Hash()) + -+ if tt.existingAccount != nil && tt.existingAccount.Nonce != 0 { -+ assert.Equal(t, tt.existingAccount.Nonce, sdb.GetNonce(address)) -+ } else { -+ assert.Equal(t, tt.newAccount.Nonce, sdb.GetNonce(address)) -+ } ++ // Ensure that the safe head has advanced to `NumL2Blocks`. ++ l2SafeHead := env.Engine.L2Chain().CurrentSafeBlock() ++ require.EqualValues(t, numL2Blocks, l2SafeHead.Number.Uint64()) + -+ if tt.existingAccount != nil { -+ assert.True(t, big.NewInt(defaultBalance).Cmp(sdb.GetBalance(address).ToBig()) == 0) -+ } else { -+ assert.True(t, big.NewInt(0).Cmp(sdb.GetBalance(address).ToBig()) == 0) -+ } -+ }) -+ } ++ // Run the FPP on the configured L2 block. ++ env.RunFaultProofProgram(t, numL2Blocks/2, testCfg.CheckResult, testCfg.InputParams...) ++} ++ ++func Test_ProgramAction_L1Lookback(gt *testing.T) { ++ matrix := helpers.NewMatrix[any]() ++ defer matrix.Run(gt) ++ ++ matrix.AddTestCase( ++ "HonestClaim", ++ nil, ++ helpers.LatestForkOnly, ++ runL1LookbackTest, ++ helpers.ExpectNoError(), ++ ) ++ matrix.AddTestCase( ++ "JunkClaim", ++ nil, ++ helpers.LatestForkOnly, ++ runL1LookbackTest, ++ helpers.ExpectError(claim.ErrClaimNotValid), ++ helpers.WithL2Claim(common.HexToHash("0xdeadbeef")), ++ ) ++ matrix.AddTestCase( ++ "HonestClaim-ReopenChannel", ++ nil, ++ helpers.LatestForkOnly, ++ runL1LookbackTest_ReopenChannel, ++ helpers.ExpectNoError(), ++ ) ++ matrix.AddTestCase( ++ "JunkClaim-ReopenChannel", ++ nil, ++ helpers.LatestForkOnly, ++ runL1LookbackTest_ReopenChannel, ++ helpers.ExpectError(claim.ErrClaimNotValid), ++ helpers.WithL2Claim(common.HexToHash("0xdeadbeef")), ++ ) +}
@@ -15629,9 +65848,9 @@
@@ -15646,7 +65865,7 @@
@@ -15656,127 +65875,183 @@
-
+109
+
+165
-0
-
diff --git OP/op-chain-ops/cmd/celo-migrate/transform.go CELO/op-chain-ops/cmd/celo-migrate/transform.go +
diff --git OP/op-e2e/actions/proofs/sequence_window_expiry_test.go CELO/op-e2e/actions/proofs/sequence_window_expiry_test.go new file mode 100644 -index 0000000000000000000000000000000000000000..5a80e8a51566f47408976d16f94885e4937108d3 +index 0000000000000000000000000000000000000000..3f5ca9562d4bfd48373c4b6e1a8c300e060d0e9a --- /dev/null -+++ CELO/op-chain-ops/cmd/celo-migrate/transform.go -@@ -0,0 +1,109 @@ -+package main ++++ CELO/op-e2e/actions/proofs/sequence_window_expiry_test.go +@@ -0,0 +1,165 @@ ++package proofs + +import ( -+ "bytes" -+ "errors" -+ "fmt" -+ "math/big" ++ "testing" + ++ actionsHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" ++ "github.com/ethereum-optimism/optimism/op-e2e/actions/proofs/helpers" ++ "github.com/ethereum-optimism/optimism/op-program/client/claim" + "github.com/ethereum/go-ethereum/common" -+ "github.com/ethereum/go-ethereum/core/types" -+ "github.com/ethereum/go-ethereum/crypto" -+ "github.com/ethereum/go-ethereum/rlp" ++ "github.com/stretchr/testify/require" +) + -+var ( -+ IstanbulExtraVanity = 32 // Fixed number of extra-data bytes reserved for validator vanity -+) ++// Run a test that proves a deposit-only block generated due to sequence window expiry. ++func runSequenceWindowExpireTest(gt *testing.T, testCfg *helpers.TestCfg[any]) { ++ t := actionsHelpers.NewDefaultTesting(gt) ++ tp := helpers.NewTestParams() ++ env := helpers.NewL2FaultProofEnv(t, testCfg, tp, helpers.NewBatcherCfg()) + -+// IstanbulAggregatedSeal is the aggregated seal for Istanbul blocks -+type IstanbulAggregatedSeal struct { -+ // Bitmap is a bitmap having an active bit for each validator that signed this block -+ Bitmap *big.Int -+ // Signature is an aggregated BLS signature resulting from signatures by each validator that signed this block -+ Signature []byte -+ // Round is the round in which the signature was created. -+ Round *big.Int -+} ++ // Mine an empty block for gas estimation purposes. ++ env.Miner.ActEmptyBlock(t) + -+// IstanbulExtra is the extra-data for Istanbul blocks -+type IstanbulExtra struct { -+ // AddedValidators are the validators that have been added in the block -+ AddedValidators []common.Address -+ // AddedValidatorsPublicKeys are the BLS public keys for the validators added in the block -+ AddedValidatorsPublicKeys [][96]byte -+ // RemovedValidators is a bitmap having an active bit for each removed validator in the block -+ RemovedValidators *big.Int -+ // Seal is an ECDSA signature by the proposer -+ Seal []byte -+ // AggregatedSeal contains the aggregated BLS signature created via IBFT consensus. -+ AggregatedSeal IstanbulAggregatedSeal -+ // ParentAggregatedSeal contains and aggregated BLS signature for the previous block. -+ ParentAggregatedSeal IstanbulAggregatedSeal -+} ++ // Expire the sequence window by building `SequenceWindow + 1` empty blocks on L1. ++ for i := 0; i < int(tp.SequencerWindowSize)+1; i++ { ++ env.Alice.L1.ActResetTxOpts(t) ++ env.Alice.ActDeposit(t) + -+// transformHeader removes the aggregated seal from the header -+func transformHeader(header []byte) ([]byte, error) { -+ newHeader := new(types.Header) -+ err := rlp.DecodeBytes(header, &newHeader) -+ if err != nil { -+ return nil, err ++ env.Miner.ActL1StartBlock(12)(t) ++ env.Miner.ActL1IncludeTx(env.Alice.Address())(t) ++ env.Miner.ActL1EndBlock(t) ++ ++ env.Miner.ActL1SafeNext(t) ++ env.Miner.ActL1FinalizeNext(t) + } + -+ if len(newHeader.Extra) < IstanbulExtraVanity { -+ return nil, errors.New("invalid istanbul header extra-data") ++ // Ensure the safe head is still 0. ++ l2SafeHead := env.Engine.L2Chain().CurrentSafeBlock() ++ require.EqualValues(t, 0, l2SafeHead.Number.Uint64()) ++ ++ // Ask the sequencer to derive the deposit-only L2 chain. ++ env.Sequencer.ActL1HeadSignal(t) ++ env.Sequencer.ActL2PipelineFull(t) ++ ++ // Ensure the safe head advanced forcefully. ++ l2SafeHead = env.Engine.L2Chain().CurrentSafeBlock() ++ require.Greater(t, l2SafeHead.Number.Uint64(), uint64(0)) ++ ++ // Run the FPP on one of the auto-derived blocks. ++ env.RunFaultProofProgram(t, l2SafeHead.Number.Uint64()/2, testCfg.CheckResult, testCfg.InputParams...) ++} ++ ++// Runs a that proves a block in a chain where the batcher opens a channel, the sequence window expires, and then the ++// batcher attempts to close the channel afterwards. ++func runSequenceWindowExpire_ChannelCloseAfterWindowExpiry_Test(gt *testing.T, testCfg *helpers.TestCfg[any]) { ++ t := actionsHelpers.NewDefaultTesting(gt) ++ tp := helpers.NewTestParams() ++ env := helpers.NewL2FaultProofEnv(t, testCfg, tp, helpers.NewBatcherCfg()) ++ ++ // Mine 2 empty blocks on L2. ++ for i := 0; i < 2; i++ { ++ env.Sequencer.ActL2StartBlock(t) ++ env.Alice.L2.ActResetTxOpts(t) ++ env.Alice.L2.ActSetTxToAddr(&env.Dp.Addresses.Bob) ++ env.Alice.L2.ActMakeTx(t) ++ env.Engine.ActL2IncludeTx(env.Alice.Address())(t) ++ env.Sequencer.ActL2EndBlock(t) + } + -+ istanbulExtra := IstanbulExtra{} -+ err = rlp.DecodeBytes(newHeader.Extra[IstanbulExtraVanity:], &istanbulExtra) -+ if err != nil { -+ return nil, err ++ // Open the channel on L1. ++ env.Batcher.ActL2BatchBuffer(t) ++ env.Batcher.ActL2BatchSubmit(t) ++ env.Miner.ActL1StartBlock(12)(t) ++ env.Miner.ActL1IncludeTxByHash(env.Batcher.LastSubmitted.Hash())(t) ++ env.Miner.ActL1EndBlock(t) ++ ++ // Finalize the block with the first channel frame on L1. ++ env.Miner.ActL1SafeNext(t) ++ env.Miner.ActL1FinalizeNext(t) ++ ++ // Instruct the sequencer to derive the L2 chain from the data on L1 that the batcher just posted. ++ env.Sequencer.ActL1HeadSignal(t) ++ env.Sequencer.ActL2PipelineFull(t) ++ ++ // Ensure the safe head is still 0. ++ l2SafeHead := env.Engine.L2Chain().CurrentSafeBlock() ++ require.EqualValues(t, 0, l2SafeHead.Number.Uint64()) ++ ++ // Cache the next frame data before expiring the sequence window, but don't submit it yet. ++ env.Batcher.ActL2BatchBuffer(t) ++ env.Batcher.ActL2ChannelClose(t) ++ finalFrame := env.Batcher.ReadNextOutputFrame(t) ++ ++ // Expire the sequence window by building `SequenceWindow + 1` empty blocks on L1. ++ for i := 0; i < int(tp.SequencerWindowSize)+1; i++ { ++ env.Alice.L1.ActResetTxOpts(t) ++ env.Alice.ActDeposit(t) ++ ++ env.Miner.ActL1StartBlock(12)(t) ++ env.Miner.ActL1IncludeTx(env.Alice.Address())(t) ++ env.Miner.ActL1EndBlock(t) ++ ++ env.Miner.ActL1SafeNext(t) ++ env.Miner.ActL1FinalizeNext(t) + } + -+ istanbulExtra.AggregatedSeal = IstanbulAggregatedSeal{} ++ // Instruct the batcher to closethe channel on L1, after the sequence window + channel timeout has elapsed. ++ env.Batcher.ActL2BatchSubmitRaw(t, finalFrame) ++ env.Miner.ActL1StartBlock(12)(t) ++ env.Miner.ActL1IncludeTxByHash(env.Batcher.LastSubmitted.Hash())(t) ++ env.Miner.ActL1EndBlock(t) + -+ payload, err := rlp.EncodeToBytes(&istanbulExtra) -+ if err != nil { -+ return nil, err -+ } ++ // Finalize the block with the second channel frame on L1. ++ env.Miner.ActL1SafeNext(t) ++ env.Miner.ActL1FinalizeNext(t) + -+ newHeader.Extra = append(newHeader.Extra[:IstanbulExtraVanity], payload...) ++ // Ensure the safe head is still 0. ++ l2SafeHead = env.Engine.L2Chain().CurrentSafeBlock() ++ require.EqualValues(t, 0, l2SafeHead.Number.Uint64()) + -+ return rlp.EncodeToBytes(newHeader) -+} ++ // Ask the sequencer to derive the deposit-only L2 chain. ++ env.Sequencer.ActL1HeadSignal(t) ++ env.Sequencer.ActL2PipelineFull(t) + -+func hasSameHash(newHeader, oldHash []byte) (bool, common.Hash) { -+ newHash := crypto.Keccak256Hash(newHeader) -+ return bytes.Equal(oldHash, newHash.Bytes()), newHash -+} ++ // Ensure the safe head advanced forcefully. ++ l2SafeHead = env.Engine.L2Chain().CurrentSafeBlock() ++ require.Greater(t, l2SafeHead.Number.Uint64(), uint64(0)) + -+// transformBlockBody migrates the block body from the old format to the new format (works with []byte input output) -+func transformBlockBody(oldBodyData []byte) ([]byte, error) { -+ // decode body into celo-blockchain Body structure -+ // remove epochSnarkData and randomness data -+ var celoBody struct { -+ Transactions types.Transactions -+ Randomness rlp.RawValue -+ EpochSnarkData rlp.RawValue -+ } -+ if err := rlp.DecodeBytes(oldBodyData, &celoBody); err != nil { -+ // body may have already been transformed in a previous migration -+ body := types.Body{} -+ if err := rlp.DecodeBytes(oldBodyData, &body); err == nil { -+ return oldBodyData, nil -+ } -+ return nil, fmt.Errorf("failed to RLP decode body: %w", err) -+ } ++ // Run the FPP on one of the auto-derived blocks. ++ env.RunFaultProofProgram(t, l2SafeHead.Number.Uint64()/2, testCfg.CheckResult, testCfg.InputParams...) ++} + -+ // transform into op-geth types.Body structure -+ newBody := types.Body{ -+ Transactions: celoBody.Transactions, -+ Uncles: []*types.Header{}, -+ } -+ newBodyData, err := rlp.EncodeToBytes(newBody) -+ if err != nil { -+ return nil, fmt.Errorf("failed to RLP encode body: %w", err) -+ } ++func Test_ProgramAction_SequenceWindowExpired(gt *testing.T) { ++ matrix := helpers.NewMatrix[any]() ++ defer matrix.Run(gt) + -+ return newBodyData, nil ++ matrix.AddTestCase( ++ "HonestClaim", ++ nil, ++ helpers.LatestForkOnly, ++ runSequenceWindowExpireTest, ++ helpers.ExpectNoError(), ++ ) ++ matrix.AddTestCase( ++ "JunkClaim", ++ nil, ++ helpers.LatestForkOnly, ++ runSequenceWindowExpireTest, ++ helpers.ExpectError(claim.ErrClaimNotValid), ++ helpers.WithL2Claim(common.HexToHash("0xdeadbeef")), ++ ) ++ matrix.AddTestCase( ++ "ChannelCloseAfterWindowExpiry-HonestClaim", ++ nil, ++ helpers.LatestForkOnly, ++ runSequenceWindowExpire_ChannelCloseAfterWindowExpiry_Test, ++ helpers.ExpectNoError(), ++ ) ++ matrix.AddTestCase( ++ "ChannelCloseAfterWindowExpiry-JunkClaim", ++ nil, ++ helpers.LatestForkOnly, ++ runSequenceWindowExpire_ChannelCloseAfterWindowExpiry_Test, ++ helpers.ExpectError(claim.ErrClaimNotValid), ++ helpers.WithL2Claim(common.HexToHash("0xdeadbeef")), ++ ) +}
@@ -15784,9 +66059,9 @@
@@ -15795,13 +66070,13 @@
- OP + (new)
@@ -15811,53 +66086,93 @@
-
+3
-
-3
+
+65
+
-0
-
diff --git OP/op-chain-ops/cmd/check-derivation/main.go CELO/op-chain-ops/cmd/check-derivation/main.go -index 499b128f8767fe560d92ee66f3ed770c373d7bf4..5f846450138445c62ccb4b5194d634382fe24d2b 100644 ---- OP/op-chain-ops/cmd/check-derivation/main.go -+++ CELO/op-chain-ops/cmd/check-derivation/main.go -@@ -225,7 +225,7 @@ data := testutils.RandomData(rng, 10) - var txData types.TxData - switch txType { - case types.LegacyTxType: -- gasLimit, err := core.IntrinsicGas(data, nil, false, true, true, false) -+ gasLimit, err := core.IntrinsicGas(data, nil, false, true, true, false, nil, nil) - if err != nil { - return nil, fmt.Errorf("failed to get intrinsicGas: %w", err) - } -@@ -242,7 +242,7 @@ accessList := types.AccessList{types.AccessTuple{ - Address: randomAddress, - StorageKeys: []common.Hash{common.HexToHash("0x1234")}, - }} -- gasLimit, err := core.IntrinsicGas(data, accessList, false, true, true, false) -+ gasLimit, err := core.IntrinsicGas(data, accessList, false, true, true, false, nil, nil) - if err != nil { - return nil, fmt.Errorf("failed to get intrinsicGas: %w", err) - } -@@ -257,7 +257,7 @@ AccessList: accessList, - Data: data, - } - case types.DynamicFeeTxType: -- gasLimit, err := core.IntrinsicGas(data, nil, false, true, true, false) -+ gasLimit, err := core.IntrinsicGas(data, nil, false, true, true, false, nil, nil) - if err != nil { - return nil, fmt.Errorf("failed to get intrinsicGas: %w", err) - }
+
diff --git OP/op-e2e/actions/proofs/simple_program_test.go CELO/op-e2e/actions/proofs/simple_program_test.go +new file mode 100644 +index 0000000000000000000000000000000000000000..ab3218caf1e483f13432aeecd9e6ba965af0a9e3 +--- /dev/null ++++ CELO/op-e2e/actions/proofs/simple_program_test.go +@@ -0,0 +1,65 @@ ++package proofs ++ ++import ( ++ "testing" ++ ++ actionsHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" ++ "github.com/ethereum-optimism/optimism/op-e2e/actions/proofs/helpers" ++ "github.com/ethereum-optimism/optimism/op-program/client/claim" ++ "github.com/ethereum/go-ethereum/common" ++ "github.com/stretchr/testify/require" ++) ++ ++func runSimpleProgramTest(gt *testing.T, testCfg *helpers.TestCfg[any]) { ++ t := actionsHelpers.NewDefaultTesting(gt) ++ env := helpers.NewL2FaultProofEnv(t, testCfg, helpers.NewTestParams(), helpers.NewBatcherCfg()) ++ ++ // Build an empty block on L2 ++ env.Sequencer.ActL2StartBlock(t) ++ env.Sequencer.ActL2EndBlock(t) ++ ++ // Instruct the batcher to submit the block to L1, and include the transaction. ++ env.Batcher.ActSubmitAll(t) ++ env.Miner.ActL1StartBlock(12)(t) ++ env.Miner.ActL1IncludeTxByHash(env.Batcher.LastSubmitted.Hash())(t) ++ env.Miner.ActL1EndBlock(t) ++ ++ // Finalize the block with the batch on L1. ++ env.Miner.ActL1SafeNext(t) ++ env.Miner.ActL1FinalizeNext(t) ++ ++ // Instruct the sequencer to derive the L2 chain from the data on L1 that the batcher just posted. ++ env.Sequencer.ActL1HeadSignal(t) ++ env.Sequencer.ActL2PipelineFull(t) ++ ++ l1Head := env.Miner.L1Chain().CurrentBlock() ++ l2SafeHead := env.Engine.L2Chain().CurrentSafeBlock() ++ ++ // Ensure there is only 1 block on L1. ++ require.Equal(t, uint64(1), l1Head.Number.Uint64()) ++ // Ensure the block is marked as safe before we attempt to fault prove it. ++ require.Equal(t, uint64(1), l2SafeHead.Number.Uint64()) ++ ++ env.RunFaultProofProgram(t, l2SafeHead.Number.Uint64(), testCfg.CheckResult, testCfg.InputParams...) ++} ++ ++func Test_ProgramAction_SimpleEmptyChain(gt *testing.T) { ++ matrix := helpers.NewMatrix[any]() ++ defer matrix.Run(gt) ++ ++ matrix.AddTestCase( ++ "HonestClaim", ++ nil, ++ helpers.LatestForkOnly, ++ runSimpleProgramTest, ++ helpers.ExpectNoError(), ++ ) ++ matrix.AddTestCase( ++ "JunkClaim", ++ nil, ++ helpers.LatestForkOnly, ++ runSimpleProgramTest, ++ helpers.ExpectError(claim.ErrClaimNotValid), ++ helpers.WithL2Claim(common.HexToHash("0xdeadbeef")), ++ ) ++}
@@ -15866,13 +66181,13 @@
- OP + (new)
@@ -15882,70 +66197,84 @@
-
+13
-
-3
+
+12
+
-10
-
diff --git OP/op-chain-ops/genesis/config.go CELO/op-chain-ops/genesis/config.go -index 0fc628727fe681e8c2040f456b9ef180c1bdd5b9..cf72fce00894eea7ba649f6ba99cb581f0286b34 100644 ---- OP/op-chain-ops/genesis/config.go -+++ CELO/op-chain-ops/genesis/config.go -@@ -271,9 +271,11 @@ var _ ConfigChecker = (*GasTokenDeployConfig)(nil) +
diff --git OP/op-e2e/actions/l2_proposer_test.go CELO/op-e2e/actions/proposer/l2_proposer_test.go +rename from op-e2e/actions/l2_proposer_test.go +rename to op-e2e/actions/proposer/l2_proposer_test.go +index bed138cdb3a71384ad872a13f4b246c706bfd5c1..a75ece69b080df82422d0405ec278b6da022849b 100644 +--- OP/op-e2e/actions/l2_proposer_test.go ++++ CELO/op-e2e/actions/proposer/l2_proposer_test.go +@@ -1,10 +1,12 @@ +-package actions ++package proposer   - func (d *GasTokenDeployConfig) Check(log log.Logger) error { - if d.UseCustomGasToken { -- if d.CustomGasTokenAddress == (common.Address{}) { -- return fmt.Errorf("%w: CustomGasTokenAddress cannot be address(0)", ErrInvalidDeployConfig) -- } -+ // NOTE: we are using the address(0) as an instruction to deploy the L1 token, -+ // so this deploy-config validation has to be disabled -+ // if d.CustomGasTokenAddress == (common.Address{}) { -+ // return fmt.Errorf("%w: CustomGasTokenAddress cannot be address(0)", ErrInvalidDeployConfig) -+ // } - log.Info("Using custom gas token", "address", d.CustomGasTokenAddress) - } - return nil -@@ -308,6 +310,8 @@ // EIP1559Denominator is the denominator of EIP1559 base fee market. - EIP1559Denominator uint64 `json:"eip1559Denominator"` - // EIP1559DenominatorCanyon is the denominator of EIP1559 base fee market when Canyon is active. - EIP1559DenominatorCanyon uint64 `json:"eip1559DenominatorCanyon"` -+ // EIP1559BaseFeeFloor is the fixed floor for the EIP1559 base fee market. -+ EIP1559BaseFeeFloor uint64 `json:"eip1559BaseFeeFloor,omitempty"` + import ( + "math/big" + "testing" + "time" +  ++ actionsHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" ++ upgradesHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/upgrades/helpers" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" +@@ -44,24 +46,24 @@ } }   - var _ ConfigChecker = (*EIP1559DeployConfig)(nil) -@@ -821,6 +825,11 @@ L1DependenciesConfig + func RunProposerTest(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { +- t := NewDefaultTesting(gt) +- dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) +- applyDeltaTimeOffset(dp, deltaTimeOffset) +- sd := e2eutils.Setup(t, dp, defaultAlloc) ++ t := actionsHelpers.NewDefaultTesting(gt) ++ dp := e2eutils.MakeDeployParams(t, actionsHelpers.DefaultRollupTestParams) ++ upgradesHelpers.ApplyDeltaTimeOffset(dp, deltaTimeOffset) ++ sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) + log := testlog.Logger(t, log.LevelDebug) +- miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) ++ miner, seqEngine, sequencer := actionsHelpers.SetupSequencerTest(t, sd, log)   - // Legacy, ignored, here for strict-JSON decoding to be accepted. - LegacyDeployConfig -+ // UseInterop is a flag that indicates if the system is using interop -+ UseInterop bool `json:"useInterop,omitempty"` -+ -+ // DeployCeloContracts indicates whether to deploy Celo contracts. -+ DeployCeloContracts bool `json:"deployCeloContracts"` - } + rollupSeqCl := sequencer.RollupClient() +- batcher := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp), ++ batcher := actionsHelpers.NewL2Batcher(log, sd.RollupCfg, actionsHelpers.DefaultBatcherCfg(dp), + rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg))   - // Copy will deeply copy the DeployConfig. This does a JSON roundtrip to copy -@@ -929,6 +938,7 @@ FjordTime: d.FjordTime(l1StartBlock.Time()), - GraniteTime: d.GraniteTime(l1StartBlock.Time()), - InteropTime: d.InteropTime(l1StartBlock.Time()), - AltDAConfig: altDA, -+ Cel2Time: d.RegolithTime(l1StartBlock.Time()), - }, nil - } -
+- var proposer *L2Proposer ++ var proposer *actionsHelpers.L2Proposer + if e2eutils.UseFaultProofs() { + optimismPortal2Contract, err := bindingspreview.NewOptimismPortal2(sd.DeploymentsL1.OptimismPortalProxy, miner.EthClient()) + require.NoError(t, err) + respectedGameType, err := optimismPortal2Contract.RespectedGameType(&bind.CallOpts{}) + require.NoError(t, err) +- proposer = NewL2Proposer(t, log, &ProposerCfg{ ++ proposer = actionsHelpers.NewL2Proposer(t, log, &actionsHelpers.ProposerCfg{ + DisputeGameFactoryAddr: &sd.DeploymentsL1.DisputeGameFactoryProxy, + ProposalInterval: 6 * time.Second, + ProposalRetryInterval: 3 * time.Second, +@@ -70,7 +72,7 @@ ProposerKey: dp.Secrets.Proposer, + AllowNonFinalized: true, + }, miner.EthClient(), rollupSeqCl) + } else { +- proposer = NewL2Proposer(t, log, &ProposerCfg{ ++ proposer = actionsHelpers.NewL2Proposer(t, log, &actionsHelpers.ProposerCfg{ + OutputOracleAddr: &sd.DeploymentsL1.L2OutputOracleProxy, + ProposerKey: dp.Secrets.Proposer, + ProposalRetryInterval: 3 * time.Second,
@@ -15954,13 +66283,13 @@
- OP + (new)
@@ -15970,49 +66299,66 @@
-
+4
-
-1
+
+38
+
-0
-
diff --git OP/op-chain-ops/genesis/genesis.go CELO/op-chain-ops/genesis/genesis.go -index f517912e109a714935c0be7ed0ca5561e396fcc8..621362f52e0d33c04a1c1416a4e9c57c94b85a11 100644 ---- OP/op-chain-ops/genesis/genesis.go -+++ CELO/op-chain-ops/genesis/genesis.go -@@ -39,7 +39,6 @@ eip1559Elasticity := config.EIP1559Elasticity - if eip1559Elasticity == 0 { - eip1559Elasticity = 10 - } -- - optimismChainConfig := params.ChainConfig{ - ChainID: new(big.Int).SetUint64(config.L2ChainID), - HomesteadBlock: big.NewInt(0), -@@ -69,10 +68,14 @@ EcotoneTime: config.EcotoneTime(block.Time()), - FjordTime: config.FjordTime(block.Time()), - GraniteTime: config.GraniteTime(block.Time()), - InteropTime: config.InteropTime(block.Time()), -+ Cel2Time: config.RegolithTime(block.Time()), - Optimism: &params.OptimismConfig{ - EIP1559Denominator: eip1559Denom, - EIP1559Elasticity: eip1559Elasticity, - EIP1559DenominatorCanyon: &eip1559DenomCanyon, -+ }, -+ Celo: &params.CeloConfig{ -+ EIP1559BaseFeeFloor: config.EIP1559BaseFeeFloor, - }, - } -
+
diff --git OP/op-e2e/actions/safedb/helpers/setups.go CELO/op-e2e/actions/safedb/helpers/setups.go +new file mode 100644 +index 0000000000000000000000000000000000000000..fcc70f494a747c264f35364cc5a2f7f57a8c39eb +--- /dev/null ++++ CELO/op-e2e/actions/safedb/helpers/setups.go +@@ -0,0 +1,38 @@ ++package helpers ++ ++import ( ++ "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" ++ "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" ++ "github.com/ethereum-optimism/optimism/op-node/node/safedb" ++ "github.com/ethereum-optimism/optimism/op-node/rollup/sync" ++ "github.com/ethereum-optimism/optimism/op-service/testlog" ++ "github.com/ethereum/go-ethereum/common" ++ "github.com/ethereum/go-ethereum/log" ++ "github.com/stretchr/testify/require" ++) ++ ++func SetupSafeDBTest(t helpers.Testing, config *e2eutils.TestParams) (*e2eutils.SetupData, *helpers.L1Miner, *helpers.L2Sequencer, *helpers.L2Verifier, *helpers.L2Engine, *helpers.L2Batcher) { ++ dp := e2eutils.MakeDeployParams(t, config) ++ ++ sd := e2eutils.Setup(t, dp, helpers.DefaultAlloc) ++ logger := testlog.Logger(t, log.LevelDebug) ++ ++ return SetupSafeDBTestActors(t, dp, sd, logger) ++} ++ ++func SetupSafeDBTestActors(t helpers.Testing, dp *e2eutils.DeployParams, sd *e2eutils.SetupData, log log.Logger) (*e2eutils.SetupData, *helpers.L1Miner, *helpers.L2Sequencer, *helpers.L2Verifier, *helpers.L2Engine, *helpers.L2Batcher) { ++ dir := t.TempDir() ++ db, err := safedb.NewSafeDB(log, dir) ++ require.NoError(t, err) ++ t.Cleanup(func() { ++ _ = db.Close() ++ }) ++ miner, seqEngine, sequencer := helpers.SetupSequencerTest(t, sd, log) ++ miner.ActL1SetFeeRecipient(common.Address{'A'}) ++ sequencer.ActL2PipelineFull(t) ++ verifEngine, verifier := helpers.SetupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}, helpers.WithSafeHeadListener(db)) ++ rollupSeqCl := sequencer.RollupClient() ++ batcher := helpers.NewL2Batcher(log, sd.RollupCfg, helpers.DefaultBatcherCfg(dp), ++ rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) ++ return sd, miner, sequencer, verifier, verifEngine, batcher ++}
@@ -16021,13 +66367,13 @@
- OP + (new)
@@ -16037,35 +66383,140 @@
-
+3
-
-1
+
+11
+
-40
-
diff --git OP/op-chain-ops/genesis/testdata/test-deploy-config-full.json CELO/op-chain-ops/genesis/testdata/test-deploy-config-full.json -index dfe420b2b7f44bc785e627da1fa8e350340c7ac8..3138d293d1133121f5d98bac47cfd55395a88f28 100644 ---- OP/op-chain-ops/genesis/testdata/test-deploy-config-full.json -+++ CELO/op-chain-ops/genesis/testdata/test-deploy-config-full.json -@@ -92,5 +92,7 @@ "daCommitmentType": "KeccakCommitment", - "daChallengeProxy": "0x0000000000000000000000000000000000000000", - "daChallengeWindow": 0, - "daResolveWindow": 0, -- "daResolverRefundPercentage": 0 -+ "daResolverRefundPercentage": 0, -+ "deployCeloContracts": false, -+ "eip1559BaseFeeFloor": 5000000000 - }
+
diff --git OP/op-e2e/actions/safedb_test.go CELO/op-e2e/actions/safedb/safedb_test.go +rename from op-e2e/actions/safedb_test.go +rename to op-e2e/actions/safedb/safedb_test.go +index 9fd570fa79f5b4daae3dab30ff6dd95c4c106042..369825e46263cb57a55fbf2b4b42c59dd64adf23 100644 +--- OP/op-e2e/actions/safedb_test.go ++++ CELO/op-e2e/actions/safedb/safedb_test.go +@@ -1,23 +1,20 @@ +-package actions ++package safedb +  + import ( + "context" + "testing" +  +- "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" +- "github.com/ethereum-optimism/optimism/op-node/node/safedb" +- "github.com/ethereum-optimism/optimism/op-node/rollup/sync" ++ actionsHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" ++ "github.com/ethereum-optimism/optimism/op-e2e/actions/safedb/helpers" + "github.com/ethereum-optimism/optimism/op-service/eth" +- "github.com/ethereum-optimism/optimism/op-service/testlog" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" +- "github.com/ethereum/go-ethereum/log" + "github.com/stretchr/testify/require" + ) +  + func TestRecordSafeHeadUpdates(gt *testing.T) { +- t := NewDefaultTesting(gt) +- sd, miner, sequencer, verifier, verifierEng, batcher := setupSafeDBTest(t, defaultRollupTestParams) ++ t := actionsHelpers.NewDefaultTesting(gt) ++ sd, miner, sequencer, verifier, verifierEng, batcher := helpers.SetupSafeDBTest(t, actionsHelpers.DefaultRollupTestParams) + verifEngClient := verifierEng.EngineClient(t, sd.RollupCfg) +  + sequencer.ActL2PipelineFull(t) +@@ -36,7 +33,7 @@ + // new L1 block with L2 batch + miner.ActL1StartBlock(12)(t) + miner.ActL1IncludeTx(sd.RollupCfg.Genesis.SystemConfig.BatcherAddr)(t) +- batchTx := miner.l1Transactions[0] ++ batchTx := miner.L1Transactions[0] + miner.ActL1EndBlock(t) +  + // verifier picks up the L2 chain that was submitted +@@ -46,7 +43,7 @@ require.Equal(t, verifier.L2Safe(), sequencer.L2Unsafe(), "verifier syncs from sequencer via L1") + require.NotEqual(t, sequencer.L2Safe(), sequencer.L2Unsafe(), "sequencer has not processed L1 yet") +  + // Verify the safe head is recorded +- l1Head := miner.l1Chain.CurrentBlock() ++ l1Head := miner.L1Chain().CurrentBlock() + firstSafeHeadUpdateL1Block := l1Head.Number.Uint64() + response, err := verifier.RollupClient().SafeHeadAtL1Block(context.Background(), firstSafeHeadUpdateL1Block) + require.NoError(t, err) +@@ -62,7 +59,7 @@ + // Only genesis is safe at this point + response, err = verifier.RollupClient().SafeHeadAtL1Block(context.Background(), firstSafeHeadUpdateL1Block-1) + require.NoError(t, err) +- require.Equal(t, eth.HeaderBlockID(miner.l1Chain.Genesis().Header()), response.L1Block) ++ require.Equal(t, eth.HeaderBlockID(miner.L1Chain().Genesis().Header()), response.L1Block) + require.Equal(t, sd.RollupCfg.Genesis.L2, response.SafeHead) +  + // orphan the L1 block that included the batch tx, and build a new different L1 block +@@ -83,7 +80,7 @@ + // The safe head has been reorged so the record should have been deleted, leaving us back with just genesis safe + response, err = verifier.RollupClient().SafeHeadAtL1Block(context.Background(), firstSafeHeadUpdateL1Block) + require.NoError(t, err) +- require.Equal(t, eth.HeaderBlockID(miner.l1Chain.Genesis().Header()), response.L1Block) ++ require.Equal(t, eth.HeaderBlockID(miner.L1Chain().Genesis().Header()), response.L1Block) + require.Equal(t, sd.RollupCfg.Genesis.L2, response.SafeHead) +  + // Now replay the batch tx in a new L1 block +@@ -91,7 +88,7 @@ miner.ActL1StartBlock(12)(t) + miner.ActL1SetFeeRecipient(common.Address{'C'}) + // note: the geth tx pool reorgLoop is too slow (responds to chain head events, but async), + // and there's no way to manually trigger runReorg, so we re-insert it ourselves. +- require.NoError(t, miner.eth.TxPool().Add([]*types.Transaction{batchTx}, true, true)[0]) ++ require.NoError(t, miner.Eth.TxPool().Add([]*types.Transaction{batchTx}, true, true)[0]) + // need to re-insert previously included tx into the block + miner.ActL1IncludeTx(sd.RollupCfg.Genesis.SystemConfig.BatcherAddr)(t) + miner.ActL1EndBlock(t) +@@ -105,36 +102,10 @@ require.NoError(t, err) + require.Equal(t, verifier.L2Safe(), ref, "verifier engine matches rollup client") +  + // Verify the safe head is recorded again +- l1Head = miner.l1Chain.CurrentBlock() ++ l1Head = miner.L1Chain().CurrentBlock() + firstSafeHeadUpdateL1Block = l1Head.Number.Uint64() + response, err = verifier.RollupClient().SafeHeadAtL1Block(context.Background(), firstSafeHeadUpdateL1Block) + require.NoError(t, err) + require.Equal(t, eth.HeaderBlockID(l1Head), response.L1Block) + require.Equal(t, verifier.L2Unsafe().ID(), response.SafeHead) + } +- +-func setupSafeDBTest(t Testing, config *e2eutils.TestParams) (*e2eutils.SetupData, *L1Miner, *L2Sequencer, *L2Verifier, *L2Engine, *L2Batcher) { +- dp := e2eutils.MakeDeployParams(t, config) +- +- sd := e2eutils.Setup(t, dp, defaultAlloc) +- logger := testlog.Logger(t, log.LevelDebug) +- +- return setupSafeDBTestActors(t, dp, sd, logger) +-} +- +-func setupSafeDBTestActors(t Testing, dp *e2eutils.DeployParams, sd *e2eutils.SetupData, log log.Logger) (*e2eutils.SetupData, *L1Miner, *L2Sequencer, *L2Verifier, *L2Engine, *L2Batcher) { +- dir := t.TempDir() +- db, err := safedb.NewSafeDB(log, dir) +- require.NoError(t, err) +- t.Cleanup(func() { +- _ = db.Close() +- }) +- miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) +- miner.ActL1SetFeeRecipient(common.Address{'A'}) +- sequencer.ActL2PipelineFull(t) +- verifEngine, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}, WithSafeHeadListener(db)) +- rollupSeqCl := sequencer.RollupClient() +- batcher := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp), +- rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) +- return sd, miner, sequencer, verifier, verifEngine, batcher +-}
@@ -16080,7 +66531,7 @@
@@ -16090,111 +66541,145 @@
-
+16
-
-0
+
+12
+
-48
-
diff --git OP/op-chain-ops/justfile CELO/op-chain-ops/justfile -new file mode 100644 -index 0000000000000000000000000000000000000000..b4b6886b4e6411e49fc4c86f9fca7f5e176cd2a6 ---- /dev/null -+++ CELO/op-chain-ops/justfile -@@ -0,0 +1,16 @@ -+abis := '../packages/contracts-bedrock/snapshots/abi' -+ -+bindings-celo-migrate: -+ #!/usr/bin/env bash -+ set -euxo pipefail -+ -+ build_abi() { -+ local lowercase=$(echo "$2" | awk '{print tolower($0)}') -+ abigen \ -+ --abi "{{abis}}/$1.json" \ -+ --pkg bindings \ -+ --out "cmd/celo-migrate/bindings/$lowercase.go" \ -+ --type $2 -+ } -+ -+ build_abi GoldToken CeloToken
- - - - - -
- -
- - - - -
- -
-
-
- - -
-
- -
-
-
- - -
-
-
-
@@ -16203,13 +66688,13 @@
- OP + (new)
@@ -16219,44 +66704,595 @@
-
+2
-
-2
+
+123
+
-107
-
diff --git OP/op-e2e/actions/l2_batcher.go CELO/op-e2e/actions/l2_batcher.go -index 42fe7c8b2bcdbf2fe72fad0f49d36cfc77aafc8e..d770429c31d9d289dcfe170ca9dfc8aca10389ca 100644 ---- OP/op-e2e/actions/l2_batcher.go -+++ CELO/op-e2e/actions/l2_batcher.go -@@ -278,7 +278,7 @@ for _, opt := range txOpts { - opt(rawTx) - } +
diff --git OP/op-e2e/actions/sync_test.go CELO/op-e2e/actions/sync/sync_test.go +rename from op-e2e/actions/sync_test.go +rename to op-e2e/actions/sync/sync_test.go +index 78297a5a8135950f16de599fa7eaa949871cde19..a39185f627058be207b5cd622646c2036237f5c5 100644 +--- OP/op-e2e/actions/sync_test.go ++++ CELO/op-e2e/actions/sync/sync_test.go +@@ -1,4 +1,4 @@ +-package actions ++package sync +  + import ( + "errors" +@@ -8,6 +8,8 @@ "strings" + "testing" + "time" +  ++ actionsHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" ++ upgradesHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/upgrades/helpers" + "github.com/stretchr/testify/require" +  + "github.com/ethereum/go-ethereum" +@@ -32,8 +34,8 @@ "github.com/ethereum-optimism/optimism/op-service/testlog" + "github.com/ethereum-optimism/optimism/op-service/testutils" + ) +  +-func newSpanChannelOut(t StatefulTesting, e e2eutils.SetupData) derive.ChannelOut { +- channelOut, err := derive.NewSpanChannelOut(e.RollupCfg.Genesis.L2Time, e.RollupCfg.L2ChainID, 128_000, derive.Zlib, rollup.NewChainSpec(e.RollupCfg)) ++func newSpanChannelOut(t actionsHelpers.StatefulTesting, e e2eutils.SetupData) derive.ChannelOut { ++ channelOut, err := derive.NewSpanChannelOut(128_000, derive.Zlib, rollup.NewChainSpec(e.RollupCfg)) + require.NoError(t, err) + return channelOut + } +@@ -64,12 +66,12 @@ } + } +  + func DerivationWithFlakyL1RPC(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { +- t := NewDefaultTesting(gt) +- dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) +- applyDeltaTimeOffset(dp, deltaTimeOffset) +- sd := e2eutils.Setup(t, dp, defaultAlloc) ++ t := actionsHelpers.NewDefaultTesting(gt) ++ dp := e2eutils.MakeDeployParams(t, actionsHelpers.DefaultRollupTestParams) ++ upgradesHelpers.ApplyDeltaTimeOffset(dp, deltaTimeOffset) ++ sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) + log := testlog.Logger(t, log.LevelError) // mute all the temporary derivation errors that we forcefully create +- _, _, miner, sequencer, _, verifier, _, batcher := setupReorgTestActors(t, dp, sd, log) ++ _, _, miner, sequencer, _, verifier, _, batcher := actionsHelpers.SetupReorgTestActors(t, dp, sd, log) +  + rng := rand.New(rand.NewSource(1234)) + sequencer.ActL2PipelineFull(t) +@@ -83,7 +85,7 @@ sequencer.ActL2PipelineFull(t) + sequencer.ActBuildToL1Head(t) + batcher.ActSubmitAll(t) + miner.ActL1StartBlock(12)(t) +- miner.ActL1IncludeTx(batcher.batcherAddr)(t) ++ miner.ActL1IncludeTx(batcher.BatcherAddr)(t) + miner.ActL1EndBlock(t) + } + // Make verifier aware of head +@@ -104,12 +106,12 @@ require.Equal(t, sequencer.L2Unsafe(), verifier.L2Safe(), "verifier is synced") + } +  + func FinalizeWhileSyncing(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { +- t := NewDefaultTesting(gt) +- dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) +- applyDeltaTimeOffset(dp, deltaTimeOffset) +- sd := e2eutils.Setup(t, dp, defaultAlloc) ++ t := actionsHelpers.NewDefaultTesting(gt) ++ dp := e2eutils.MakeDeployParams(t, actionsHelpers.DefaultRollupTestParams) ++ upgradesHelpers.ApplyDeltaTimeOffset(dp, deltaTimeOffset) ++ sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) + log := testlog.Logger(t, log.LevelError) // mute all the temporary derivation errors that we forcefully create +- _, _, miner, sequencer, _, verifier, _, batcher := setupReorgTestActors(t, dp, sd, log) ++ _, _, miner, sequencer, _, verifier, _, batcher := actionsHelpers.SetupReorgTestActors(t, dp, sd, log) +  + sequencer.ActL2PipelineFull(t) + verifier.ActL2PipelineFull(t) +@@ -126,10 +128,10 @@ sequencer.ActL2PipelineFull(t) + sequencer.ActBuildToL1Head(t) + batcher.ActSubmitAll(t) + miner.ActL1StartBlock(12)(t) +- miner.ActL1IncludeTx(batcher.batcherAddr)(t) ++ miner.ActL1IncludeTx(batcher.BatcherAddr)(t) + miner.ActL1EndBlock(t) + } +- l1Head := miner.l1Chain.CurrentHeader() ++ l1Head := miner.L1Chain().CurrentHeader() + // finalize all of L1 + miner.ActL1Safe(t, l1Head.Number.Uint64()) + miner.ActL1Finalize(t, l1Head.Number.Uint64()) +@@ -150,12 +152,12 @@ } +  + // TestUnsafeSync tests that a verifier properly imports unsafe blocks via gossip. + func TestUnsafeSync(gt *testing.T) { +- t := NewDefaultTesting(gt) +- dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) +- sd := e2eutils.Setup(t, dp, defaultAlloc) ++ t := actionsHelpers.NewDefaultTesting(gt) ++ dp := e2eutils.MakeDeployParams(t, actionsHelpers.DefaultRollupTestParams) ++ sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) + log := testlog.Logger(t, log.LevelInfo) +  +- sd, _, _, sequencer, seqEng, verifier, _, _ := setupReorgTestActors(t, dp, sd, log) ++ sd, _, _, sequencer, seqEng, verifier, _, _ := actionsHelpers.SetupReorgTestActors(t, dp, sd, log) + seqEngCl, err := sources.NewEngineClient(seqEng.RPCClient(), log, nil, sources.EngineClientDefaultConfig(sd.RollupCfg)) + require.NoError(t, err) +  +@@ -178,15 +180,15 @@ } + } +  + func TestBackupUnsafe(gt *testing.T) { +- t := NewDefaultTesting(gt) +- dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) ++ t := actionsHelpers.NewDefaultTesting(gt) ++ dp := e2eutils.MakeDeployParams(t, actionsHelpers.DefaultRollupTestParams) + minTs := hexutil.Uint64(0) + // Activate Delta hardfork +- applyDeltaTimeOffset(dp, &minTs) ++ upgradesHelpers.ApplyDeltaTimeOffset(dp, &minTs) + dp.DeployConfig.L2BlockTime = 2 +- sd := e2eutils.Setup(t, dp, defaultAlloc) ++ sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) + log := testlog.Logger(t, log.LvlInfo) +- _, dp, miner, sequencer, seqEng, verifier, _, batcher := setupReorgTestActors(t, dp, sd, log) ++ _, dp, miner, sequencer, seqEng, verifier, _, batcher := actionsHelpers.SetupReorgTestActors(t, dp, sd, log) + l2Cl := seqEng.EthClient() + seqEngCl, err := sources.NewEngineClient(seqEng.RPCClient(), log, nil, sources.EngineClientDefaultConfig(sd.RollupCfg)) + require.NoError(t, err) +@@ -238,7 +240,7 @@ validTx := types.MustSignNewTx(dp.Secrets.Alice, signer, &types.DynamicFeeTx{ + ChainID: sd.L2Cfg.Config.ChainID, + Nonce: n, + GasTipCap: big.NewInt(2 * params.GWei), +- GasFeeCap: new(big.Int).Add(miner.l1Chain.CurrentBlock().BaseFee, big.NewInt(2*params.GWei)), ++ GasFeeCap: new(big.Int).Add(miner.L1Chain().CurrentBlock().BaseFee, big.NewInt(2*params.GWei)), + Gas: params.TxGas, + To: &dp.Addresses.Bob, + Value: e2eutils.Ether(2), +@@ -256,7 +258,7 @@ require.NoError(t, err) + } +  + // Submit span batch(A1, B2, invalid B3, B4, B5) +- batcher.l2ChannelOut = channelOut ++ batcher.L2ChannelOut = channelOut + batcher.ActL2ChannelClose(t) + batcher.ActL2BatchSubmit(t) +  +@@ -339,15 +341,15 @@ require.Equal(t, eth.L2BlockRef{}, verifier.L2BackupUnsafe()) + } +  + func TestBackupUnsafeReorgForkChoiceInputError(gt *testing.T) { +- t := NewDefaultTesting(gt) +- dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) ++ t := actionsHelpers.NewDefaultTesting(gt) ++ dp := e2eutils.MakeDeployParams(t, actionsHelpers.DefaultRollupTestParams) + minTs := hexutil.Uint64(0) + // Activate Delta hardfork +- applyDeltaTimeOffset(dp, &minTs) ++ upgradesHelpers.ApplyDeltaTimeOffset(dp, &minTs) + dp.DeployConfig.L2BlockTime = 2 +- sd := e2eutils.Setup(t, dp, defaultAlloc) ++ sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) + log := testlog.Logger(t, log.LvlInfo) +- _, dp, miner, sequencer, seqEng, verifier, _, batcher := setupReorgTestActors(t, dp, sd, log) ++ _, dp, miner, sequencer, seqEng, verifier, _, batcher := actionsHelpers.SetupReorgTestActors(t, dp, sd, log) + l2Cl := seqEng.EthClient() + seqEngCl, err := sources.NewEngineClient(seqEng.RPCClient(), log, nil, sources.EngineClientDefaultConfig(sd.RollupCfg)) + require.NoError(t, err) +@@ -399,7 +401,7 @@ validTx := types.MustSignNewTx(dp.Secrets.Alice, signer, &types.DynamicFeeTx{ + ChainID: sd.L2Cfg.Config.ChainID, + Nonce: n, + GasTipCap: big.NewInt(2 * params.GWei), +- GasFeeCap: new(big.Int).Add(miner.l1Chain.CurrentBlock().BaseFee, big.NewInt(2*params.GWei)), ++ GasFeeCap: new(big.Int).Add(miner.L1Chain().CurrentBlock().BaseFee, big.NewInt(2*params.GWei)), + Gas: params.TxGas, + To: &dp.Addresses.Bob, + Value: e2eutils.Ether(2), +@@ -417,7 +419,7 @@ require.NoError(t, err) + } +  + // Submit span batch(A1, B2, invalid B3, B4, B5) +- batcher.l2ChannelOut = channelOut ++ batcher.L2ChannelOut = channelOut + batcher.ActL2ChannelClose(t) + batcher.ActL2BatchSubmit(t) +  +@@ -472,15 +474,15 @@ require.Equal(t, sequencer.L2Safe().Number, uint64(0)) + } +  + func TestBackupUnsafeReorgForkChoiceNotInputError(gt *testing.T) { +- t := NewDefaultTesting(gt) +- dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) ++ t := actionsHelpers.NewDefaultTesting(gt) ++ dp := e2eutils.MakeDeployParams(t, actionsHelpers.DefaultRollupTestParams) + minTs := hexutil.Uint64(0) + // Activate Delta hardfork +- applyDeltaTimeOffset(dp, &minTs) ++ upgradesHelpers.ApplyDeltaTimeOffset(dp, &minTs) + dp.DeployConfig.L2BlockTime = 2 +- sd := e2eutils.Setup(t, dp, defaultAlloc) ++ sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) + log := testlog.Logger(t, log.LvlInfo) +- _, dp, miner, sequencer, seqEng, verifier, _, batcher := setupReorgTestActors(t, dp, sd, log) ++ _, dp, miner, sequencer, seqEng, verifier, _, batcher := actionsHelpers.SetupReorgTestActors(t, dp, sd, log) + l2Cl := seqEng.EthClient() + seqEngCl, err := sources.NewEngineClient(seqEng.RPCClient(), log, nil, sources.EngineClientDefaultConfig(sd.RollupCfg)) + require.NoError(t, err) +@@ -532,7 +534,7 @@ validTx := types.MustSignNewTx(dp.Secrets.Alice, signer, &types.DynamicFeeTx{ + ChainID: sd.L2Cfg.Config.ChainID, + Nonce: n, + GasTipCap: big.NewInt(2 * params.GWei), +- GasFeeCap: new(big.Int).Add(miner.l1Chain.CurrentBlock().BaseFee, big.NewInt(2*params.GWei)), ++ GasFeeCap: new(big.Int).Add(miner.L1Chain().CurrentBlock().BaseFee, big.NewInt(2*params.GWei)), + Gas: params.TxGas, + To: &dp.Addresses.Bob, + Value: e2eutils.Ether(2), +@@ -550,7 +552,7 @@ require.NoError(t, err) + } +  + // Submit span batch(A1, B2, invalid B3, B4, B5) +- batcher.l2ChannelOut = channelOut ++ batcher.L2ChannelOut = channelOut + batcher.ActL2ChannelClose(t) + batcher.ActL2BatchSubmit(t) +  +@@ -587,7 +589,7 @@ sequencer.ActL2EventsUntil(t, event.Is[engine2.BuildStartEvent], 100, true) +  + serverErrCnt := 2 + // mock forkChoiceUpdate failure while restoring previous unsafe chain using backupUnsafe. +- seqEng.failL2RPC = func(call []rpc.BatchElem) error { ++ seqEng.FailL2RPC = func(call []rpc.BatchElem) error { + for _, e := range call { + // There may be other calls, like payload-processing-cancellation + // based on previous invalid block, and processing of block attributes. +@@ -625,7 +627,7 @@ + // builds l2 blocks within the specified range `from` - `to` + // and performs an EL sync between the sequencer and the verifier, + // then checks the validity of the payloads within a specified block range. +-func PerformELSyncAndCheckPayloads(t Testing, miner *L1Miner, seqEng *L2Engine, sequencer *L2Sequencer, verEng *L2Engine, verifier *L2Verifier, seqEngCl *sources.EngineClient, from, to uint64) { ++func PerformELSyncAndCheckPayloads(t actionsHelpers.Testing, miner *actionsHelpers.L1Miner, seqEng *actionsHelpers.L2Engine, sequencer *actionsHelpers.L2Sequencer, verEng *actionsHelpers.L2Engine, verifier *actionsHelpers.L2Verifier, seqEngCl *sources.EngineClient, from, to uint64) { + miner.ActEmptyBlock(t) + sequencer.ActL2PipelineFull(t) +  +@@ -658,7 +660,7 @@ // Expect snap sync to download & execute the entire chain + // Verify this by checking that the verifier has the correct value for block 1 + require.Eventually(t, + func() bool { +- block, err := verifier.eng.L2BlockRefByNumber(t.Ctx(), from) ++ block, err := verifier.Eng.L2BlockRefByNumber(t.Ctx(), from) + if err != nil { + return false + } +@@ -670,14 +672,14 @@ ) + } +  + // verifies that a specific block number on the L2 engine has the expected label. +-func VerifyBlock(t Testing, engine L2API, number uint64, label eth.BlockLabel) { ++func VerifyBlock(t actionsHelpers.Testing, engine actionsHelpers.L2API, number uint64, label eth.BlockLabel) { + id, err := engine.L2BlockRefByLabel(t.Ctx(), label) + require.NoError(t, err) + require.Equal(t, number, id.Number) + } +  + // submits batch at a specified block number +-func BatchSubmitBlock(t Testing, miner *L1Miner, sequencer *L2Sequencer, verifier *L2Verifier, batcher *L2Batcher, dp *e2eutils.DeployParams, number uint64) { ++func BatchSubmitBlock(t actionsHelpers.Testing, miner *actionsHelpers.L1Miner, sequencer *actionsHelpers.L2Sequencer, verifier *actionsHelpers.L2Verifier, batcher *actionsHelpers.L2Batcher, dp *e2eutils.DeployParams, number uint64) { + sequencer.ActL2StartBlock(t) + sequencer.ActL2EndBlock(t) + batcher.ActSubmitAll(t) +@@ -691,14 +693,14 @@ + // TestELSync tests that a verifier will have the EL import the full chain from the sequencer + // when passed a single unsafe block. op-geth can either snap sync or full sync here. + func TestELSync(gt *testing.T) { +- t := NewDefaultTesting(gt) +- dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) +- sd := e2eutils.Setup(t, dp, defaultAlloc) ++ t := actionsHelpers.NewDefaultTesting(gt) ++ dp := e2eutils.MakeDeployParams(t, actionsHelpers.DefaultRollupTestParams) ++ sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) + log := testlog.Logger(t, log.LevelInfo) +  +- miner, seqEng, sequencer := setupSequencerTest(t, sd, log) ++ miner, seqEng, sequencer := actionsHelpers.SetupSequencerTest(t, sd, log) + // Enable engine P2P sync +- verEng, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{SyncMode: sync.ELSync}) ++ verEng, verifier := actionsHelpers.SetupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{SyncMode: sync.ELSync}) +  + seqEngCl, err := sources.NewEngineClient(seqEng.RPCClient(), log, nil, sources.EngineClientDefaultConfig(sd.RollupCfg)) + require.NoError(t, err) +@@ -706,11 +708,11 @@ + PerformELSyncAndCheckPayloads(t, miner, seqEng, sequencer, verEng, verifier, seqEngCl, 0, 10) + } +  +-func PrepareELSyncedNode(t Testing, miner *L1Miner, sequencer *L2Sequencer, seqEng *L2Engine, verifier *L2Verifier, verEng *L2Engine, seqEngCl *sources.EngineClient, batcher *L2Batcher, dp *e2eutils.DeployParams) { ++func PrepareELSyncedNode(t actionsHelpers.Testing, miner *actionsHelpers.L1Miner, sequencer *actionsHelpers.L2Sequencer, seqEng *actionsHelpers.L2Engine, verifier *actionsHelpers.L2Verifier, verEng *actionsHelpers.L2Engine, seqEngCl *sources.EngineClient, batcher *actionsHelpers.L2Batcher, dp *e2eutils.DeployParams) { + PerformELSyncAndCheckPayloads(t, miner, seqEng, sequencer, verEng, verifier, seqEngCl, 0, 10) +  + // Despite downloading the blocks, it has not finished finalizing +- _, err := verifier.eng.L2BlockRefByLabel(t.Ctx(), "safe") ++ _, err := verifier.Eng.L2BlockRefByLabel(t.Ctx(), "safe") + require.ErrorIs(t, err, ethereum.NotFound) +  + // Insert a block on the verifier to end snap sync +@@ -721,15 +723,15 @@ require.NoError(t, err) + verifier.ActL2InsertUnsafePayload(seqHead)(t) +  + // Check that safe + finalized are there +- VerifyBlock(t, verifier.eng, 11, eth.Safe) +- VerifyBlock(t, verifier.eng, 11, eth.Finalized) ++ VerifyBlock(t, verifier.Eng, 11, eth.Safe) ++ VerifyBlock(t, verifier.Eng, 11, eth.Finalized) +  + // Batch submit everything + BatchSubmitBlock(t, miner, sequencer, verifier, batcher, dp, 12) +  + // Verify that the batch submitted blocks are there now +- VerifyBlock(t, sequencer.eng, 12, eth.Safe) +- VerifyBlock(t, verifier.eng, 12, eth.Safe) ++ VerifyBlock(t, sequencer.Eng, 12, eth.Safe) ++ VerifyBlock(t, verifier.Eng, 12, eth.Safe) + } +  + // TestELSyncTransitionstoCL tests that a verifier which starts with EL sync can switch back to a proper CL sync. +@@ -744,17 +746,17 @@ // 7. Then gossip the rest of the blocks to the verifier. Once this is complete it should pick up all of the unsafe blocks. + // Prior to this PR, the test would fail at this point. + // 8. Create 1 more block & batch submit everything & assert that the verifier picked up those blocks + func TestELSyncTransitionstoCL(gt *testing.T) { +- t := NewDefaultTesting(gt) +- dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) +- sd := e2eutils.Setup(t, dp, defaultAlloc) ++ t := actionsHelpers.NewDefaultTesting(gt) ++ dp := e2eutils.MakeDeployParams(t, actionsHelpers.DefaultRollupTestParams) ++ sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) + logger := testlog.Logger(t, log.LevelInfo) +  + captureLog, captureLogHandler := testlog.CaptureLogger(t, log.LevelInfo) +  +- miner, seqEng, sequencer := setupSequencerTest(t, sd, logger) +- batcher := NewL2Batcher(logger, sd.RollupCfg, DefaultBatcherCfg(dp), sequencer.RollupClient(), miner.EthClient(), seqEng.EthClient(), seqEng.EngineClient(t, sd.RollupCfg)) ++ miner, seqEng, sequencer := actionsHelpers.SetupSequencerTest(t, sd, logger) ++ batcher := actionsHelpers.NewL2Batcher(logger, sd.RollupCfg, actionsHelpers.DefaultBatcherCfg(dp), sequencer.RollupClient(), miner.EthClient(), seqEng.EthClient(), seqEng.EngineClient(t, sd.RollupCfg)) + // Enable engine P2P sync +- verEng, verifier := setupVerifier(t, sd, captureLog, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{SyncMode: sync.ELSync}) ++ verEng, verifier := actionsHelpers.SetupVerifier(t, sd, captureLog, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{SyncMode: sync.ELSync}) +  + seqEngCl, err := sources.NewEngineClient(seqEng.RPCClient(), logger, nil, sources.EngineClientDefaultConfig(sd.RollupCfg)) + require.NoError(t, err) +@@ -790,28 +792,28 @@ // Verify that the unsafe blocks are there now + // This was failing prior to PR 9661 because op-node would attempt to immediately insert blocks into the EL inside the engine queue. op-geth + // would not be able to fetch the second range of blocks & it would wipe out the unsafe payloads queue because op-node thought that it had a + // higher unsafe block but op-geth did not. +- VerifyBlock(t, verifier.eng, 22, eth.Unsafe) ++ VerifyBlock(t, verifier.Eng, 22, eth.Unsafe) +  + // Create 1 more block & batch submit everything + BatchSubmitBlock(t, miner, sequencer, verifier, batcher, dp, 12) +  + // Verify that the batch submitted blocks are there now +- VerifyBlock(t, sequencer.eng, 23, eth.Safe) +- VerifyBlock(t, verifier.eng, 23, eth.Safe) ++ VerifyBlock(t, sequencer.Eng, 23, eth.Safe) ++ VerifyBlock(t, verifier.Eng, 23, eth.Safe) + } +  + func TestELSyncTransitionsToCLSyncAfterNodeRestart(gt *testing.T) { +- t := NewDefaultTesting(gt) +- dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) +- sd := e2eutils.Setup(t, dp, defaultAlloc) ++ t := actionsHelpers.NewDefaultTesting(gt) ++ dp := e2eutils.MakeDeployParams(t, actionsHelpers.DefaultRollupTestParams) ++ sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) + logger := testlog.Logger(t, log.LevelInfo) +  + captureLog, captureLogHandler := testlog.CaptureLogger(t, log.LevelInfo) +  +- miner, seqEng, sequencer := setupSequencerTest(t, sd, logger) +- batcher := NewL2Batcher(logger, sd.RollupCfg, DefaultBatcherCfg(dp), sequencer.RollupClient(), miner.EthClient(), seqEng.EthClient(), seqEng.EngineClient(t, sd.RollupCfg)) ++ miner, seqEng, sequencer := actionsHelpers.SetupSequencerTest(t, sd, logger) ++ batcher := actionsHelpers.NewL2Batcher(logger, sd.RollupCfg, actionsHelpers.DefaultBatcherCfg(dp), sequencer.RollupClient(), miner.EthClient(), seqEng.EthClient(), seqEng.EngineClient(t, sd.RollupCfg)) + // Enable engine P2P sync +- verEng, verifier := setupVerifier(t, sd, captureLog, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{SyncMode: sync.ELSync}) ++ verEng, verifier := actionsHelpers.SetupVerifier(t, sd, captureLog, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{SyncMode: sync.ELSync})   -- gas, err := core.IntrinsicGas(rawTx.Data, nil, false, true, true, false) -+ gas, err := core.IntrinsicGas(rawTx.Data, nil, false, true, true, false, nil, nil) - require.NoError(t, err, "need to compute intrinsic gas") - rawTx.Gas = gas - txData = rawTx -@@ -469,7 +469,7 @@ GasTipCap: gasTipCap, - GasFeeCap: gasFeeCap, - Data: outputFrame, + seqEngCl, err := sources.NewEngineClient(seqEng.RPCClient(), logger, nil, sources.EngineClientDefaultConfig(sd.RollupCfg)) + require.NoError(t, err) +@@ -819,7 +821,7 @@ + PrepareELSyncedNode(t, miner, sequencer, seqEng, verifier, verEng, seqEngCl, batcher, dp) +  + // Create a new verifier which is essentially a new op-node with the sync mode of ELSync and default geth engine kind. +- verifier = NewL2Verifier(t, captureLog, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), altda.Disabled, verifier.eng, sd.RollupCfg, &sync.Config{SyncMode: sync.ELSync}, defaultVerifierCfg().safeHeadListener) ++ verifier = actionsHelpers.NewL2Verifier(t, captureLog, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), altda.Disabled, verifier.Eng, sd.RollupCfg, &sync.Config{SyncMode: sync.ELSync}, actionsHelpers.DefaultVerifierCfg().SafeHeadListener, nil) +  + // Build another 10 L1 blocks on the sequencer + for i := 0; i < 10; i++ { +@@ -843,17 +845,17 @@ require.NotNil(t, record, "The verifier should skip EL Sync at this point.") + } +  + func TestForcedELSyncCLAfterNodeRestart(gt *testing.T) { +- t := NewDefaultTesting(gt) +- dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) +- sd := e2eutils.Setup(t, dp, defaultAlloc) ++ t := actionsHelpers.NewDefaultTesting(gt) ++ dp := e2eutils.MakeDeployParams(t, actionsHelpers.DefaultRollupTestParams) ++ sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) + logger := testlog.Logger(t, log.LevelInfo) +  + captureLog, captureLogHandler := testlog.CaptureLogger(t, log.LevelInfo) +  +- miner, seqEng, sequencer := setupSequencerTest(t, sd, logger) +- batcher := NewL2Batcher(logger, sd.RollupCfg, DefaultBatcherCfg(dp), sequencer.RollupClient(), miner.EthClient(), seqEng.EthClient(), seqEng.EngineClient(t, sd.RollupCfg)) ++ miner, seqEng, sequencer := actionsHelpers.SetupSequencerTest(t, sd, logger) ++ batcher := actionsHelpers.NewL2Batcher(logger, sd.RollupCfg, actionsHelpers.DefaultBatcherCfg(dp), sequencer.RollupClient(), miner.EthClient(), seqEng.EthClient(), seqEng.EngineClient(t, sd.RollupCfg)) + // Enable engine P2P sync +- verEng, verifier := setupVerifier(t, sd, captureLog, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{SyncMode: sync.ELSync}) ++ verEng, verifier := actionsHelpers.SetupVerifier(t, sd, captureLog, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{SyncMode: sync.ELSync}) +  + seqEngCl, err := sources.NewEngineClient(seqEng.RPCClient(), logger, nil, sources.EngineClientDefaultConfig(sd.RollupCfg)) + require.NoError(t, err) +@@ -861,7 +863,7 @@ + PrepareELSyncedNode(t, miner, sequencer, seqEng, verifier, verEng, seqEngCl, batcher, dp) +  + // Create a new verifier which is essentially a new op-node with the sync mode of ELSync and erigon engine kind. +- verifier2 := NewL2Verifier(t, captureLog, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), altda.Disabled, verifier.eng, sd.RollupCfg, &sync.Config{SyncMode: sync.ELSync, SupportsPostFinalizationELSync: true}, defaultVerifierCfg().safeHeadListener) ++ verifier2 := actionsHelpers.NewL2Verifier(t, captureLog, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), altda.Disabled, verifier.Eng, sd.RollupCfg, &sync.Config{SyncMode: sync.ELSync, SupportsPostFinalizationELSync: true}, actionsHelpers.DefaultVerifierCfg().SafeHeadListener, nil) +  + // Build another 10 L1 blocks on the sequencer + for i := 0; i < 10; i++ { +@@ -889,15 +891,15 @@ require.NotNil(t, record, "The verifier should start EL Sync when l2.engineKind is not geth") + } +  + func TestInvalidPayloadInSpanBatch(gt *testing.T) { +- t := NewDefaultTesting(gt) +- dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) ++ t := actionsHelpers.NewDefaultTesting(gt) ++ dp := e2eutils.MakeDeployParams(t, actionsHelpers.DefaultRollupTestParams) + minTs := hexutil.Uint64(0) + // Activate Delta hardfork +- applyDeltaTimeOffset(dp, &minTs) ++ upgradesHelpers.ApplyDeltaTimeOffset(dp, &minTs) + dp.DeployConfig.L2BlockTime = 2 +- sd := e2eutils.Setup(t, dp, defaultAlloc) ++ sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) + log := testlog.Logger(t, log.LevelInfo) +- _, _, miner, sequencer, seqEng, verifier, _, batcher := setupReorgTestActors(t, dp, sd, log) ++ _, _, miner, sequencer, seqEng, verifier, _, batcher := actionsHelpers.SetupReorgTestActors(t, dp, sd, log) + l2Cl := seqEng.EthClient() + rng := rand.New(rand.NewSource(1234)) + signer := types.LatestSigner(sd.L2Cfg.Config) +@@ -927,7 +929,7 @@ require.NoError(t, err) } -- gas, err := core.IntrinsicGas(rawTx.Data, nil, false, true, true, false) -+ gas, err := core.IntrinsicGas(rawTx.Data, nil, false, true, true, false, nil, nil) - require.NoError(t, err, "need to compute intrinsic gas") - rawTx.Gas = gas -
+  + // Submit span batch(A1, ..., A7, invalid A8, A9, ..., A12) +- batcher.l2ChannelOut = channelOut ++ batcher.L2ChannelOut = channelOut + batcher.ActL2ChannelClose(t) + batcher.ActL2BatchSubmit(t) +  +@@ -954,9 +956,9 @@ // Create valid TX + aliceNonce, err := seqEng.EthClient().PendingNonceAt(t.Ctx(), dp.Addresses.Alice) + require.NoError(t, err) + data := make([]byte, rand.Intn(100)) +- gas, err := core.IntrinsicGas(data, nil, false, true, true, false) ++ gas, err := core.IntrinsicGas(data, nil, false, true, true, false, nil, nil) + require.NoError(t, err) +- baseFee := seqEng.l2Chain.CurrentBlock().BaseFee ++ baseFee := seqEng.L2Chain().CurrentBlock().BaseFee + tx := types.MustSignNewTx(dp.Secrets.Alice, signer, &types.DynamicFeeTx{ + ChainID: sd.L2Cfg.Config.ChainID, + Nonce: aliceNonce, +@@ -975,7 +977,7 @@ err = channelOut.AddBlock(sd.RollupCfg, block) + require.NoError(t, err) + } + // Submit span batch(B1, A2, ... A12) +- batcher.l2ChannelOut = channelOut ++ batcher.L2ChannelOut = channelOut + batcher.ActL2ChannelClose(t) + batcher.ActL2BatchSubmit(t) +  +@@ -994,15 +996,15 @@ require.Equal(t, verifier.L2Safe().Number, uint64(12)) + } +  + func TestSpanBatchAtomicity_Consolidation(gt *testing.T) { +- t := NewDefaultTesting(gt) +- dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) ++ t := actionsHelpers.NewDefaultTesting(gt) ++ dp := e2eutils.MakeDeployParams(t, actionsHelpers.DefaultRollupTestParams) + minTs := hexutil.Uint64(0) + // Activate Delta hardfork +- applyDeltaTimeOffset(dp, &minTs) ++ upgradesHelpers.ApplyDeltaTimeOffset(dp, &minTs) + dp.DeployConfig.L2BlockTime = 2 +- sd := e2eutils.Setup(t, dp, defaultAlloc) ++ sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) + log := testlog.Logger(t, log.LevelInfo) +- _, _, miner, sequencer, seqEng, verifier, _, batcher := setupReorgTestActors(t, dp, sd, log) ++ _, _, miner, sequencer, seqEng, verifier, _, batcher := actionsHelpers.SetupReorgTestActors(t, dp, sd, log) + seqEngCl, err := sources.NewEngineClient(seqEng.RPCClient(), log, nil, sources.EngineClientDefaultConfig(sd.RollupCfg)) + require.NoError(t, err) +  +@@ -1036,15 +1038,22 @@ miner.ActL1EndBlock(t) +  + // Start verifier safe sync + verifier.ActL1HeadSignal(t) +- verifier.l2PipelineIdle = false +- for !verifier.l2PipelineIdle { ++ verifier.L2PipelineIdle = false ++ for !verifier.L2PipelineIdle { + // wait for next pending block +- verifier.ActL2EventsUntil(t, event.Any( +- event.Is[engine2.PendingSafeUpdateEvent], event.Is[derive.DeriverIdleEvent]), 1000, false) ++ verifier.ActL2EventsUntil(t, func(ev event.Event) bool { ++ if event.Is[engine2.SafeDerivedEvent](ev) { // safe updates should only happen once the pending-safe reaches the target. ++ t.Fatal("unexpected next safe update") ++ } ++ return event.Any(event.Is[engine2.PendingSafeUpdateEvent], event.Is[derive.DeriverIdleEvent])(ev) ++ }, 1000, false) + if verifier.L2PendingSafe().Number < targetHeadNumber { + // If the span batch is not fully processed, the safe head must not advance. + require.Equal(t, verifier.L2Safe().Number, uint64(0)) + } else { ++ // Make sure we do the post-processing of what safety updates might happen ++ // after the pending-safe event, before the next pending-safe event. ++ verifier.ActL2EventsUntil(t, event.Is[engine2.PendingSafeUpdateEvent], 100, true) + // Once the span batch is fully processed, the safe head must advance to the end of span batch. + require.Equal(t, verifier.L2Safe().Number, targetHeadNumber) + require.Equal(t, verifier.L2Safe(), verifier.L2PendingSafe()) +@@ -1055,15 +1064,15 @@ } + } +  + func TestSpanBatchAtomicity_ForceAdvance(gt *testing.T) { +- t := NewDefaultTesting(gt) +- dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) ++ t := actionsHelpers.NewDefaultTesting(gt) ++ dp := e2eutils.MakeDeployParams(t, actionsHelpers.DefaultRollupTestParams) + minTs := hexutil.Uint64(0) + // Activate Delta hardfork +- applyDeltaTimeOffset(dp, &minTs) ++ upgradesHelpers.ApplyDeltaTimeOffset(dp, &minTs) + dp.DeployConfig.L2BlockTime = 2 +- sd := e2eutils.Setup(t, dp, defaultAlloc) ++ sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) + log := testlog.Logger(t, log.LevelInfo) +- _, _, miner, sequencer, _, verifier, _, batcher := setupReorgTestActors(t, dp, sd, log) ++ _, _, miner, sequencer, _, verifier, _, batcher := actionsHelpers.SetupReorgTestActors(t, dp, sd, log) +  + targetHeadNumber := uint64(6) // L1 block time / L2 block time +  +@@ -1085,15 +1094,22 @@ miner.ActL1EndBlock(t) +  + // Start verifier safe sync + verifier.ActL1HeadSignal(t) +- verifier.l2PipelineIdle = false +- for !verifier.l2PipelineIdle { ++ verifier.L2PipelineIdle = false ++ for !verifier.L2PipelineIdle { + // wait for next pending block +- verifier.ActL2EventsUntil(t, event.Any( +- event.Is[engine2.PendingSafeUpdateEvent], event.Is[derive.DeriverIdleEvent]), 1000, false) ++ verifier.ActL2EventsUntil(t, func(ev event.Event) bool { ++ if event.Is[engine2.SafeDerivedEvent](ev) { // safe updates should only happen once the pending-safe reaches the target. ++ t.Fatal("unexpected next safe update") ++ } ++ return event.Any(event.Is[engine2.PendingSafeUpdateEvent], event.Is[derive.DeriverIdleEvent])(ev) ++ }, 1000, false) + if verifier.L2PendingSafe().Number < targetHeadNumber { + // If the span batch is not fully processed, the safe head must not advance. + require.Equal(t, verifier.L2Safe().Number, uint64(0)) + } else { ++ // Make sure we do the post-processing of what safety updates might happen ++ // after the pending-safe event, before the next pending-safe event. ++ verifier.ActL2EventsUntil(t, event.Is[engine2.PendingSafeUpdateEvent], 100, true) + // Once the span batch is fully processed, the safe head must advance to the end of span batch. + require.Equal(t, verifier.L2Safe().Number, targetHeadNumber) + require.Equal(t, verifier.L2Safe(), verifier.L2PendingSafe())
@@ -16265,13 +67301,13 @@
- OP + (new)
@@ -16281,35 +67317,262 @@
-
+1
-
-1
+
+45
+
-44
-
diff --git OP/op-e2e/actions/l2_batcher_test.go CELO/op-e2e/actions/l2_batcher_test.go -index 6235c7482326b022d7d2328bafe6996957f19a52..a4a61b78473d22c09c2600e9bff119b2c7993507 100644 ---- OP/op-e2e/actions/l2_batcher_test.go -+++ CELO/op-e2e/actions/l2_batcher_test.go -@@ -486,7 +486,7 @@ signer := types.LatestSigner(sd.L2Cfg.Config) - data := make([]byte, 120_000) // very large L2 txs, as large as the tx-pool will accept - _, err := rng.Read(data[:]) // fill with random bytes, to make compression ineffective - require.NoError(t, err) -- gas, err := core.IntrinsicGas(data, nil, false, true, true, false) -+ gas, err := core.IntrinsicGas(data, nil, false, true, true, false, nil, nil) - require.NoError(t, err) - if gas > engine.engineApi.RemainingBlockGas() { - break
+
diff --git OP/op-e2e/actions/dencun_fork_test.go CELO/op-e2e/actions/upgrades/dencun_fork_test.go +rename from op-e2e/actions/dencun_fork_test.go +rename to op-e2e/actions/upgrades/dencun_fork_test.go +index 9b411e28f1e712740cca4fd6cb996077946cd105..a9e3eb2cc25624aa03a8f4309b548923151e38b1 100644 +--- OP/op-e2e/actions/dencun_fork_test.go ++++ CELO/op-e2e/actions/upgrades/dencun_fork_test.go +@@ -1,9 +1,10 @@ +-package actions ++package upgrades +  + import ( + "context" + "testing" +  ++ "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" + "github.com/stretchr/testify/require" +  + "github.com/ethereum/go-ethereum/common" +@@ -17,15 +18,15 @@ "github.com/ethereum-optimism/optimism/op-service/testlog" + ) +  + func TestDencunL1ForkAfterGenesis(gt *testing.T) { +- t := NewDefaultTesting(gt) +- dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) ++ t := helpers.NewDefaultTesting(gt) ++ dp := e2eutils.MakeDeployParams(t, helpers.DefaultRollupTestParams) + offset := hexutil.Uint64(24) + dp.DeployConfig.L1CancunTimeOffset = &offset +- sd := e2eutils.Setup(t, dp, defaultAlloc) ++ sd := e2eutils.Setup(t, dp, helpers.DefaultAlloc) + log := testlog.Logger(t, log.LevelDebug) +- _, _, miner, sequencer, _, verifier, _, batcher := setupReorgTestActors(t, dp, sd, log) ++ _, _, miner, sequencer, _, verifier, _, batcher := helpers.SetupReorgTestActors(t, dp, sd, log) +  +- l1Head := miner.l1Chain.CurrentBlock() ++ l1Head := miner.L1Chain().CurrentBlock() + require.False(t, sd.L1Cfg.Config.IsCancun(l1Head.Number, l1Head.Time), "Cancun not active yet") + require.Nil(t, l1Head.ExcessBlobGas, "Cancun blob gas not in header") +  +@@ -39,7 +40,7 @@ miner.ActEmptyBlock(t) + miner.ActEmptyBlock(t) // Cancun activates here + miner.ActEmptyBlock(t) + // verify Cancun is active +- l1Head = miner.l1Chain.CurrentBlock() ++ l1Head = miner.L1Chain().CurrentBlock() + require.True(t, sd.L1Cfg.Config.IsCancun(l1Head.Number, l1Head.Time), "Cancun active") + require.NotNil(t, l1Head.ExcessBlobGas, "Cancun blob gas in header") +  +@@ -48,7 +49,7 @@ sequencer.ActL1HeadSignal(t) + sequencer.ActBuildToL1Head(t) + miner.ActL1StartBlock(12)(t) + batcher.ActSubmitAll(t) +- miner.ActL1IncludeTx(batcher.batcherAddr)(t) ++ miner.ActL1IncludeTx(batcher.BatcherAddr)(t) + miner.ActL1EndBlock(t) +  + // sync verifier +@@ -60,14 +61,14 @@ require.Equal(t, sequencer.SyncStatus().UnsafeL2, verifier.SyncStatus().UnsafeL2, "verifier and sequencer agree") + } +  + func TestDencunL1ForkAtGenesis(gt *testing.T) { +- t := NewDefaultTesting(gt) +- dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) ++ t := helpers.NewDefaultTesting(gt) ++ dp := e2eutils.MakeDeployParams(t, helpers.DefaultRollupTestParams) + require.Zero(t, *dp.DeployConfig.L1CancunTimeOffset) +- sd := e2eutils.Setup(t, dp, defaultAlloc) ++ sd := e2eutils.Setup(t, dp, helpers.DefaultAlloc) + log := testlog.Logger(t, log.LevelDebug) +- _, _, miner, sequencer, _, verifier, _, batcher := setupReorgTestActors(t, dp, sd, log) ++ _, _, miner, sequencer, _, verifier, _, batcher := helpers.SetupReorgTestActors(t, dp, sd, log) +  +- l1Head := miner.l1Chain.CurrentBlock() ++ l1Head := miner.L1Chain().CurrentBlock() + require.True(t, sd.L1Cfg.Config.IsCancun(l1Head.Number, l1Head.Time), "Cancun active at genesis") + require.NotNil(t, l1Head.ExcessBlobGas, "Cancun blob gas in header") +  +@@ -81,7 +82,7 @@ miner.ActEmptyBlock(t) + miner.ActEmptyBlock(t) +  + // verify Cancun is still active +- l1Head = miner.l1Chain.CurrentBlock() ++ l1Head = miner.L1Chain().CurrentBlock() + require.True(t, sd.L1Cfg.Config.IsCancun(l1Head.Number, l1Head.Time), "Cancun active") + require.NotNil(t, l1Head.ExcessBlobGas, "Cancun blob gas in header") +  +@@ -90,7 +91,7 @@ sequencer.ActL1HeadSignal(t) + sequencer.ActBuildToL1Head(t) + miner.ActL1StartBlock(12)(t) + batcher.ActSubmitAll(t) +- miner.ActL1IncludeTx(batcher.batcherAddr)(t) ++ miner.ActL1IncludeTx(batcher.BatcherAddr)(t) + miner.ActL1EndBlock(t) +  + // sync verifier +@@ -117,8 +118,8 @@ require.Equal(gt, *header.BlobGasUsed, uint64(0)) + } +  + func TestDencunL2ForkAfterGenesis(gt *testing.T) { +- t := NewDefaultTesting(gt) +- dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) ++ t := helpers.NewDefaultTesting(gt) ++ dp := e2eutils.MakeDeployParams(t, helpers.DefaultRollupTestParams) + require.Zero(t, *dp.DeployConfig.L1CancunTimeOffset) + // This test wil fork on the second block + offset := hexutil.Uint64(dp.DeployConfig.L2BlockTime * 2) +@@ -127,56 +128,56 @@ dp.DeployConfig.L2GenesisFjordTimeOffset = nil + dp.DeployConfig.L2GenesisGraniteTimeOffset = nil + // New forks have to be added here, after changing the default deploy config! +  +- sd := e2eutils.Setup(t, dp, defaultAlloc) ++ sd := e2eutils.Setup(t, dp, helpers.DefaultAlloc) + log := testlog.Logger(t, log.LevelDebug) +- _, _, _, sequencer, engine, verifier, _, _ := setupReorgTestActors(t, dp, sd, log) ++ _, _, _, sequencer, engine, verifier, _, _ := helpers.SetupReorgTestActors(t, dp, sd, log) +  + // start op-nodes + sequencer.ActL2PipelineFull(t) + verifier.ActL2PipelineFull(t) +  + // Genesis block is pre-ecotone +- verifyPreEcotoneBlock(gt, engine.l2Chain.CurrentBlock()) ++ verifyPreEcotoneBlock(gt, engine.L2Chain().CurrentBlock()) +  + // Block before fork block + sequencer.ActL2StartBlock(t) + sequencer.ActL2EndBlock(t) +- verifyPreEcotoneBlock(gt, engine.l2Chain.CurrentBlock()) ++ verifyPreEcotoneBlock(gt, engine.L2Chain().CurrentBlock()) +  + // Fork block is ecotone + sequencer.ActL2StartBlock(t) + sequencer.ActL2EndBlock(t) +- verifyEcotoneBlock(gt, engine.l2Chain.CurrentBlock()) ++ verifyEcotoneBlock(gt, engine.L2Chain().CurrentBlock()) +  + // Blocks post fork have Ecotone properties + sequencer.ActL2StartBlock(t) + sequencer.ActL2EndBlock(t) +- verifyEcotoneBlock(gt, engine.l2Chain.CurrentBlock()) ++ verifyEcotoneBlock(gt, engine.L2Chain().CurrentBlock()) + } +  + func TestDencunL2ForkAtGenesis(gt *testing.T) { +- t := NewDefaultTesting(gt) +- dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) ++ t := helpers.NewDefaultTesting(gt) ++ dp := e2eutils.MakeDeployParams(t, helpers.DefaultRollupTestParams) + require.Zero(t, *dp.DeployConfig.L2GenesisEcotoneTimeOffset) +  +- sd := e2eutils.Setup(t, dp, defaultAlloc) ++ sd := e2eutils.Setup(t, dp, helpers.DefaultAlloc) + log := testlog.Logger(t, log.LevelDebug) +- _, _, _, sequencer, engine, verifier, _, _ := setupReorgTestActors(t, dp, sd, log) ++ _, _, _, sequencer, engine, verifier, _, _ := helpers.SetupReorgTestActors(t, dp, sd, log) +  + // start op-nodes + sequencer.ActL2PipelineFull(t) + verifier.ActL2PipelineFull(t) +  + // Genesis block has ecotone properties +- verifyEcotoneBlock(gt, engine.l2Chain.CurrentBlock()) ++ verifyEcotoneBlock(gt, engine.L2Chain().CurrentBlock()) +  + // Blocks post fork have Ecotone properties + sequencer.ActL2StartBlock(t) + sequencer.ActL2EndBlock(t) +- verifyEcotoneBlock(gt, engine.l2Chain.CurrentBlock()) ++ verifyEcotoneBlock(gt, engine.L2Chain().CurrentBlock()) + } +  +-func aliceSimpleBlobTx(t Testing, dp *e2eutils.DeployParams) *types.Transaction { ++func aliceSimpleBlobTx(t helpers.Testing, dp *e2eutils.DeployParams) *types.Transaction { + txData := transactions.CreateEmptyBlobTx(true, dp.DeployConfig.L2ChainID) + // Manual signer creation, so we can sign a blob tx on the chain, + // even though we have disabled cancun signer support in Ecotone. +@@ -186,17 +187,17 @@ require.NoError(t, err, "must sign tx") + return tx + } +  +-func newEngine(t Testing, sd *e2eutils.SetupData, log log.Logger) *L2Engine { ++func newEngine(t helpers.Testing, sd *e2eutils.SetupData, log log.Logger) *helpers.L2Engine { + jwtPath := e2eutils.WriteDefaultJWT(t) +- return NewL2Engine(t, log, sd.L2Cfg, sd.RollupCfg.Genesis.L1, jwtPath) ++ return helpers.NewL2Engine(t, log, sd.L2Cfg, sd.RollupCfg.Genesis.L1, jwtPath) + } +  + // TestDencunBlobTxRPC tries to send a Blob tx to the L2 engine via RPC, it should not be accepted. + func TestDencunBlobTxRPC(gt *testing.T) { +- t := NewDefaultTesting(gt) +- dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) ++ t := helpers.NewDefaultTesting(gt) ++ dp := e2eutils.MakeDeployParams(t, helpers.DefaultRollupTestParams) +  +- sd := e2eutils.Setup(t, dp, defaultAlloc) ++ sd := e2eutils.Setup(t, dp, helpers.DefaultAlloc) + log := testlog.Logger(t, log.LevelDebug) + engine := newEngine(t, sd, log) + cl := engine.EthClient() +@@ -207,31 +208,31 @@ } +  + // TestDencunBlobTxInTxPool tries to insert a blob tx directly into the tx pool, it should not be accepted. + func TestDencunBlobTxInTxPool(gt *testing.T) { +- t := NewDefaultTesting(gt) +- dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) ++ t := helpers.NewDefaultTesting(gt) ++ dp := e2eutils.MakeDeployParams(t, helpers.DefaultRollupTestParams) +  +- sd := e2eutils.Setup(t, dp, defaultAlloc) ++ sd := e2eutils.Setup(t, dp, helpers.DefaultAlloc) + log := testlog.Logger(t, log.LevelDebug) + engine := newEngine(t, sd, log) + tx := aliceSimpleBlobTx(t, dp) +- errs := engine.eth.TxPool().Add([]*types.Transaction{tx}, true, true) ++ errs := engine.Eth.TxPool().Add([]*types.Transaction{tx}, true, true) + require.ErrorContains(t, errs[0], "transaction type not supported") + } +  + // TestDencunBlobTxInclusion tries to send a Blob tx to the L2 engine, it should not be accepted. + func TestDencunBlobTxInclusion(gt *testing.T) { +- t := NewDefaultTesting(gt) +- dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) ++ t := helpers.NewDefaultTesting(gt) ++ dp := e2eutils.MakeDeployParams(t, helpers.DefaultRollupTestParams) +  +- sd := e2eutils.Setup(t, dp, defaultAlloc) ++ sd := e2eutils.Setup(t, dp, helpers.DefaultAlloc) + log := testlog.Logger(t, log.LevelDebug) +  +- _, engine, sequencer := setupSequencerTest(t, sd, log) ++ _, engine, sequencer := helpers.SetupSequencerTest(t, sd, log) + sequencer.ActL2PipelineFull(t) +  + tx := aliceSimpleBlobTx(t, dp) +  + sequencer.ActL2StartBlock(t) +- err := engine.engineApi.IncludeTx(tx, dp.Addresses.Alice) ++ err := engine.EngineApi.IncludeTx(tx, dp.Addresses.Alice) + require.ErrorContains(t, err, "invalid L2 block (tx 1): failed to apply transaction to L2 block (tx 1): transaction type not supported") + }
@@ -16318,13 +67581,13 @@
- OP + (new)
@@ -16334,44 +67597,107 @@
-
+2
-
-2
+
+13
+
-12
-
diff --git OP/op-e2e/actions/span_batch_test.go CELO/op-e2e/actions/span_batch_test.go -index 23f5963fa97aea45fedfb6a28cedb5e6fca45f14..27e91484f4b0acfa49bc8de742d9be1cbe5c0715 100644 ---- OP/op-e2e/actions/span_batch_test.go -+++ CELO/op-e2e/actions/span_batch_test.go -@@ -530,7 +530,7 @@ signer := types.LatestSigner(sd.L2Cfg.Config) - data := make([]byte, rand.Intn(100)) - _, err := crand.Read(data[:]) // fill with random bytes - require.NoError(t, err) -- gas, err := core.IntrinsicGas(data, nil, false, true, true, false) -+ gas, err := core.IntrinsicGas(data, nil, false, true, true, false, nil, nil) - require.NoError(t, err) - baseFee := seqEngine.l2Chain.CurrentBlock().BaseFee - nonce, err := cl.PendingNonceAt(t.Ctx(), addrs[userIdx]) -@@ -669,7 +669,7 @@ signer := types.LatestSigner(sdDeltaActivated.L2Cfg.Config) - data := make([]byte, rand.Intn(100)) - _, err := crand.Read(data[:]) // fill with random bytes - require.NoError(t, err) -- gas, err := core.IntrinsicGas(data, nil, false, true, true, false) -+ gas, err := core.IntrinsicGas(data, nil, false, true, true, false, nil, nil) - require.NoError(t, err) - baseFee := seqEngine.l2Chain.CurrentBlock().BaseFee - nonce, err := seqEngCl.PendingNonceAt(t.Ctx(), addrs[userIdx])
+
diff --git OP/op-e2e/actions/ecotone_fork_test.go CELO/op-e2e/actions/upgrades/ecotone_fork_test.go +rename from op-e2e/actions/ecotone_fork_test.go +rename to op-e2e/actions/upgrades/ecotone_fork_test.go +index 260a7960089adbbbac523c545844194e5344b964..c4135266e1625c26f2033e22d95b3750ba737945 100644 +--- OP/op-e2e/actions/ecotone_fork_test.go ++++ CELO/op-e2e/actions/upgrades/ecotone_fork_test.go +@@ -1,10 +1,11 @@ +-package actions ++package upgrades +  + import ( + "context" + "math/big" + "testing" +  ++ "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" + "github.com/stretchr/testify/require" +  + "github.com/ethereum/go-ethereum/common" +@@ -30,7 +31,7 @@ + // verifyCodeHashMatches checks that the has of the code at the given address matches the expected code-hash. + // It also sanity-checks that the code is not empty: we should never deploy empty contract codes. + // Returns the contract code +-func verifyCodeHashMatches(t Testing, client *ethclient.Client, address common.Address, expectedCodeHash common.Hash) []byte { ++func verifyCodeHashMatches(t helpers.Testing, client *ethclient.Client, address common.Address, expectedCodeHash common.Hash) []byte { + code, err := client.CodeAt(context.Background(), address, nil) + require.NoError(t, err) + require.NotEmpty(t, code) +@@ -40,8 +41,8 @@ return code + } +  + func TestEcotoneNetworkUpgradeTransactions(gt *testing.T) { +- t := NewDefaultTesting(gt) +- dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) ++ t := helpers.NewDefaultTesting(gt) ++ dp := e2eutils.MakeDeployParams(t, helpers.DefaultRollupTestParams) + ecotoneOffset := hexutil.Uint64(4) +  + log := testlog.Logger(t, log.LevelDebug) +@@ -54,8 +55,8 @@ dp.DeployConfig.L2GenesisGraniteTimeOffset = nil + // New forks have to be added here... + require.NoError(t, dp.DeployConfig.Check(log), "must have valid config") +  +- sd := e2eutils.Setup(t, dp, defaultAlloc) +- _, _, miner, sequencer, engine, verifier, _, _ := setupReorgTestActors(t, dp, sd, log) ++ sd := e2eutils.Setup(t, dp, helpers.DefaultAlloc) ++ _, _, miner, sequencer, engine, verifier, _, _ := helpers.SetupReorgTestActors(t, dp, sd, log) + ethCl := engine.EthClient() +  + // build a single block to move away from the genesis with 0-values in L1Block contract +@@ -238,8 +239,8 @@ } +  + // TestEcotoneBeforeL1 tests that the L2 Ecotone fork can activate before L1 Dencun does + func TestEcotoneBeforeL1(gt *testing.T) { +- t := NewDefaultTesting(gt) +- dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) ++ t := helpers.NewDefaultTesting(gt) ++ dp := e2eutils.MakeDeployParams(t, helpers.DefaultRollupTestParams) + offset := hexutil.Uint64(0) + farOffset := hexutil.Uint64(10000) + dp.DeployConfig.L2GenesisRegolithTimeOffset = &offset +@@ -248,19 +249,19 @@ dp.DeployConfig.L2GenesisCanyonTimeOffset = &offset + dp.DeployConfig.L2GenesisDeltaTimeOffset = &offset + dp.DeployConfig.L2GenesisEcotoneTimeOffset = &offset +  +- sd := e2eutils.Setup(t, dp, defaultAlloc) ++ sd := e2eutils.Setup(t, dp, helpers.DefaultAlloc) + log := testlog.Logger(t, log.LevelDebug) +- _, _, _, sequencer, engine, verifier, _, _ := setupReorgTestActors(t, dp, sd, log) ++ _, _, _, sequencer, engine, verifier, _, _ := helpers.SetupReorgTestActors(t, dp, sd, log) +  + // start op-nodes + sequencer.ActL2PipelineFull(t) + verifier.ActL2PipelineFull(t) +  + // Genesis block has ecotone properties +- verifyEcotoneBlock(gt, engine.l2Chain.CurrentBlock()) ++ verifyEcotoneBlock(gt, engine.L2Chain().CurrentBlock()) +  + // Blocks post fork have Ecotone properties + sequencer.ActL2StartBlock(t) + sequencer.ActL2EndBlock(t) +- verifyEcotoneBlock(gt, engine.l2Chain.CurrentBlock()) ++ verifyEcotoneBlock(gt, engine.L2Chain().CurrentBlock()) + }
@@ -16380,13 +67706,13 @@
- OP + (new)
@@ -16396,35 +67722,64 @@
-
+1
-
-1
+
+6
+
-5
-
diff --git OP/op-e2e/actions/sync_test.go CELO/op-e2e/actions/sync_test.go -index 78297a5a8135950f16de599fa7eaa949871cde19..4ce4b0ef2243ce3a1d6a475372f983478046684a 100644 ---- OP/op-e2e/actions/sync_test.go -+++ CELO/op-e2e/actions/sync_test.go -@@ -954,7 +954,7 @@ // Create valid TX - aliceNonce, err := seqEng.EthClient().PendingNonceAt(t.Ctx(), dp.Addresses.Alice) - require.NoError(t, err) - data := make([]byte, rand.Intn(100)) -- gas, err := core.IntrinsicGas(data, nil, false, true, true, false) -+ gas, err := core.IntrinsicGas(data, nil, false, true, true, false, nil, nil) - require.NoError(t, err) - baseFee := seqEng.l2Chain.CurrentBlock().BaseFee - tx := types.MustSignNewTx(dp.Secrets.Alice, signer, &types.DynamicFeeTx{
+
diff --git OP/op-e2e/actions/fjord_fork_test.go CELO/op-e2e/actions/upgrades/fjord_fork_test.go +rename from op-e2e/actions/fjord_fork_test.go +rename to op-e2e/actions/upgrades/fjord_fork_test.go +index 517ec5cd2618a0d780e89debc894bf43c07e29fa..9444fcfcb7ae6e39609855c4a88f4f9515e76661 100644 +--- OP/op-e2e/actions/fjord_fork_test.go ++++ CELO/op-e2e/actions/upgrades/fjord_fork_test.go +@@ -1,4 +1,4 @@ +-package actions ++package upgrades +  + import ( + "context" +@@ -6,6 +6,7 @@ "encoding/hex" + "math/big" + "testing" +  ++ "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" + "github.com/ethereum-optimism/optimism/op-service/predeploys" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" +@@ -29,8 +30,8 @@ txHex = "02f875822105819b8405709fb884057d460082e97f94273ca93a52b817294830ed7572aa591ccfa647fd80881249c58b0021fb3fc080a05bb08ccfd68f83392e446dac64d88a2d28e7072c06502dfabc4a77e77b5c7913a05878d53dd4ebba4f6367e572d524dffcabeec3abb1d8725ee3ac5dc32e1852e3" + ) +  + func TestFjordNetworkUpgradeTransactions(gt *testing.T) { +- t := NewDefaultTesting(gt) +- dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) ++ t := helpers.NewDefaultTesting(gt) ++ dp := e2eutils.MakeDeployParams(t, helpers.DefaultRollupTestParams) + genesisBlock := hexutil.Uint64(0) + fjordOffset := hexutil.Uint64(2) +  +@@ -46,8 +47,8 @@ dp.DeployConfig.L2GenesisEcotoneTimeOffset = &genesisBlock + dp.DeployConfig.L2GenesisFjordTimeOffset = &fjordOffset + require.NoError(t, dp.DeployConfig.Check(log), "must have valid config") +  +- sd := e2eutils.Setup(t, dp, defaultAlloc) +- _, _, _, sequencer, engine, verifier, _, _ := setupReorgTestActors(t, dp, sd, log) ++ sd := e2eutils.Setup(t, dp, helpers.DefaultAlloc) ++ _, _, _, sequencer, engine, verifier, _, _ := helpers.SetupReorgTestActors(t, dp, sd, log) + ethCl := engine.EthClient() +  + // start op-nodes
@@ -16433,13 +67788,13 @@
- OP + (new)
@@ -16449,35 +67804,55 @@
-
+1
-
-1
+
+27
+
-0
-
diff --git OP/op-e2e/brotli_batcher_test.go CELO/op-e2e/brotli_batcher_test.go -index ee4a223bf3ea53fe8e16b61192060c5b0a7e3e6c..f8e9728b03ca0167537f19471831932f876e680c 100644 ---- OP/op-e2e/brotli_batcher_test.go -+++ CELO/op-e2e/brotli_batcher_test.go -@@ -80,7 +80,7 @@ receipt := SendL2Tx(t, cfg, l2Seq, ethPrivKey, func(opts *TxOpts) { - opts.Value = big.NewInt(1_000_000_000) - opts.Nonce = 1 // Already have deposit - opts.ToAddr = &common.Address{0xff, 0xff} -- opts.Gas, err = core.IntrinsicGas(opts.Data, nil, false, true, true, false) -+ opts.Gas, err = core.IntrinsicGas(opts.Data, nil, false, true, true, false, nil, nil) - require.NoError(t, err) - opts.VerifyOnClients(l2Verif) - })
+
diff --git OP/op-e2e/actions/upgrades/helpers/config.go CELO/op-e2e/actions/upgrades/helpers/config.go +new file mode 100644 +index 0000000000000000000000000000000000000000..a936d86250a0505015060da9bc1f017fef941edc +--- /dev/null ++++ CELO/op-e2e/actions/upgrades/helpers/config.go +@@ -0,0 +1,27 @@ ++package helpers ++ ++import ( ++ "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" ++ "github.com/ethereum/go-ethereum/common/hexutil" ++) ++ ++// ApplyDeltaTimeOffset adjusts fork configuration to not conflict with the delta overrides ++func ApplyDeltaTimeOffset(dp *e2eutils.DeployParams, deltaTimeOffset *hexutil.Uint64) { ++ dp.DeployConfig.L2GenesisDeltaTimeOffset = deltaTimeOffset ++ // configure Ecotone to not be before Delta accidentally ++ if dp.DeployConfig.L2GenesisEcotoneTimeOffset != nil { ++ if deltaTimeOffset == nil { ++ dp.DeployConfig.L2GenesisEcotoneTimeOffset = nil ++ } else if *dp.DeployConfig.L2GenesisEcotoneTimeOffset < *deltaTimeOffset { ++ dp.DeployConfig.L2GenesisEcotoneTimeOffset = deltaTimeOffset ++ } ++ } ++ // configure Fjord to not be before Delta accidentally ++ if dp.DeployConfig.L2GenesisFjordTimeOffset != nil { ++ if deltaTimeOffset == nil { ++ dp.DeployConfig.L2GenesisFjordTimeOffset = nil ++ } else if *dp.DeployConfig.L2GenesisFjordTimeOffset < *deltaTimeOffset { ++ dp.DeployConfig.L2GenesisFjordTimeOffset = deltaTimeOffset ++ } ++ } ++}
@@ -16492,7 +67867,7 @@
@@ -16502,31 +67877,402 @@
-
+4
-
-0
+
+64
+
-62
-
diff --git OP/op-e2e/celo/.prettierrc.toml CELO/op-e2e/celo/.prettierrc.toml -new file mode 100644 -index 0000000000000000000000000000000000000000..d5b43d58c0b8c7eba8fa0cb9e8d2673652e309e6 ---- /dev/null -+++ CELO/op-e2e/celo/.prettierrc.toml -@@ -0,0 +1,4 @@ -+trailingComma = "es5" -+tabWidth = 2 -+semi = false -+singleQuote = true
+
diff --git OP/op-e2e/actions/span_batch_test.go CELO/op-e2e/actions/upgrades/span_batch_test.go +rename from op-e2e/actions/span_batch_test.go +rename to op-e2e/actions/upgrades/span_batch_test.go +index 23f5963fa97aea45fedfb6a28cedb5e6fca45f14..3713f2fb62ce0ca72b4018cc55de5926a378c19b 100644 +--- OP/op-e2e/actions/span_batch_test.go ++++ CELO/op-e2e/actions/upgrades/span_batch_test.go +@@ -1,4 +1,4 @@ +-package actions ++package upgrades +  + import ( + "context" +@@ -10,6 +10,8 @@ "math/big" + "math/rand" + "testing" +  ++ actionsHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" ++ upgradesHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/upgrades/helpers" + "github.com/stretchr/testify/require" +  + "github.com/ethereum/go-ethereum" +@@ -31,7 +33,7 @@ + // TestDropSpanBatchBeforeHardfork tests behavior of op-node before Delta hardfork. + // op-node must drop SpanBatch before Delta hardfork. + func TestDropSpanBatchBeforeHardfork(gt *testing.T) { +- t := NewDefaultTesting(gt) ++ t := actionsHelpers.NewDefaultTesting(gt) + p := &e2eutils.TestParams{ + MaxSequencerDrift: 20, // larger than L1 block time we simulate in this test (12) + SequencerWindowSize: 24, +@@ -40,15 +42,15 @@ L1BlockTime: 12, + } + dp := e2eutils.MakeDeployParams(t, p) + // do not activate Delta hardfork for verifier +- applyDeltaTimeOffset(dp, nil) +- sd := e2eutils.Setup(t, dp, defaultAlloc) ++ upgradesHelpers.ApplyDeltaTimeOffset(dp, nil) ++ sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) + log := testlog.Logger(t, log.LevelError) +- miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) +- verifEngine, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) ++ miner, seqEngine, sequencer := actionsHelpers.SetupSequencerTest(t, sd, log) ++ verifEngine, verifier := actionsHelpers.SetupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) + rollupSeqCl := sequencer.RollupClient() +  + // Force batcher to submit SpanBatches to L1. +- batcher := NewL2Batcher(log, sd.RollupCfg, &BatcherCfg{ ++ batcher := actionsHelpers.NewL2Batcher(log, sd.RollupCfg, &actionsHelpers.BatcherCfg{ + MinL1TxSize: 0, + MaxL1TxSize: 128_000, + BatcherKey: dp.Secrets.Batcher, +@@ -65,7 +67,7 @@ tx := types.MustSignNewTx(dp.Secrets.Alice, signer, &types.DynamicFeeTx{ + ChainID: sd.L2Cfg.Config.ChainID, + Nonce: n, + GasTipCap: big.NewInt(2 * params.GWei), +- GasFeeCap: new(big.Int).Add(miner.l1Chain.CurrentBlock().BaseFee, big.NewInt(2*params.GWei)), ++ GasFeeCap: new(big.Int).Add(miner.L1Chain().CurrentBlock().BaseFee, big.NewInt(2*params.GWei)), + Gas: params.TxGas, + To: &dp.Addresses.Bob, + Value: e2eutils.Ether(2), +@@ -89,8 +91,8 @@ // confirm batch on L1 + miner.ActL1StartBlock(12)(t) + miner.ActL1IncludeTx(dp.Addresses.Batcher)(t) + miner.ActL1EndBlock(t) +- bl := miner.l1Chain.CurrentBlock() +- log.Info("bl", "txs", len(miner.l1Chain.GetBlockByHash(bl.Hash()).Transactions())) ++ bl := miner.L1Chain().CurrentBlock() ++ log.Info("bl", "txs", len(miner.L1Chain().GetBlockByHash(bl.Hash()).Transactions())) +  + // Now make enough L1 blocks that the verifier will have to derive a L2 block + // It will also eagerly derive the block from the batcher +@@ -120,7 +122,7 @@ + // TestHardforkMiddleOfSpanBatch tests behavior of op-node Delta hardfork. + // If Delta activation time is in the middle of time range of a SpanBatch, op-node must drop the batch. + func TestHardforkMiddleOfSpanBatch(gt *testing.T) { +- t := NewDefaultTesting(gt) ++ t := actionsHelpers.NewDefaultTesting(gt) + p := &e2eutils.TestParams{ + MaxSequencerDrift: 20, // larger than L1 block time we simulate in this test (12) + SequencerWindowSize: 24, +@@ -131,21 +133,21 @@ dp := e2eutils.MakeDeployParams(t, p) +  + // Activate HF in the middle of the first epoch + deltaOffset := hexutil.Uint64(6) +- applyDeltaTimeOffset(dp, &deltaOffset) ++ upgradesHelpers.ApplyDeltaTimeOffset(dp, &deltaOffset) + // Applies to HF that goes into Delta. Otherwise we end up with more upgrade txs and things during this case. + dp.DeployConfig.L2GenesisEcotoneTimeOffset = nil + dp.DeployConfig.L2GenesisFjordTimeOffset = nil + dp.DeployConfig.L2GenesisGraniteTimeOffset = nil +  +- sd := e2eutils.Setup(t, dp, defaultAlloc) ++ sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) + log := testlog.Logger(t, log.LevelError) +- miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) +- verifEngine, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) ++ miner, seqEngine, sequencer := actionsHelpers.SetupSequencerTest(t, sd, log) ++ verifEngine, verifier := actionsHelpers.SetupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) + minerCl := miner.EthClient() + rollupSeqCl := sequencer.RollupClient() +  + // Force batcher to submit SpanBatches to L1. +- batcher := NewL2Batcher(log, sd.RollupCfg, &BatcherCfg{ ++ batcher := actionsHelpers.NewL2Batcher(log, sd.RollupCfg, &actionsHelpers.BatcherCfg{ + MinL1TxSize: 0, + MaxL1TxSize: 128_000, + BatcherKey: dp.Secrets.Batcher, +@@ -162,7 +164,7 @@ tx := types.MustSignNewTx(dp.Secrets.Alice, signer, &types.DynamicFeeTx{ + ChainID: sd.L2Cfg.Config.ChainID, + Nonce: n, + GasTipCap: big.NewInt(2 * params.GWei), +- GasFeeCap: new(big.Int).Add(miner.l1Chain.CurrentBlock().BaseFee, big.NewInt(2*params.GWei)), ++ GasFeeCap: new(big.Int).Add(miner.L1Chain().CurrentBlock().BaseFee, big.NewInt(2*params.GWei)), + Gas: params.TxGas, + To: &dp.Addresses.Bob, + Value: e2eutils.Ether(2), +@@ -202,8 +204,8 @@ // Confirm batch on L1 + miner.ActL1StartBlock(12)(t) + miner.ActL1IncludeTx(dp.Addresses.Batcher)(t) + miner.ActL1EndBlock(t) +- bl := miner.l1Chain.CurrentBlock() +- log.Info("bl", "txs", len(miner.l1Chain.GetBlockByHash(bl.Hash()).Transactions())) ++ bl := miner.L1Chain().CurrentBlock() ++ log.Info("bl", "txs", len(miner.L1Chain().GetBlockByHash(bl.Hash()).Transactions())) +  + // Now make enough L1 blocks that the verifier will have to derive a L2 block + // It will also eagerly derive the block from the batcher +@@ -233,7 +235,7 @@ + // TestAcceptSingularBatchAfterHardfork tests behavior of op-node after Delta hardfork. + // op-node must accept SingularBatch after Delta hardfork. + func TestAcceptSingularBatchAfterHardfork(gt *testing.T) { +- t := NewDefaultTesting(gt) ++ t := actionsHelpers.NewDefaultTesting(gt) + p := &e2eutils.TestParams{ + MaxSequencerDrift: 20, // larger than L1 block time we simulate in this test (12) + SequencerWindowSize: 24, +@@ -244,15 +246,15 @@ minTs := hexutil.Uint64(0) + dp := e2eutils.MakeDeployParams(t, p) +  + // activate Delta hardfork for verifier. +- applyDeltaTimeOffset(dp, &minTs) +- sd := e2eutils.Setup(t, dp, defaultAlloc) ++ upgradesHelpers.ApplyDeltaTimeOffset(dp, &minTs) ++ sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) + log := testlog.Logger(t, log.LevelError) +- miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) +- verifEngine, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) ++ miner, seqEngine, sequencer := actionsHelpers.SetupSequencerTest(t, sd, log) ++ verifEngine, verifier := actionsHelpers.SetupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) + rollupSeqCl := sequencer.RollupClient() +  + // Force batcher to submit SingularBatches to L1. +- batcher := NewL2Batcher(log, sd.RollupCfg, &BatcherCfg{ ++ batcher := actionsHelpers.NewL2Batcher(log, sd.RollupCfg, &actionsHelpers.BatcherCfg{ + MinL1TxSize: 0, + MaxL1TxSize: 128_000, + BatcherKey: dp.Secrets.Batcher, +@@ -269,7 +271,7 @@ tx := types.MustSignNewTx(dp.Secrets.Alice, signer, &types.DynamicFeeTx{ + ChainID: sd.L2Cfg.Config.ChainID, + Nonce: n, + GasTipCap: big.NewInt(2 * params.GWei), +- GasFeeCap: new(big.Int).Add(miner.l1Chain.CurrentBlock().BaseFee, big.NewInt(2*params.GWei)), ++ GasFeeCap: new(big.Int).Add(miner.L1Chain().CurrentBlock().BaseFee, big.NewInt(2*params.GWei)), + Gas: params.TxGas, + To: &dp.Addresses.Bob, + Value: e2eutils.Ether(2), +@@ -293,8 +295,8 @@ // confirm batch on L1 + miner.ActL1StartBlock(12)(t) + miner.ActL1IncludeTx(dp.Addresses.Batcher)(t) + miner.ActL1EndBlock(t) +- bl := miner.l1Chain.CurrentBlock() +- log.Info("bl", "txs", len(miner.l1Chain.GetBlockByHash(bl.Hash()).Transactions())) ++ bl := miner.L1Chain().CurrentBlock() ++ log.Info("bl", "txs", len(miner.L1Chain().GetBlockByHash(bl.Hash()).Transactions())) +  + // Now make enough L1 blocks that the verifier will have to derive a L2 block + // It will also eagerly derive the block from the batcher +@@ -319,7 +321,7 @@ + // TestMixOfBatchesAfterHardfork tests behavior of op-node after Delta hardfork. + // op-node must accept SingularBatch and SpanBatch in sequence. + func TestMixOfBatchesAfterHardfork(gt *testing.T) { +- t := NewDefaultTesting(gt) ++ t := actionsHelpers.NewDefaultTesting(gt) + p := &e2eutils.TestParams{ + MaxSequencerDrift: 20, // larger than L1 block time we simulate in this test (12) + SequencerWindowSize: 24, +@@ -330,11 +332,11 @@ minTs := hexutil.Uint64(0) + dp := e2eutils.MakeDeployParams(t, p) +  + // Activate Delta hardfork for verifier. +- applyDeltaTimeOffset(dp, &minTs) +- sd := e2eutils.Setup(t, dp, defaultAlloc) ++ upgradesHelpers.ApplyDeltaTimeOffset(dp, &minTs) ++ sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) + log := testlog.Logger(t, log.LevelError) +- miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) +- verifEngine, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) ++ miner, seqEngine, sequencer := actionsHelpers.SetupSequencerTest(t, sd, log) ++ verifEngine, verifier := actionsHelpers.SetupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) + rollupSeqCl := sequencer.RollupClient() + seqEngCl := seqEngine.EthClient() +  +@@ -352,7 +354,7 @@ tx := types.MustSignNewTx(dp.Secrets.Alice, signer, &types.DynamicFeeTx{ + ChainID: sd.L2Cfg.Config.ChainID, + Nonce: n, + GasTipCap: big.NewInt(2 * params.GWei), +- GasFeeCap: new(big.Int).Add(miner.l1Chain.CurrentBlock().BaseFee, big.NewInt(2*params.GWei)), ++ GasFeeCap: new(big.Int).Add(miner.L1Chain().CurrentBlock().BaseFee, big.NewInt(2*params.GWei)), + Gas: params.TxGas, + To: &dp.Addresses.Bob, + Value: e2eutils.Ether(2), +@@ -368,7 +370,7 @@ sequencer.ActL2EndBlock(t) + sequencer.ActBuildToL1Head(t) +  + // Select batcher mode +- batcherCfg := BatcherCfg{ ++ batcherCfg := actionsHelpers.BatcherCfg{ + MinL1TxSize: 0, + MaxL1TxSize: 128_000, + BatcherKey: dp.Secrets.Batcher, +@@ -376,7 +378,7 @@ ForceSubmitSpanBatch: i%2 == 0, // Submit SpanBatch for odd numbered batches + ForceSubmitSingularBatch: i%2 == 1, // Submit SingularBatch for even numbered batches + DataAvailabilityType: batcherFlags.CalldataType, + } +- batcher := NewL2Batcher(log, sd.RollupCfg, &batcherCfg, rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) ++ batcher := actionsHelpers.NewL2Batcher(log, sd.RollupCfg, &batcherCfg, rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) + // Submit all new blocks + batcher.ActSubmitAll(t) +  +@@ -410,7 +412,7 @@ } +  + // TestSpanBatchEmptyChain tests derivation of empty chain using SpanBatch. + func TestSpanBatchEmptyChain(gt *testing.T) { +- t := NewDefaultTesting(gt) ++ t := actionsHelpers.NewDefaultTesting(gt) + p := &e2eutils.TestParams{ + MaxSequencerDrift: 20, + SequencerWindowSize: 24, +@@ -420,14 +422,14 @@ } + dp := e2eutils.MakeDeployParams(t, p) + minTs := hexutil.Uint64(0) + // Activate Delta hardfork +- applyDeltaTimeOffset(dp, &minTs) +- sd := e2eutils.Setup(t, dp, defaultAlloc) ++ upgradesHelpers.ApplyDeltaTimeOffset(dp, &minTs) ++ sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) + log := testlog.Logger(t, log.LevelError) +- miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) +- _, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) ++ miner, seqEngine, sequencer := actionsHelpers.SetupSequencerTest(t, sd, log) ++ _, verifier := actionsHelpers.SetupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) +  + rollupSeqCl := sequencer.RollupClient() +- batcher := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp), ++ batcher := actionsHelpers.NewL2Batcher(log, sd.RollupCfg, actionsHelpers.DefaultBatcherCfg(dp), + rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) +  + sequencer.ActL2PipelineFull(t) +@@ -473,7 +475,7 @@ } +  + // TestSpanBatchLowThroughputChain tests derivation of low-throughput chain using SpanBatch. + func TestSpanBatchLowThroughputChain(gt *testing.T) { +- t := NewDefaultTesting(gt) ++ t := actionsHelpers.NewDefaultTesting(gt) + p := &e2eutils.TestParams{ + MaxSequencerDrift: 20, + SequencerWindowSize: 24, +@@ -483,14 +485,14 @@ } + dp := e2eutils.MakeDeployParams(t, p) + minTs := hexutil.Uint64(0) + // Activate Delta hardfork +- applyDeltaTimeOffset(dp, &minTs) +- sd := e2eutils.Setup(t, dp, defaultAlloc) ++ upgradesHelpers.ApplyDeltaTimeOffset(dp, &minTs) ++ sd := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) + log := testlog.Logger(t, log.LevelError) +- miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) +- _, verifier := setupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) ++ miner, seqEngine, sequencer := actionsHelpers.SetupSequencerTest(t, sd, log) ++ _, verifier := actionsHelpers.SetupVerifier(t, sd, log, miner.L1Client(t, sd.RollupCfg), miner.BlobStore(), &sync.Config{}) +  + rollupSeqCl := sequencer.RollupClient() +- batcher := NewL2Batcher(log, sd.RollupCfg, DefaultBatcherCfg(dp), ++ batcher := actionsHelpers.NewL2Batcher(log, sd.RollupCfg, actionsHelpers.DefaultBatcherCfg(dp), + rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sd.RollupCfg)) + cl := seqEngine.EthClient() +  +@@ -521,7 +523,7 @@ miner.ActEmptyBlock(t) + totalTxCount := 0 + // Make 600 L2 blocks (L1BlockTime / L2BlockTime * 50) including 1~3 txs + for i := 0; i < 50; i++ { +- for sequencer.engine.UnsafeL2Head().L1Origin.Number < sequencer.syncStatus.L1Head().Number { ++ for sequencer.L2Unsafe().L1Origin.Number < sequencer.SyncStatus().HeadL1.Number { + sequencer.ActL2StartBlock(t) + // fill the block with random number of L2 txs + for j := 0; j < rand.Intn(3); j++ { +@@ -530,9 +532,9 @@ signer := types.LatestSigner(sd.L2Cfg.Config) + data := make([]byte, rand.Intn(100)) + _, err := crand.Read(data[:]) // fill with random bytes + require.NoError(t, err) +- gas, err := core.IntrinsicGas(data, nil, false, true, true, false) ++ gas, err := core.IntrinsicGas(data, nil, false, true, true, false, nil, nil) + require.NoError(t, err) +- baseFee := seqEngine.l2Chain.CurrentBlock().BaseFee ++ baseFee := seqEngine.L2Chain().CurrentBlock().BaseFee + nonce, err := cl.PendingNonceAt(t.Ctx(), addrs[userIdx]) + require.NoError(t, err) + tx := types.MustSignNewTx(privKeys[userIdx], signer, &types.DynamicFeeTx{ +@@ -585,7 +587,7 @@ require.Equal(t, sequencer.L2Safe(), verifier.L2Safe()) + } +  + func TestBatchEquivalence(gt *testing.T) { +- t := NewDefaultTesting(gt) ++ t := actionsHelpers.NewDefaultTesting(gt) + log := testlog.Logger(t, log.LevelError) +  + p := &e2eutils.TestParams{ +@@ -597,8 +599,8 @@ } + // Delta activated deploy config + dp := e2eutils.MakeDeployParams(t, p) + minTs := hexutil.Uint64(0) +- applyDeltaTimeOffset(dp, &minTs) +- sdDeltaActivated := e2eutils.Setup(t, dp, defaultAlloc) ++ upgradesHelpers.ApplyDeltaTimeOffset(dp, &minTs) ++ sdDeltaActivated := e2eutils.Setup(t, dp, actionsHelpers.DefaultAlloc) +  + // Delta deactivated deploy config + rcfg := *sdDeltaActivated.RollupCfg +@@ -611,18 +613,18 @@ DeploymentsL1: sdDeltaActivated.DeploymentsL1, + } +  + // Setup sequencer +- miner, seqEngine, sequencer := setupSequencerTest(t, sdDeltaActivated, log) ++ miner, seqEngine, sequencer := actionsHelpers.SetupSequencerTest(t, sdDeltaActivated, log) + rollupSeqCl := sequencer.RollupClient() + seqEngCl := seqEngine.EthClient() +  + // Setup Delta activated spanVerifier +- _, spanVerifier := setupVerifier(t, sdDeltaActivated, log, miner.L1Client(t, sdDeltaActivated.RollupCfg), miner.BlobStore(), &sync.Config{}) ++ _, spanVerifier := actionsHelpers.SetupVerifier(t, sdDeltaActivated, log, miner.L1Client(t, sdDeltaActivated.RollupCfg), miner.BlobStore(), &sync.Config{}) +  + // Setup Delta deactivated spanVerifier +- _, singularVerifier := setupVerifier(t, sdDeltaDeactivated, log, miner.L1Client(t, sdDeltaDeactivated.RollupCfg), miner.BlobStore(), &sync.Config{}) ++ _, singularVerifier := actionsHelpers.SetupVerifier(t, sdDeltaDeactivated, log, miner.L1Client(t, sdDeltaDeactivated.RollupCfg), miner.BlobStore(), &sync.Config{}) +  + // Setup SpanBatcher +- spanBatcher := NewL2Batcher(log, sdDeltaActivated.RollupCfg, &BatcherCfg{ ++ spanBatcher := actionsHelpers.NewL2Batcher(log, sdDeltaActivated.RollupCfg, &actionsHelpers.BatcherCfg{ + MinL1TxSize: 0, + MaxL1TxSize: 128_000, + BatcherKey: dp.Secrets.Batcher, +@@ -631,7 +633,7 @@ DataAvailabilityType: batcherFlags.CalldataType, + }, rollupSeqCl, miner.EthClient(), seqEngine.EthClient(), seqEngine.EngineClient(t, sdDeltaActivated.RollupCfg)) +  + // Setup SingularBatcher +- singularBatcher := NewL2Batcher(log, sdDeltaDeactivated.RollupCfg, &BatcherCfg{ ++ singularBatcher := actionsHelpers.NewL2Batcher(log, sdDeltaDeactivated.RollupCfg, &actionsHelpers.BatcherCfg{ + MinL1TxSize: 0, + MaxL1TxSize: 128_000, + BatcherKey: dp.Secrets.Batcher, +@@ -660,7 +662,7 @@ sequencer.ActL1HeadSignal(t) + sequencer.ActL2PipelineFull(t) + totalTxCount := 0 + // Build random blocks +- for sequencer.engine.UnsafeL2Head().L1Origin.Number < sequencer.syncStatus.L1Head().Number { ++ for sequencer.L2Unsafe().L1Origin.Number < sequencer.SyncStatus().HeadL1.Number { + sequencer.ActL2StartBlock(t) + // fill the block with random number of L2 txs + for j := 0; j < rand.Intn(3); j++ { +@@ -669,9 +671,9 @@ signer := types.LatestSigner(sdDeltaActivated.L2Cfg.Config) + data := make([]byte, rand.Intn(100)) + _, err := crand.Read(data[:]) // fill with random bytes + require.NoError(t, err) +- gas, err := core.IntrinsicGas(data, nil, false, true, true, false) ++ gas, err := core.IntrinsicGas(data, nil, false, true, true, false, nil, nil) + require.NoError(t, err) +- baseFee := seqEngine.l2Chain.CurrentBlock().BaseFee ++ baseFee := seqEngine.L2Chain().CurrentBlock().BaseFee + nonce, err := seqEngCl.PendingNonceAt(t.Ctx(), addrs[userIdx]) + require.NoError(t, err) + tx := types.MustSignNewTx(privKeys[userIdx], signer, &types.DynamicFeeTx{
- @@ -16542,7 +68288,7 @@
@@ -16559,7 +68305,7 @@
-
diff --git OP/op-e2e/celo/babel.config.cjs CELO/op-e2e/celo/babel.config.cjs +
diff --git OP/op-e2e/celo/babel.config.cjs CELO/op-e2e/celo/babel.config.cjs new file mode 100644 index 0000000000000000000000000000000000000000..a76dfe63099c9948289ad9c3cad15a8e391e7e76 --- /dev/null @@ -16574,8 +68320,8 @@
- @@ -16591,7 +68337,7 @@
@@ -16608,7 +68354,7 @@
-
diff --git OP/op-e2e/celo/foundry.toml CELO/op-e2e/celo/foundry.toml +
diff --git OP/op-e2e/celo/foundry.toml CELO/op-e2e/celo/foundry.toml new file mode 100644 index 0000000000000000000000000000000000000000..8df5305625e49af8485993916160a3fe99512d1d --- /dev/null @@ -16639,8 +68385,8 @@
- @@ -16656,7 +68402,7 @@
@@ -16673,7 +68419,7 @@
-
diff --git OP/op-e2e/celo/jest.config.json CELO/op-e2e/celo/jest.config.json +
diff --git OP/op-e2e/celo/jest.config.json CELO/op-e2e/celo/jest.config.json new file mode 100644 index 0000000000000000000000000000000000000000..aea28c9f68597eeaca251715ad80f924c20670e3 --- /dev/null @@ -16690,8 +68436,8 @@
@@ -16717,19 +68463,19 @@
-
+6578
+
+6543
-0
-
diff --git OP/op-e2e/celo/package-lock.json CELO/op-e2e/celo/package-lock.json +
diff --git OP/op-e2e/celo/package-lock.json CELO/op-e2e/celo/package-lock.json new file mode 100644 -index 0000000000000000000000000000000000000000..fc39534dff450603e7d3df74d56844c733cbbf7d +index 0000000000000000000000000000000000000000..b4e15405b5ab96e1edd45a99581f95fb992d3be7 --- /dev/null +++ CELO/op-e2e/celo/package-lock.json -@@ -0,0 +1,6578 @@ +@@ -0,0 +1,6543 @@ +{ + "name": "testsuite", + "version": "1.0.0", @@ -16744,103 +68490,362 @@ + "reverse-mirage": "^1.1.0", + "viem": "^2.13.1" + }, -+ "devDependencies": { -+ "@babel/core": "^7.24.7", -+ "@babel/preset-env": "^7.24.7", -+ "babel-jest": "^29.7.0", -+ "jest": "^29.7.0", -+ "prettier": "3.3.3" ++ "devDependencies": { ++ "@babel/core": "^7.24.7", ++ "@babel/preset-env": "^7.24.7", ++ "babel-jest": "^29.7.0", ++ "jest": "^29.7.0" ++ } ++ }, ++ "node_modules/@adraffy/ens-normalize": { ++ "version": "1.10.0", ++ "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.0.tgz", ++ "integrity": "sha512-nA9XHtlAkYfJxY7bce8DcN7eKxWWCWkU+1GR9d+U6MbNpfwQp8TI7vqOsBsMcHoT4mBu2kypKoSKnghEzOOq5Q==" ++ }, ++ "node_modules/@ampproject/remapping": { ++ "version": "2.3.0", ++ "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", ++ "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", ++ "dev": true, ++ "dependencies": { ++ "@jridgewell/gen-mapping": "^0.3.5", ++ "@jridgewell/trace-mapping": "^0.3.24" ++ }, ++ "engines": { ++ "node": ">=6.0.0" ++ } ++ }, ++ "node_modules/@babel/code-frame": { ++ "version": "7.24.7", ++ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", ++ "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", ++ "dev": true, ++ "dependencies": { ++ "@babel/highlight": "^7.24.7", ++ "picocolors": "^1.0.0" ++ }, ++ "engines": { ++ "node": ">=6.9.0" ++ } ++ }, ++ "node_modules/@babel/compat-data": { ++ "version": "7.24.9", ++ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.9.tgz", ++ "integrity": "sha512-e701mcfApCJqMMueQI0Fb68Amflj83+dvAvHawoBpAz+GDjCIyGHzNwnefjsWJ3xiYAqqiQFoWbspGYBdb2/ng==", ++ "dev": true, ++ "engines": { ++ "node": ">=6.9.0" ++ } ++ }, ++ "node_modules/@babel/core": { ++ "version": "7.24.9", ++ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.9.tgz", ++ "integrity": "sha512-5e3FI4Q3M3Pbr21+5xJwCv6ZT6KmGkI0vw3Tozy5ODAQFTIWe37iT8Cr7Ice2Ntb+M3iSKCEWMB1MBgKrW3whg==", ++ "dev": true, ++ "dependencies": { ++ "@ampproject/remapping": "^2.2.0", ++ "@babel/code-frame": "^7.24.7", ++ "@babel/generator": "^7.24.9", ++ "@babel/helper-compilation-targets": "^7.24.8", ++ "@babel/helper-module-transforms": "^7.24.9", ++ "@babel/helpers": "^7.24.8", ++ "@babel/parser": "^7.24.8", ++ "@babel/template": "^7.24.7", ++ "@babel/traverse": "^7.24.8", ++ "@babel/types": "^7.24.9", ++ "convert-source-map": "^2.0.0", ++ "debug": "^4.1.0", ++ "gensync": "^1.0.0-beta.2", ++ "json5": "^2.2.3", ++ "semver": "^6.3.1" ++ }, ++ "engines": { ++ "node": ">=6.9.0" ++ }, ++ "funding": { ++ "type": "opencollective", ++ "url": "https://opencollective.com/babel" ++ } ++ }, ++ "node_modules/@babel/generator": { ++ "version": "7.24.10", ++ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.10.tgz", ++ "integrity": "sha512-o9HBZL1G2129luEUlG1hB4N/nlYNWHnpwlND9eOMclRqqu1YDy2sSYVCFUZwl8I1Gxh+QSRrP2vD7EpUmFVXxg==", ++ "dev": true, ++ "dependencies": { ++ "@babel/types": "^7.24.9", ++ "@jridgewell/gen-mapping": "^0.3.5", ++ "@jridgewell/trace-mapping": "^0.3.25", ++ "jsesc": "^2.5.1" ++ }, ++ "engines": { ++ "node": ">=6.9.0" ++ } ++ }, ++ "node_modules/@babel/helper-annotate-as-pure": { ++ "version": "7.24.7", ++ "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", ++ "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", ++ "dev": true, ++ "dependencies": { ++ "@babel/types": "^7.24.7" ++ }, ++ "engines": { ++ "node": ">=6.9.0" ++ } ++ }, ++ "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { ++ "version": "7.24.7", ++ "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.24.7.tgz", ++ "integrity": "sha512-xZeCVVdwb4MsDBkkyZ64tReWYrLRHlMN72vP7Bdm3OUOuyFZExhsHUUnuWnm2/XOlAJzR0LfPpB56WXZn0X/lA==", ++ "dev": true, ++ "dependencies": { ++ "@babel/traverse": "^7.24.7", ++ "@babel/types": "^7.24.7" ++ }, ++ "engines": { ++ "node": ">=6.9.0" ++ } ++ }, ++ "node_modules/@babel/helper-compilation-targets": { ++ "version": "7.24.8", ++ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.8.tgz", ++ "integrity": "sha512-oU+UoqCHdp+nWVDkpldqIQL/i/bvAv53tRqLG/s+cOXxe66zOYLU7ar/Xs3LdmBihrUMEUhwu6dMZwbNOYDwvw==", ++ "dev": true, ++ "dependencies": { ++ "@babel/compat-data": "^7.24.8", ++ "@babel/helper-validator-option": "^7.24.8", ++ "browserslist": "^4.23.1", ++ "lru-cache": "^5.1.1", ++ "semver": "^6.3.1" ++ }, ++ "engines": { ++ "node": ">=6.9.0" ++ } ++ }, ++ "node_modules/@babel/helper-create-class-features-plugin": { ++ "version": "7.24.8", ++ "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.8.tgz", ++ "integrity": "sha512-4f6Oqnmyp2PP3olgUMmOwC3akxSm5aBYraQ6YDdKy7NcAMkDECHWG0DEnV6M2UAkERgIBhYt8S27rURPg7SxWA==", ++ "dev": true, ++ "dependencies": { ++ "@babel/helper-annotate-as-pure": "^7.24.7", ++ "@babel/helper-environment-visitor": "^7.24.7", ++ "@babel/helper-function-name": "^7.24.7", ++ "@babel/helper-member-expression-to-functions": "^7.24.8", ++ "@babel/helper-optimise-call-expression": "^7.24.7", ++ "@babel/helper-replace-supers": "^7.24.7", ++ "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", ++ "@babel/helper-split-export-declaration": "^7.24.7", ++ "semver": "^6.3.1" ++ }, ++ "engines": { ++ "node": ">=6.9.0" ++ }, ++ "peerDependencies": { ++ "@babel/core": "^7.0.0" ++ } ++ }, ++ "node_modules/@babel/helper-create-regexp-features-plugin": { ++ "version": "7.24.7", ++ "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.24.7.tgz", ++ "integrity": "sha512-03TCmXy2FtXJEZfbXDTSqq1fRJArk7lX9DOFC/47VthYcxyIOx+eXQmdo6DOQvrbpIix+KfXwvuXdFDZHxt+rA==", ++ "dev": true, ++ "dependencies": { ++ "@babel/helper-annotate-as-pure": "^7.24.7", ++ "regexpu-core": "^5.3.1", ++ "semver": "^6.3.1" ++ }, ++ "engines": { ++ "node": ">=6.9.0" ++ }, ++ "peerDependencies": { ++ "@babel/core": "^7.0.0" ++ } ++ }, ++ "node_modules/@babel/helper-define-polyfill-provider": { ++ "version": "0.6.2", ++ "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", ++ "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", ++ "dev": true, ++ "dependencies": { ++ "@babel/helper-compilation-targets": "^7.22.6", ++ "@babel/helper-plugin-utils": "^7.22.5", ++ "debug": "^4.1.1", ++ "lodash.debounce": "^4.0.8", ++ "resolve": "^1.14.2" ++ }, ++ "peerDependencies": { ++ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" ++ } ++ }, ++ "node_modules/@babel/helper-environment-visitor": { ++ "version": "7.24.7", ++ "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz", ++ "integrity": "sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==", ++ "dev": true, ++ "dependencies": { ++ "@babel/types": "^7.24.7" ++ }, ++ "engines": { ++ "node": ">=6.9.0" ++ } ++ }, ++ "node_modules/@babel/helper-function-name": { ++ "version": "7.24.7", ++ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.7.tgz", ++ "integrity": "sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==", ++ "dev": true, ++ "dependencies": { ++ "@babel/template": "^7.24.7", ++ "@babel/types": "^7.24.7" ++ }, ++ "engines": { ++ "node": ">=6.9.0" ++ } ++ }, ++ "node_modules/@babel/helper-hoist-variables": { ++ "version": "7.24.7", ++ "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.7.tgz", ++ "integrity": "sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==", ++ "dev": true, ++ "dependencies": { ++ "@babel/types": "^7.24.7" ++ }, ++ "engines": { ++ "node": ">=6.9.0" ++ } ++ }, ++ "node_modules/@babel/helper-member-expression-to-functions": { ++ "version": "7.24.8", ++ "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.8.tgz", ++ "integrity": "sha512-LABppdt+Lp/RlBxqrh4qgf1oEH/WxdzQNDJIu5gC/W1GyvPVrOBiItmmM8wan2fm4oYqFuFfkXmlGpLQhPY8CA==", ++ "dev": true, ++ "dependencies": { ++ "@babel/traverse": "^7.24.8", ++ "@babel/types": "^7.24.8" ++ }, ++ "engines": { ++ "node": ">=6.9.0" ++ } ++ }, ++ "node_modules/@babel/helper-module-imports": { ++ "version": "7.24.7", ++ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", ++ "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", ++ "dev": true, ++ "dependencies": { ++ "@babel/traverse": "^7.24.7", ++ "@babel/types": "^7.24.7" ++ }, ++ "engines": { ++ "node": ">=6.9.0" ++ } ++ }, ++ "node_modules/@babel/helper-module-transforms": { ++ "version": "7.24.9", ++ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.9.tgz", ++ "integrity": "sha512-oYbh+rtFKj/HwBQkFlUzvcybzklmVdVV3UU+mN7n2t/q3yGHbuVdNxyFvSBO1tfvjyArpHNcWMAzsSPdyI46hw==", ++ "dev": true, ++ "dependencies": { ++ "@babel/helper-environment-visitor": "^7.24.7", ++ "@babel/helper-module-imports": "^7.24.7", ++ "@babel/helper-simple-access": "^7.24.7", ++ "@babel/helper-split-export-declaration": "^7.24.7", ++ "@babel/helper-validator-identifier": "^7.24.7" ++ }, ++ "engines": { ++ "node": ">=6.9.0" ++ }, ++ "peerDependencies": { ++ "@babel/core": "^7.0.0" + } + }, -+ "node_modules/@adraffy/ens-normalize": { -+ "version": "1.11.0", -+ "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.11.0.tgz", -+ "integrity": "sha512-/3DDPKHqqIqxUULp8yP4zODUY1i+2xvVWsv8A79xGWdCAG+8sb0hRh0Rk2QyOJUnnbyPUAZYcpBuRe3nS2OIUg==" -+ }, -+ "node_modules/@ampproject/remapping": { -+ "version": "2.3.0", -+ "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", -+ "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", ++ "node_modules/@babel/helper-optimise-call-expression": { ++ "version": "7.24.7", ++ "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz", ++ "integrity": "sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A==", + "dev": true, + "dependencies": { -+ "@jridgewell/gen-mapping": "^0.3.5", -+ "@jridgewell/trace-mapping": "^0.3.24" ++ "@babel/types": "^7.24.7" + }, + "engines": { -+ "node": ">=6.0.0" ++ "node": ">=6.9.0" + } + }, -+ "node_modules/@babel/code-frame": { ++ "node_modules/@babel/helper-plugin-utils": { ++ "version": "7.24.8", ++ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz", ++ "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==", ++ "dev": true, ++ "engines": { ++ "node": ">=6.9.0" ++ } ++ }, ++ "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", -+ "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", ++ "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.24.7.tgz", ++ "integrity": "sha512-9pKLcTlZ92hNZMQfGCHImUpDOlAgkkpqalWEeftW5FBya75k8Li2ilerxkM/uBEj01iBZXcCIB/bwvDYgWyibA==", + "dev": true, + "dependencies": { -+ "@babel/highlight": "^7.24.7", -+ "picocolors": "^1.0.0" ++ "@babel/helper-annotate-as-pure": "^7.24.7", ++ "@babel/helper-environment-visitor": "^7.24.7", ++ "@babel/helper-wrap-function": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" ++ }, ++ "peerDependencies": { ++ "@babel/core": "^7.0.0" + } + }, -+ "node_modules/@babel/compat-data": { -+ "version": "7.24.9", -+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.9.tgz", -+ "integrity": "sha512-e701mcfApCJqMMueQI0Fb68Amflj83+dvAvHawoBpAz+GDjCIyGHzNwnefjsWJ3xiYAqqiQFoWbspGYBdb2/ng==", ++ "node_modules/@babel/helper-replace-supers": { ++ "version": "7.24.7", ++ "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.24.7.tgz", ++ "integrity": "sha512-qTAxxBM81VEyoAY0TtLrx1oAEJc09ZK67Q9ljQToqCnA+55eNwCORaxlKyu+rNfX86o8OXRUSNUnrtsAZXM9sg==", + "dev": true, ++ "dependencies": { ++ "@babel/helper-environment-visitor": "^7.24.7", ++ "@babel/helper-member-expression-to-functions": "^7.24.7", ++ "@babel/helper-optimise-call-expression": "^7.24.7" ++ }, + "engines": { + "node": ">=6.9.0" ++ }, ++ "peerDependencies": { ++ "@babel/core": "^7.0.0" + } + }, -+ "node_modules/@babel/core": { -+ "version": "7.24.9", -+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.9.tgz", -+ "integrity": "sha512-5e3FI4Q3M3Pbr21+5xJwCv6ZT6KmGkI0vw3Tozy5ODAQFTIWe37iT8Cr7Ice2Ntb+M3iSKCEWMB1MBgKrW3whg==", ++ "node_modules/@babel/helper-simple-access": { ++ "version": "7.24.7", ++ "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", ++ "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", + "dev": true, + "dependencies": { -+ "@ampproject/remapping": "^2.2.0", -+ "@babel/code-frame": "^7.24.7", -+ "@babel/generator": "^7.24.9", -+ "@babel/helper-compilation-targets": "^7.24.8", -+ "@babel/helper-module-transforms": "^7.24.9", -+ "@babel/helpers": "^7.24.8", -+ "@babel/parser": "^7.24.8", -+ "@babel/template": "^7.24.7", -+ "@babel/traverse": "^7.24.8", -+ "@babel/types": "^7.24.9", -+ "convert-source-map": "^2.0.0", -+ "debug": "^4.1.0", -+ "gensync": "^1.0.0-beta.2", -+ "json5": "^2.2.3", -+ "semver": "^6.3.1" ++ "@babel/traverse": "^7.24.7", ++ "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" -+ }, -+ "funding": { -+ "type": "opencollective", -+ "url": "https://opencollective.com/babel" + } + }, -+ "node_modules/@babel/generator": { -+ "version": "7.24.10", -+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.10.tgz", -+ "integrity": "sha512-o9HBZL1G2129luEUlG1hB4N/nlYNWHnpwlND9eOMclRqqu1YDy2sSYVCFUZwl8I1Gxh+QSRrP2vD7EpUmFVXxg==", ++ "node_modules/@babel/helper-skip-transparent-expression-wrappers": { ++ "version": "7.24.7", ++ "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz", ++ "integrity": "sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ==", + "dev": true, + "dependencies": { -+ "@babel/types": "^7.24.9", -+ "@jridgewell/gen-mapping": "^0.3.5", -+ "@jridgewell/trace-mapping": "^0.3.25", -+ "jsesc": "^2.5.1" ++ "@babel/traverse": "^7.24.7", ++ "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, -+ "node_modules/@babel/helper-annotate-as-pure": { ++ "node_modules/@babel/helper-split-export-declaration": { + "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", -+ "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", ++ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz", ++ "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.24.7" @@ -16849,12 +68854,41 @@ + "node": ">=6.9.0" + } + }, -+ "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { ++ "node_modules/@babel/helper-string-parser": { ++ "version": "7.24.8", ++ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", ++ "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", ++ "dev": true, ++ "engines": { ++ "node": ">=6.9.0" ++ } ++ }, ++ "node_modules/@babel/helper-validator-identifier": { + "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.24.7.tgz", -+ "integrity": "sha512-xZeCVVdwb4MsDBkkyZ64tReWYrLRHlMN72vP7Bdm3OUOuyFZExhsHUUnuWnm2/XOlAJzR0LfPpB56WXZn0X/lA==", ++ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", ++ "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", ++ "dev": true, ++ "engines": { ++ "node": ">=6.9.0" ++ } ++ }, ++ "node_modules/@babel/helper-validator-option": { ++ "version": "7.24.8", ++ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz", ++ "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==", ++ "dev": true, ++ "engines": { ++ "node": ">=6.9.0" ++ } ++ }, ++ "node_modules/@babel/helper-wrap-function": { ++ "version": "7.24.7", ++ "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.24.7.tgz", ++ "integrity": "sha512-N9JIYk3TD+1vq/wn77YnJOqMtfWhNewNE+DJV4puD2X7Ew9J4JvrzrFDfTfyv5EgEXVy9/Wt8QiOErzEmv5Ifw==", + "dev": true, + "dependencies": { ++ "@babel/helper-function-name": "^7.24.7", ++ "@babel/template": "^7.24.7", + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, @@ -16862,37 +68896,54 @@ + "node": ">=6.9.0" + } + }, -+ "node_modules/@babel/helper-compilation-targets": { ++ "node_modules/@babel/helpers": { + "version": "7.24.8", -+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.8.tgz", -+ "integrity": "sha512-oU+UoqCHdp+nWVDkpldqIQL/i/bvAv53tRqLG/s+cOXxe66zOYLU7ar/Xs3LdmBihrUMEUhwu6dMZwbNOYDwvw==", ++ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.8.tgz", ++ "integrity": "sha512-gV2265Nkcz7weJJfvDoAEVzC1e2OTDpkGbEsebse8koXUJUXPsCMi7sRo/+SPMuMZ9MtUPnGwITTnQnU5YjyaQ==", + "dev": true, + "dependencies": { -+ "@babel/compat-data": "^7.24.8", -+ "@babel/helper-validator-option": "^7.24.8", -+ "browserslist": "^4.23.1", -+ "lru-cache": "^5.1.1", -+ "semver": "^6.3.1" ++ "@babel/template": "^7.24.7", ++ "@babel/types": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + } + }, -+ "node_modules/@babel/helper-create-class-features-plugin": { ++ "node_modules/@babel/highlight": { ++ "version": "7.24.7", ++ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", ++ "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", ++ "dev": true, ++ "dependencies": { ++ "@babel/helper-validator-identifier": "^7.24.7", ++ "chalk": "^2.4.2", ++ "js-tokens": "^4.0.0", ++ "picocolors": "^1.0.0" ++ }, ++ "engines": { ++ "node": ">=6.9.0" ++ } ++ }, ++ "node_modules/@babel/parser": { + "version": "7.24.8", -+ "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.8.tgz", -+ "integrity": "sha512-4f6Oqnmyp2PP3olgUMmOwC3akxSm5aBYraQ6YDdKy7NcAMkDECHWG0DEnV6M2UAkERgIBhYt8S27rURPg7SxWA==", ++ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.8.tgz", ++ "integrity": "sha512-WzfbgXOkGzZiXXCqk43kKwZjzwx4oulxZi3nq2TYL9mOjQv6kYwul9mz6ID36njuL7Xkp6nJEfok848Zj10j/w==", ++ "dev": true, ++ "bin": { ++ "parser": "bin/babel-parser.js" ++ }, ++ "engines": { ++ "node": ">=6.0.0" ++ } ++ }, ++ "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { ++ "version": "7.24.7", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.24.7.tgz", ++ "integrity": "sha512-TiT1ss81W80eQsN+722OaeQMY/G4yTb4G9JrqeiDADs3N8lbPMGldWi9x8tyqCW5NLx1Jh2AvkE6r6QvEltMMQ==", + "dev": true, + "dependencies": { -+ "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-environment-visitor": "^7.24.7", -+ "@babel/helper-function-name": "^7.24.7", -+ "@babel/helper-member-expression-to-functions": "^7.24.8", -+ "@babel/helper-optimise-call-expression": "^7.24.7", -+ "@babel/helper-replace-supers": "^7.24.7", -+ "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", -+ "@babel/helper-split-export-declaration": "^7.24.7", -+ "semver": "^6.3.1" ++ "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" @@ -16901,15 +68952,13 @@ + "@babel/core": "^7.0.0" + } + }, -+ "node_modules/@babel/helper-create-regexp-features-plugin": { ++ "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.24.7.tgz", -+ "integrity": "sha512-03TCmXy2FtXJEZfbXDTSqq1fRJArk7lX9DOFC/47VthYcxyIOx+eXQmdo6DOQvrbpIix+KfXwvuXdFDZHxt+rA==", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.24.7.tgz", ++ "integrity": "sha512-unaQgZ/iRu/By6tsjMZzpeBZjChYfLYry6HrEXPoz3KmfF0sVBQ1l8zKMQ4xRGLWVsjuvB8nQfjNP/DcfEOCsg==", + "dev": true, + "dependencies": { -+ "@babel/helper-annotate-as-pure": "^7.24.7", -+ "regexpu-core": "^5.3.1", -+ "semver": "^6.3.1" ++ "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" @@ -16918,348 +68967,646 @@ + "@babel/core": "^7.0.0" + } + }, -+ "node_modules/@babel/helper-define-polyfill-provider": { -+ "version": "0.6.2", -+ "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", -+ "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", ++ "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { ++ "version": "7.24.7", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.7.tgz", ++ "integrity": "sha512-+izXIbke1T33mY4MSNnrqhPXDz01WYhEf3yF5NbnUtkiNnm+XBZJl3kNfoK6NKmYlz/D07+l2GWVK/QfDkNCuQ==", + "dev": true, + "dependencies": { -+ "@babel/helper-compilation-targets": "^7.22.6", -+ "@babel/helper-plugin-utils": "^7.22.5", -+ "debug": "^4.1.1", -+ "lodash.debounce": "^4.0.8", -+ "resolve": "^1.14.2" ++ "@babel/helper-plugin-utils": "^7.24.7", ++ "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", ++ "@babel/plugin-transform-optional-chaining": "^7.24.7" ++ }, ++ "engines": { ++ "node": ">=6.9.0" + }, + "peerDependencies": { -+ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" ++ "@babel/core": "^7.13.0" + } + }, -+ "node_modules/@babel/helper-environment-visitor": { ++ "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz", -+ "integrity": "sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.24.7.tgz", ++ "integrity": "sha512-utA4HuR6F4Vvcr+o4DnjL8fCOlgRFGbeeBEGNg3ZTrLFw6VWG5XmUrvcQ0FjIYMU2ST4XcR2Wsp7t9qOAPnxMg==", + "dev": true, + "dependencies": { -+ "@babel/types": "^7.24.7" ++ "@babel/helper-environment-visitor": "^7.24.7", ++ "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" ++ }, ++ "peerDependencies": { ++ "@babel/core": "^7.0.0" + } + }, -+ "node_modules/@babel/helper-function-name": { ++ "node_modules/@babel/plugin-proposal-private-property-in-object": { ++ "version": "7.21.0-placeholder-for-preset-env.2", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", ++ "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", ++ "dev": true, ++ "engines": { ++ "node": ">=6.9.0" ++ }, ++ "peerDependencies": { ++ "@babel/core": "^7.0.0-0" ++ } ++ }, ++ "node_modules/@babel/plugin-syntax-async-generators": { ++ "version": "7.8.4", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", ++ "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", ++ "dev": true, ++ "dependencies": { ++ "@babel/helper-plugin-utils": "^7.8.0" ++ }, ++ "peerDependencies": { ++ "@babel/core": "^7.0.0-0" ++ } ++ }, ++ "node_modules/@babel/plugin-syntax-bigint": { ++ "version": "7.8.3", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", ++ "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", ++ "dev": true, ++ "dependencies": { ++ "@babel/helper-plugin-utils": "^7.8.0" ++ }, ++ "peerDependencies": { ++ "@babel/core": "^7.0.0-0" ++ } ++ }, ++ "node_modules/@babel/plugin-syntax-class-properties": { ++ "version": "7.12.13", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", ++ "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", ++ "dev": true, ++ "dependencies": { ++ "@babel/helper-plugin-utils": "^7.12.13" ++ }, ++ "peerDependencies": { ++ "@babel/core": "^7.0.0-0" ++ } ++ }, ++ "node_modules/@babel/plugin-syntax-class-static-block": { ++ "version": "7.14.5", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", ++ "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", ++ "dev": true, ++ "dependencies": { ++ "@babel/helper-plugin-utils": "^7.14.5" ++ }, ++ "engines": { ++ "node": ">=6.9.0" ++ }, ++ "peerDependencies": { ++ "@babel/core": "^7.0.0-0" ++ } ++ }, ++ "node_modules/@babel/plugin-syntax-dynamic-import": { ++ "version": "7.8.3", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", ++ "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", ++ "dev": true, ++ "dependencies": { ++ "@babel/helper-plugin-utils": "^7.8.0" ++ }, ++ "peerDependencies": { ++ "@babel/core": "^7.0.0-0" ++ } ++ }, ++ "node_modules/@babel/plugin-syntax-export-namespace-from": { ++ "version": "7.8.3", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", ++ "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", ++ "dev": true, ++ "dependencies": { ++ "@babel/helper-plugin-utils": "^7.8.3" ++ }, ++ "peerDependencies": { ++ "@babel/core": "^7.0.0-0" ++ } ++ }, ++ "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.7.tgz", -+ "integrity": "sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.7.tgz", ++ "integrity": "sha512-Ec3NRUMoi8gskrkBe3fNmEQfxDvY8bgfQpz6jlk/41kX9eUjvpyqWU7PBP/pLAvMaSQjbMNKJmvX57jP+M6bPg==", + "dev": true, + "dependencies": { -+ "@babel/template": "^7.24.7", -+ "@babel/types": "^7.24.7" ++ "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" ++ }, ++ "peerDependencies": { ++ "@babel/core": "^7.0.0-0" + } + }, -+ "node_modules/@babel/helper-hoist-variables": { ++ "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.7.tgz", -+ "integrity": "sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.7.tgz", ++ "integrity": "sha512-hbX+lKKeUMGihnK8nvKqmXBInriT3GVjzXKFriV3YC6APGxMbP8RZNFwy91+hocLXq90Mta+HshoB31802bb8A==", ++ "dev": true, ++ "dependencies": { ++ "@babel/helper-plugin-utils": "^7.24.7" ++ }, ++ "engines": { ++ "node": ">=6.9.0" ++ }, ++ "peerDependencies": { ++ "@babel/core": "^7.0.0-0" ++ } ++ }, ++ "node_modules/@babel/plugin-syntax-import-meta": { ++ "version": "7.10.4", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", ++ "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", ++ "dev": true, ++ "dependencies": { ++ "@babel/helper-plugin-utils": "^7.10.4" ++ }, ++ "peerDependencies": { ++ "@babel/core": "^7.0.0-0" ++ } ++ }, ++ "node_modules/@babel/plugin-syntax-json-strings": { ++ "version": "7.8.3", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", ++ "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", ++ "dev": true, ++ "dependencies": { ++ "@babel/helper-plugin-utils": "^7.8.0" ++ }, ++ "peerDependencies": { ++ "@babel/core": "^7.0.0-0" ++ } ++ }, ++ "node_modules/@babel/plugin-syntax-jsx": { ++ "version": "7.24.7", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz", ++ "integrity": "sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==", ++ "dev": true, ++ "dependencies": { ++ "@babel/helper-plugin-utils": "^7.24.7" ++ }, ++ "engines": { ++ "node": ">=6.9.0" ++ }, ++ "peerDependencies": { ++ "@babel/core": "^7.0.0-0" ++ } ++ }, ++ "node_modules/@babel/plugin-syntax-logical-assignment-operators": { ++ "version": "7.10.4", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", ++ "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", ++ "dev": true, ++ "dependencies": { ++ "@babel/helper-plugin-utils": "^7.10.4" ++ }, ++ "peerDependencies": { ++ "@babel/core": "^7.0.0-0" ++ } ++ }, ++ "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { ++ "version": "7.8.3", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", ++ "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", ++ "dev": true, ++ "dependencies": { ++ "@babel/helper-plugin-utils": "^7.8.0" ++ }, ++ "peerDependencies": { ++ "@babel/core": "^7.0.0-0" ++ } ++ }, ++ "node_modules/@babel/plugin-syntax-numeric-separator": { ++ "version": "7.10.4", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", ++ "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", ++ "dev": true, ++ "dependencies": { ++ "@babel/helper-plugin-utils": "^7.10.4" ++ }, ++ "peerDependencies": { ++ "@babel/core": "^7.0.0-0" ++ } ++ }, ++ "node_modules/@babel/plugin-syntax-object-rest-spread": { ++ "version": "7.8.3", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", ++ "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", ++ "dev": true, ++ "dependencies": { ++ "@babel/helper-plugin-utils": "^7.8.0" ++ }, ++ "peerDependencies": { ++ "@babel/core": "^7.0.0-0" ++ } ++ }, ++ "node_modules/@babel/plugin-syntax-optional-catch-binding": { ++ "version": "7.8.3", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", ++ "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", ++ "dev": true, ++ "dependencies": { ++ "@babel/helper-plugin-utils": "^7.8.0" ++ }, ++ "peerDependencies": { ++ "@babel/core": "^7.0.0-0" ++ } ++ }, ++ "node_modules/@babel/plugin-syntax-optional-chaining": { ++ "version": "7.8.3", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", ++ "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", ++ "dev": true, ++ "dependencies": { ++ "@babel/helper-plugin-utils": "^7.8.0" ++ }, ++ "peerDependencies": { ++ "@babel/core": "^7.0.0-0" ++ } ++ }, ++ "node_modules/@babel/plugin-syntax-private-property-in-object": { ++ "version": "7.14.5", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", ++ "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", ++ "dev": true, ++ "dependencies": { ++ "@babel/helper-plugin-utils": "^7.14.5" ++ }, ++ "engines": { ++ "node": ">=6.9.0" ++ }, ++ "peerDependencies": { ++ "@babel/core": "^7.0.0-0" ++ } ++ }, ++ "node_modules/@babel/plugin-syntax-top-level-await": { ++ "version": "7.14.5", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", ++ "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", ++ "dev": true, ++ "dependencies": { ++ "@babel/helper-plugin-utils": "^7.14.5" ++ }, ++ "engines": { ++ "node": ">=6.9.0" ++ }, ++ "peerDependencies": { ++ "@babel/core": "^7.0.0-0" ++ } ++ }, ++ "node_modules/@babel/plugin-syntax-typescript": { ++ "version": "7.24.7", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.7.tgz", ++ "integrity": "sha512-c/+fVeJBB0FeKsFvwytYiUD+LBvhHjGSI0g446PRGdSVGZLRNArBUno2PETbAly3tpiNAQR5XaZ+JslxkotsbA==", + "dev": true, + "dependencies": { -+ "@babel/types": "^7.24.7" ++ "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" ++ }, ++ "peerDependencies": { ++ "@babel/core": "^7.0.0-0" + } + }, -+ "node_modules/@babel/helper-member-expression-to-functions": { -+ "version": "7.24.8", -+ "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.8.tgz", -+ "integrity": "sha512-LABppdt+Lp/RlBxqrh4qgf1oEH/WxdzQNDJIu5gC/W1GyvPVrOBiItmmM8wan2fm4oYqFuFfkXmlGpLQhPY8CA==", ++ "node_modules/@babel/plugin-syntax-unicode-sets-regex": { ++ "version": "7.18.6", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", ++ "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "dev": true, + "dependencies": { -+ "@babel/traverse": "^7.24.8", -+ "@babel/types": "^7.24.8" ++ "@babel/helper-create-regexp-features-plugin": "^7.18.6", ++ "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" ++ }, ++ "peerDependencies": { ++ "@babel/core": "^7.0.0" + } + }, -+ "node_modules/@babel/helper-module-imports": { ++ "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", -+ "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.7.tgz", ++ "integrity": "sha512-Dt9LQs6iEY++gXUwY03DNFat5C2NbO48jj+j/bSAz6b3HgPs39qcPiYt77fDObIcFwj3/C2ICX9YMwGflUoSHQ==", + "dev": true, + "dependencies": { -+ "@babel/traverse": "^7.24.7", -+ "@babel/types": "^7.24.7" ++ "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" ++ }, ++ "peerDependencies": { ++ "@babel/core": "^7.0.0-0" + } + }, -+ "node_modules/@babel/helper-module-transforms": { -+ "version": "7.24.9", -+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.9.tgz", -+ "integrity": "sha512-oYbh+rtFKj/HwBQkFlUzvcybzklmVdVV3UU+mN7n2t/q3yGHbuVdNxyFvSBO1tfvjyArpHNcWMAzsSPdyI46hw==", ++ "node_modules/@babel/plugin-transform-async-generator-functions": { ++ "version": "7.24.7", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.24.7.tgz", ++ "integrity": "sha512-o+iF77e3u7ZS4AoAuJvapz9Fm001PuD2V3Lp6OSE4FYQke+cSewYtnek+THqGRWyQloRCyvWL1OkyfNEl9vr/g==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.24.7", -+ "@babel/helper-module-imports": "^7.24.7", -+ "@babel/helper-simple-access": "^7.24.7", -+ "@babel/helper-split-export-declaration": "^7.24.7", -+ "@babel/helper-validator-identifier": "^7.24.7" ++ "@babel/helper-plugin-utils": "^7.24.7", ++ "@babel/helper-remap-async-to-generator": "^7.24.7", ++ "@babel/plugin-syntax-async-generators": "^7.8.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { -+ "@babel/core": "^7.0.0" ++ "@babel/core": "^7.0.0-0" + } + }, -+ "node_modules/@babel/helper-optimise-call-expression": { ++ "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz", -+ "integrity": "sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A==", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.7.tgz", ++ "integrity": "sha512-SQY01PcJfmQ+4Ash7NE+rpbLFbmqA2GPIgqzxfFTL4t1FKRq4zTms/7htKpoCUI9OcFYgzqfmCdH53s6/jn5fA==", + "dev": true, + "dependencies": { -+ "@babel/types": "^7.24.7" ++ "@babel/helper-module-imports": "^7.24.7", ++ "@babel/helper-plugin-utils": "^7.24.7", ++ "@babel/helper-remap-async-to-generator": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" ++ }, ++ "peerDependencies": { ++ "@babel/core": "^7.0.0-0" + } + }, -+ "node_modules/@babel/helper-plugin-utils": { -+ "version": "7.24.8", -+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz", -+ "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==", ++ "node_modules/@babel/plugin-transform-block-scoped-functions": { ++ "version": "7.24.7", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.7.tgz", ++ "integrity": "sha512-yO7RAz6EsVQDaBH18IDJcMB1HnrUn2FJ/Jslc/WtPPWcjhpUJXU/rjbwmluzp7v/ZzWcEhTMXELnnsz8djWDwQ==", + "dev": true, ++ "dependencies": { ++ "@babel/helper-plugin-utils": "^7.24.7" ++ }, + "engines": { + "node": ">=6.9.0" ++ }, ++ "peerDependencies": { ++ "@babel/core": "^7.0.0-0" + } + }, -+ "node_modules/@babel/helper-remap-async-to-generator": { ++ "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.24.7.tgz", -+ "integrity": "sha512-9pKLcTlZ92hNZMQfGCHImUpDOlAgkkpqalWEeftW5FBya75k8Li2ilerxkM/uBEj01iBZXcCIB/bwvDYgWyibA==", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.7.tgz", ++ "integrity": "sha512-Nd5CvgMbWc+oWzBsuaMcbwjJWAcp5qzrbg69SZdHSP7AMY0AbWFqFO0WTFCA1jxhMCwodRwvRec8k0QUbZk7RQ==", + "dev": true, + "dependencies": { -+ "@babel/helper-annotate-as-pure": "^7.24.7", -+ "@babel/helper-environment-visitor": "^7.24.7", -+ "@babel/helper-wrap-function": "^7.24.7" ++ "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { -+ "@babel/core": "^7.0.0" ++ "@babel/core": "^7.0.0-0" + } + }, -+ "node_modules/@babel/helper-replace-supers": { ++ "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.24.7.tgz", -+ "integrity": "sha512-qTAxxBM81VEyoAY0TtLrx1oAEJc09ZK67Q9ljQToqCnA+55eNwCORaxlKyu+rNfX86o8OXRUSNUnrtsAZXM9sg==", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.7.tgz", ++ "integrity": "sha512-vKbfawVYayKcSeSR5YYzzyXvsDFWU2mD8U5TFeXtbCPLFUqe7GyCgvO6XDHzje862ODrOwy6WCPmKeWHbCFJ4w==", + "dev": true, + "dependencies": { -+ "@babel/helper-environment-visitor": "^7.24.7", -+ "@babel/helper-member-expression-to-functions": "^7.24.7", -+ "@babel/helper-optimise-call-expression": "^7.24.7" ++ "@babel/helper-create-class-features-plugin": "^7.24.7", ++ "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { -+ "@babel/core": "^7.0.0" ++ "@babel/core": "^7.0.0-0" + } + }, -+ "node_modules/@babel/helper-simple-access": { ++ "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", -+ "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.7.tgz", ++ "integrity": "sha512-HMXK3WbBPpZQufbMG4B46A90PkuuhN9vBCb5T8+VAHqvAqvcLi+2cKoukcpmUYkszLhScU3l1iudhrks3DggRQ==", + "dev": true, + "dependencies": { -+ "@babel/traverse": "^7.24.7", -+ "@babel/types": "^7.24.7" ++ "@babel/helper-create-class-features-plugin": "^7.24.7", ++ "@babel/helper-plugin-utils": "^7.24.7", ++ "@babel/plugin-syntax-class-static-block": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" ++ }, ++ "peerDependencies": { ++ "@babel/core": "^7.12.0" + } + }, -+ "node_modules/@babel/helper-skip-transparent-expression-wrappers": { -+ "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz", -+ "integrity": "sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ==", ++ "node_modules/@babel/plugin-transform-classes": { ++ "version": "7.24.8", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.8.tgz", ++ "integrity": "sha512-VXy91c47uujj758ud9wx+OMgheXm4qJfyhj1P18YvlrQkNOSrwsteHk+EFS3OMGfhMhpZa0A+81eE7G4QC+3CA==", + "dev": true, + "dependencies": { -+ "@babel/traverse": "^7.24.7", -+ "@babel/types": "^7.24.7" ++ "@babel/helper-annotate-as-pure": "^7.24.7", ++ "@babel/helper-compilation-targets": "^7.24.8", ++ "@babel/helper-environment-visitor": "^7.24.7", ++ "@babel/helper-function-name": "^7.24.7", ++ "@babel/helper-plugin-utils": "^7.24.8", ++ "@babel/helper-replace-supers": "^7.24.7", ++ "@babel/helper-split-export-declaration": "^7.24.7", ++ "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" ++ }, ++ "peerDependencies": { ++ "@babel/core": "^7.0.0-0" + } + }, -+ "node_modules/@babel/helper-split-export-declaration": { ++ "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz", -+ "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.7.tgz", ++ "integrity": "sha512-25cS7v+707Gu6Ds2oY6tCkUwsJ9YIDbggd9+cu9jzzDgiNq7hR/8dkzxWfKWnTic26vsI3EsCXNd4iEB6e8esQ==", + "dev": true, + "dependencies": { -+ "@babel/types": "^7.24.7" ++ "@babel/helper-plugin-utils": "^7.24.7", ++ "@babel/template": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" ++ }, ++ "peerDependencies": { ++ "@babel/core": "^7.0.0-0" + } + }, -+ "node_modules/@babel/helper-string-parser": { ++ "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.24.8", -+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", -+ "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.8.tgz", ++ "integrity": "sha512-36e87mfY8TnRxc7yc6M9g9gOB7rKgSahqkIKwLpz4Ppk2+zC2Cy1is0uwtuSG6AE4zlTOUa+7JGz9jCJGLqQFQ==", + "dev": true, ++ "dependencies": { ++ "@babel/helper-plugin-utils": "^7.24.8" ++ }, + "engines": { + "node": ">=6.9.0" ++ }, ++ "peerDependencies": { ++ "@babel/core": "^7.0.0-0" + } + }, -+ "node_modules/@babel/helper-validator-identifier": { ++ "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", -+ "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.7.tgz", ++ "integrity": "sha512-ZOA3W+1RRTSWvyqcMJDLqbchh7U4NRGqwRfFSVbOLS/ePIP4vHB5e8T8eXcuqyN1QkgKyj5wuW0lcS85v4CrSw==", + "dev": true, ++ "dependencies": { ++ "@babel/helper-create-regexp-features-plugin": "^7.24.7", ++ "@babel/helper-plugin-utils": "^7.24.7" ++ }, + "engines": { + "node": ">=6.9.0" ++ }, ++ "peerDependencies": { ++ "@babel/core": "^7.0.0-0" + } + }, -+ "node_modules/@babel/helper-validator-option": { -+ "version": "7.24.8", -+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz", -+ "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==", ++ "node_modules/@babel/plugin-transform-duplicate-keys": { ++ "version": "7.24.7", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.7.tgz", ++ "integrity": "sha512-JdYfXyCRihAe46jUIliuL2/s0x0wObgwwiGxw/UbgJBr20gQBThrokO4nYKgWkD7uBaqM7+9x5TU7NkExZJyzw==", + "dev": true, ++ "dependencies": { ++ "@babel/helper-plugin-utils": "^7.24.7" ++ }, + "engines": { + "node": ">=6.9.0" ++ }, ++ "peerDependencies": { ++ "@babel/core": "^7.0.0-0" + } + }, -+ "node_modules/@babel/helper-wrap-function": { ++ "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.24.7.tgz", -+ "integrity": "sha512-N9JIYk3TD+1vq/wn77YnJOqMtfWhNewNE+DJV4puD2X7Ew9J4JvrzrFDfTfyv5EgEXVy9/Wt8QiOErzEmv5Ifw==", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.7.tgz", ++ "integrity": "sha512-sc3X26PhZQDb3JhORmakcbvkeInvxz+A8oda99lj7J60QRuPZvNAk9wQlTBS1ZynelDrDmTU4pw1tyc5d5ZMUg==", + "dev": true, + "dependencies": { -+ "@babel/helper-function-name": "^7.24.7", -+ "@babel/template": "^7.24.7", -+ "@babel/traverse": "^7.24.7", -+ "@babel/types": "^7.24.7" ++ "@babel/helper-plugin-utils": "^7.24.7", ++ "@babel/plugin-syntax-dynamic-import": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" ++ }, ++ "peerDependencies": { ++ "@babel/core": "^7.0.0-0" + } + }, -+ "node_modules/@babel/helpers": { -+ "version": "7.24.8", -+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.8.tgz", -+ "integrity": "sha512-gV2265Nkcz7weJJfvDoAEVzC1e2OTDpkGbEsebse8koXUJUXPsCMi7sRo/+SPMuMZ9MtUPnGwITTnQnU5YjyaQ==", ++ "node_modules/@babel/plugin-transform-exponentiation-operator": { ++ "version": "7.24.7", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.7.tgz", ++ "integrity": "sha512-Rqe/vSc9OYgDajNIK35u7ot+KeCoetqQYFXM4Epf7M7ez3lWlOjrDjrwMei6caCVhfdw+mIKD4cgdGNy5JQotQ==", + "dev": true, + "dependencies": { -+ "@babel/template": "^7.24.7", -+ "@babel/types": "^7.24.8" ++ "@babel/helper-builder-binary-assignment-operator-visitor": "^7.24.7", ++ "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" ++ }, ++ "peerDependencies": { ++ "@babel/core": "^7.0.0-0" + } + }, -+ "node_modules/@babel/highlight": { ++ "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", -+ "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.7.tgz", ++ "integrity": "sha512-v0K9uNYsPL3oXZ/7F9NNIbAj2jv1whUEtyA6aujhekLs56R++JDQuzRcP2/z4WX5Vg/c5lE9uWZA0/iUoFhLTA==", + "dev": true, + "dependencies": { -+ "@babel/helper-validator-identifier": "^7.24.7", -+ "chalk": "^2.4.2", -+ "js-tokens": "^4.0.0", -+ "picocolors": "^1.0.0" ++ "@babel/helper-plugin-utils": "^7.24.7", ++ "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" -+ } -+ }, -+ "node_modules/@babel/parser": { -+ "version": "7.24.8", -+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.8.tgz", -+ "integrity": "sha512-WzfbgXOkGzZiXXCqk43kKwZjzwx4oulxZi3nq2TYL9mOjQv6kYwul9mz6ID36njuL7Xkp6nJEfok848Zj10j/w==", -+ "dev": true, -+ "bin": { -+ "parser": "bin/babel-parser.js" + }, -+ "engines": { -+ "node": ">=6.0.0" ++ "peerDependencies": { ++ "@babel/core": "^7.0.0-0" + } + }, -+ "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { ++ "node_modules/@babel/plugin-transform-for-of": { + "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.24.7.tgz", -+ "integrity": "sha512-TiT1ss81W80eQsN+722OaeQMY/G4yTb4G9JrqeiDADs3N8lbPMGldWi9x8tyqCW5NLx1Jh2AvkE6r6QvEltMMQ==", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.7.tgz", ++ "integrity": "sha512-wo9ogrDG1ITTTBsy46oGiN1dS9A7MROBTcYsfS8DtsImMkHk9JXJ3EWQM6X2SUw4x80uGPlwj0o00Uoc6nEE3g==", + "dev": true, + "dependencies": { -+ "@babel/helper-environment-visitor": "^7.24.7", -+ "@babel/helper-plugin-utils": "^7.24.7" ++ "@babel/helper-plugin-utils": "^7.24.7", ++ "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { -+ "@babel/core": "^7.0.0" ++ "@babel/core": "^7.0.0-0" + } + }, -+ "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { ++ "node_modules/@babel/plugin-transform-function-name": { + "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.24.7.tgz", -+ "integrity": "sha512-unaQgZ/iRu/By6tsjMZzpeBZjChYfLYry6HrEXPoz3KmfF0sVBQ1l8zKMQ4xRGLWVsjuvB8nQfjNP/DcfEOCsg==", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.24.7.tgz", ++ "integrity": "sha512-U9FcnA821YoILngSmYkW6FjyQe2TyZD5pHt4EVIhmcTkrJw/3KqcrRSxuOo5tFZJi7TE19iDyI1u+weTI7bn2w==", + "dev": true, + "dependencies": { ++ "@babel/helper-compilation-targets": "^7.24.7", ++ "@babel/helper-function-name": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { -+ "@babel/core": "^7.0.0" ++ "@babel/core": "^7.0.0-0" + } + }, -+ "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { ++ "node_modules/@babel/plugin-transform-json-strings": { + "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.7.tgz", -+ "integrity": "sha512-+izXIbke1T33mY4MSNnrqhPXDz01WYhEf3yF5NbnUtkiNnm+XBZJl3kNfoK6NKmYlz/D07+l2GWVK/QfDkNCuQ==", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.7.tgz", ++ "integrity": "sha512-2yFnBGDvRuxAaE/f0vfBKvtnvvqU8tGpMHqMNpTN2oWMKIR3NqFkjaAgGwawhqK/pIN2T3XdjGPdaG0vDhOBGw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", -+ "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", -+ "@babel/plugin-transform-optional-chaining": "^7.24.7" ++ "@babel/plugin-syntax-json-strings": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { -+ "@babel/core": "^7.13.0" ++ "@babel/core": "^7.0.0-0" + } + }, -+ "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { ++ "node_modules/@babel/plugin-transform-literals": { + "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.24.7.tgz", -+ "integrity": "sha512-utA4HuR6F4Vvcr+o4DnjL8fCOlgRFGbeeBEGNg3ZTrLFw6VWG5XmUrvcQ0FjIYMU2ST4XcR2Wsp7t9qOAPnxMg==", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.24.7.tgz", ++ "integrity": "sha512-vcwCbb4HDH+hWi8Pqenwnjy+UiklO4Kt1vfspcQYFhJdpthSnW8XvWGyDZWKNVrVbVViI/S7K9PDJZiUmP2fYQ==", + "dev": true, + "dependencies": { -+ "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { -+ "@babel/core": "^7.0.0" ++ "@babel/core": "^7.0.0-0" + } + }, -+ "node_modules/@babel/plugin-proposal-private-property-in-object": { -+ "version": "7.21.0-placeholder-for-preset-env.2", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", -+ "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", ++ "node_modules/@babel/plugin-transform-logical-assignment-operators": { ++ "version": "7.24.7", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.7.tgz", ++ "integrity": "sha512-4D2tpwlQ1odXmTEIFWy9ELJcZHqrStlzK/dAOWYyxX3zT0iXQB6banjgeOJQXzEc4S0E0a5A+hahxPaEFYftsw==", + "dev": true, ++ "dependencies": { ++ "@babel/helper-plugin-utils": "^7.24.7", ++ "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" ++ }, + "engines": { + "node": ">=6.9.0" + }, @@ -17267,49 +69614,64 @@ + "@babel/core": "^7.0.0-0" + } + }, -+ "node_modules/@babel/plugin-syntax-async-generators": { -+ "version": "7.8.4", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", -+ "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", ++ "node_modules/@babel/plugin-transform-member-expression-literals": { ++ "version": "7.24.7", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.7.tgz", ++ "integrity": "sha512-T/hRC1uqrzXMKLQ6UCwMT85S3EvqaBXDGf0FaMf4446Qx9vKwlghvee0+uuZcDUCZU5RuNi4781UQ7R308zzBw==", + "dev": true, + "dependencies": { -+ "@babel/helper-plugin-utils": "^7.8.0" ++ "@babel/helper-plugin-utils": "^7.24.7" ++ }, ++ "engines": { ++ "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, -+ "node_modules/@babel/plugin-syntax-bigint": { -+ "version": "7.8.3", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", -+ "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", ++ "node_modules/@babel/plugin-transform-modules-amd": { ++ "version": "7.24.7", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.7.tgz", ++ "integrity": "sha512-9+pB1qxV3vs/8Hdmz/CulFB8w2tuu6EB94JZFsjdqxQokwGa9Unap7Bo2gGBGIvPmDIVvQrom7r5m/TCDMURhg==", + "dev": true, + "dependencies": { -+ "@babel/helper-plugin-utils": "^7.8.0" ++ "@babel/helper-module-transforms": "^7.24.7", ++ "@babel/helper-plugin-utils": "^7.24.7" ++ }, ++ "engines": { ++ "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, -+ "node_modules/@babel/plugin-syntax-class-properties": { -+ "version": "7.12.13", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", -+ "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", ++ "node_modules/@babel/plugin-transform-modules-commonjs": { ++ "version": "7.24.8", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.8.tgz", ++ "integrity": "sha512-WHsk9H8XxRs3JXKWFiqtQebdh9b/pTk4EgueygFzYlTKAg0Ud985mSevdNjdXdFBATSKVJGQXP1tv6aGbssLKA==", + "dev": true, + "dependencies": { -+ "@babel/helper-plugin-utils": "^7.12.13" ++ "@babel/helper-module-transforms": "^7.24.8", ++ "@babel/helper-plugin-utils": "^7.24.8", ++ "@babel/helper-simple-access": "^7.24.7" ++ }, ++ "engines": { ++ "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, -+ "node_modules/@babel/plugin-syntax-class-static-block": { -+ "version": "7.14.5", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", -+ "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", ++ "node_modules/@babel/plugin-transform-modules-systemjs": { ++ "version": "7.24.7", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.24.7.tgz", ++ "integrity": "sha512-GYQE0tW7YoaN13qFh3O1NCY4MPkUiAH3fiF7UcV/I3ajmDKEdG3l+UOcbAm4zUE3gnvUU+Eni7XrVKo9eO9auw==", + "dev": true, + "dependencies": { -+ "@babel/helper-plugin-utils": "^7.14.5" ++ "@babel/helper-hoist-variables": "^7.24.7", ++ "@babel/helper-module-transforms": "^7.24.7", ++ "@babel/helper-plugin-utils": "^7.24.7", ++ "@babel/helper-validator-identifier": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" @@ -17318,34 +69680,42 @@ + "@babel/core": "^7.0.0-0" + } + }, -+ "node_modules/@babel/plugin-syntax-dynamic-import": { -+ "version": "7.8.3", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", -+ "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", ++ "node_modules/@babel/plugin-transform-modules-umd": { ++ "version": "7.24.7", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.7.tgz", ++ "integrity": "sha512-3aytQvqJ/h9z4g8AsKPLvD4Zqi2qT+L3j7XoFFu1XBlZWEl2/1kWnhmAbxpLgPrHSY0M6UA02jyTiwUVtiKR6A==", + "dev": true, + "dependencies": { -+ "@babel/helper-plugin-utils": "^7.8.0" ++ "@babel/helper-module-transforms": "^7.24.7", ++ "@babel/helper-plugin-utils": "^7.24.7" ++ }, ++ "engines": { ++ "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, -+ "node_modules/@babel/plugin-syntax-export-namespace-from": { -+ "version": "7.8.3", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", -+ "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", ++ "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { ++ "version": "7.24.7", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.24.7.tgz", ++ "integrity": "sha512-/jr7h/EWeJtk1U/uz2jlsCioHkZk1JJZVcc8oQsJ1dUlaJD83f4/6Zeh2aHt9BIFokHIsSeDfhUmju0+1GPd6g==", + "dev": true, + "dependencies": { -+ "@babel/helper-plugin-utils": "^7.8.3" ++ "@babel/helper-create-regexp-features-plugin": "^7.24.7", ++ "@babel/helper-plugin-utils": "^7.24.7" ++ }, ++ "engines": { ++ "node": ">=6.9.0" + }, + "peerDependencies": { -+ "@babel/core": "^7.0.0-0" ++ "@babel/core": "^7.0.0" + } + }, -+ "node_modules/@babel/plugin-syntax-import-assertions": { ++ "node_modules/@babel/plugin-transform-new-target": { + "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.7.tgz", -+ "integrity": "sha512-Ec3NRUMoi8gskrkBe3fNmEQfxDvY8bgfQpz6jlk/41kX9eUjvpyqWU7PBP/pLAvMaSQjbMNKJmvX57jP+M6bPg==", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.7.tgz", ++ "integrity": "sha512-RNKwfRIXg4Ls/8mMTza5oPF5RkOW8Wy/WgMAp1/F1yZ8mMbtwXW+HDoJiOsagWrAhI5f57Vncrmr9XeT4CVapA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" @@ -17357,13 +69727,14 @@ + "@babel/core": "^7.0.0-0" + } + }, -+ "node_modules/@babel/plugin-syntax-import-attributes": { ++ "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.7.tgz", -+ "integrity": "sha512-hbX+lKKeUMGihnK8nvKqmXBInriT3GVjzXKFriV3YC6APGxMbP8RZNFwy91+hocLXq90Mta+HshoB31802bb8A==", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.7.tgz", ++ "integrity": "sha512-Ts7xQVk1OEocqzm8rHMXHlxvsfZ0cEF2yomUqpKENHWMF4zKk175Y4q8H5knJes6PgYad50uuRmt3UJuhBw8pQ==", + "dev": true, + "dependencies": { -+ "@babel/helper-plugin-utils": "^7.24.7" ++ "@babel/helper-plugin-utils": "^7.24.7", ++ "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" @@ -17372,37 +69743,48 @@ + "@babel/core": "^7.0.0-0" + } + }, -+ "node_modules/@babel/plugin-syntax-import-meta": { -+ "version": "7.10.4", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", -+ "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", ++ "node_modules/@babel/plugin-transform-numeric-separator": { ++ "version": "7.24.7", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.7.tgz", ++ "integrity": "sha512-e6q1TiVUzvH9KRvicuxdBTUj4AdKSRwzIyFFnfnezpCfP2/7Qmbb8qbU2j7GODbl4JMkblitCQjKYUaX/qkkwA==", + "dev": true, + "dependencies": { -+ "@babel/helper-plugin-utils": "^7.10.4" ++ "@babel/helper-plugin-utils": "^7.24.7", ++ "@babel/plugin-syntax-numeric-separator": "^7.10.4" ++ }, ++ "engines": { ++ "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, -+ "node_modules/@babel/plugin-syntax-json-strings": { -+ "version": "7.8.3", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", -+ "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", ++ "node_modules/@babel/plugin-transform-object-rest-spread": { ++ "version": "7.24.7", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.7.tgz", ++ "integrity": "sha512-4QrHAr0aXQCEFni2q4DqKLD31n2DL+RxcwnNjDFkSG0eNQ/xCavnRkfCUjsyqGC2OviNJvZOF/mQqZBw7i2C5Q==", + "dev": true, + "dependencies": { -+ "@babel/helper-plugin-utils": "^7.8.0" ++ "@babel/helper-compilation-targets": "^7.24.7", ++ "@babel/helper-plugin-utils": "^7.24.7", ++ "@babel/plugin-syntax-object-rest-spread": "^7.8.3", ++ "@babel/plugin-transform-parameters": "^7.24.7" ++ }, ++ "engines": { ++ "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, -+ "node_modules/@babel/plugin-syntax-jsx": { ++ "node_modules/@babel/plugin-transform-object-super": { + "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz", -+ "integrity": "sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.7.tgz", ++ "integrity": "sha512-A/vVLwN6lBrMFmMDmPPz0jnE6ZGx7Jq7d6sT/Ev4H65RER6pZ+kczlf1DthF5N0qaPHBsI7UXiE8Zy66nmAovg==", + "dev": true, + "dependencies": { -+ "@babel/helper-plugin-utils": "^7.24.7" ++ "@babel/helper-plugin-utils": "^7.24.7", ++ "@babel/helper-replace-supers": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" @@ -17411,85 +69793,111 @@ + "@babel/core": "^7.0.0-0" + } + }, -+ "node_modules/@babel/plugin-syntax-logical-assignment-operators": { -+ "version": "7.10.4", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", -+ "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", ++ "node_modules/@babel/plugin-transform-optional-catch-binding": { ++ "version": "7.24.7", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.7.tgz", ++ "integrity": "sha512-uLEndKqP5BfBbC/5jTwPxLh9kqPWWgzN/f8w6UwAIirAEqiIVJWWY312X72Eub09g5KF9+Zn7+hT7sDxmhRuKA==", + "dev": true, + "dependencies": { -+ "@babel/helper-plugin-utils": "^7.10.4" ++ "@babel/helper-plugin-utils": "^7.24.7", ++ "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" ++ }, ++ "engines": { ++ "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, -+ "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { -+ "version": "7.8.3", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", -+ "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", ++ "node_modules/@babel/plugin-transform-optional-chaining": { ++ "version": "7.24.8", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.8.tgz", ++ "integrity": "sha512-5cTOLSMs9eypEy8JUVvIKOu6NgvbJMnpG62VpIHrTmROdQ+L5mDAaI40g25k5vXti55JWNX5jCkq3HZxXBQANw==", + "dev": true, + "dependencies": { -+ "@babel/helper-plugin-utils": "^7.8.0" ++ "@babel/helper-plugin-utils": "^7.24.8", ++ "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", ++ "@babel/plugin-syntax-optional-chaining": "^7.8.3" ++ }, ++ "engines": { ++ "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, -+ "node_modules/@babel/plugin-syntax-numeric-separator": { -+ "version": "7.10.4", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", -+ "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", ++ "node_modules/@babel/plugin-transform-parameters": { ++ "version": "7.24.7", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.7.tgz", ++ "integrity": "sha512-yGWW5Rr+sQOhK0Ot8hjDJuxU3XLRQGflvT4lhlSY0DFvdb3TwKaY26CJzHtYllU0vT9j58hc37ndFPsqT1SrzA==", + "dev": true, + "dependencies": { -+ "@babel/helper-plugin-utils": "^7.10.4" ++ "@babel/helper-plugin-utils": "^7.24.7" ++ }, ++ "engines": { ++ "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, -+ "node_modules/@babel/plugin-syntax-object-rest-spread": { -+ "version": "7.8.3", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", -+ "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", ++ "node_modules/@babel/plugin-transform-private-methods": { ++ "version": "7.24.7", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.7.tgz", ++ "integrity": "sha512-COTCOkG2hn4JKGEKBADkA8WNb35TGkkRbI5iT845dB+NyqgO8Hn+ajPbSnIQznneJTa3d30scb6iz/DhH8GsJQ==", + "dev": true, + "dependencies": { -+ "@babel/helper-plugin-utils": "^7.8.0" ++ "@babel/helper-create-class-features-plugin": "^7.24.7", ++ "@babel/helper-plugin-utils": "^7.24.7" ++ }, ++ "engines": { ++ "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, -+ "node_modules/@babel/plugin-syntax-optional-catch-binding": { -+ "version": "7.8.3", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", -+ "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", ++ "node_modules/@babel/plugin-transform-private-property-in-object": { ++ "version": "7.24.7", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.7.tgz", ++ "integrity": "sha512-9z76mxwnwFxMyxZWEgdgECQglF2Q7cFLm0kMf8pGwt+GSJsY0cONKj/UuO4bOH0w/uAel3ekS4ra5CEAyJRmDA==", + "dev": true, + "dependencies": { -+ "@babel/helper-plugin-utils": "^7.8.0" ++ "@babel/helper-annotate-as-pure": "^7.24.7", ++ "@babel/helper-create-class-features-plugin": "^7.24.7", ++ "@babel/helper-plugin-utils": "^7.24.7", ++ "@babel/plugin-syntax-private-property-in-object": "^7.14.5" ++ }, ++ "engines": { ++ "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, -+ "node_modules/@babel/plugin-syntax-optional-chaining": { -+ "version": "7.8.3", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", -+ "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", ++ "node_modules/@babel/plugin-transform-property-literals": { ++ "version": "7.24.7", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.7.tgz", ++ "integrity": "sha512-EMi4MLQSHfd2nrCqQEWxFdha2gBCqU4ZcCng4WBGZ5CJL4bBRW0ptdqqDdeirGZcpALazVVNJqRmsO8/+oNCBA==", + "dev": true, + "dependencies": { -+ "@babel/helper-plugin-utils": "^7.8.0" ++ "@babel/helper-plugin-utils": "^7.24.7" ++ }, ++ "engines": { ++ "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, -+ "node_modules/@babel/plugin-syntax-private-property-in-object": { -+ "version": "7.14.5", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", -+ "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", ++ "node_modules/@babel/plugin-transform-regenerator": { ++ "version": "7.24.7", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.7.tgz", ++ "integrity": "sha512-lq3fvXPdimDrlg6LWBoqj+r/DEWgONuwjuOuQCSYgRroXDH/IdM1C0IZf59fL5cHLpjEH/O6opIRBbqv7ELnuA==", + "dev": true, + "dependencies": { -+ "@babel/helper-plugin-utils": "^7.14.5" ++ "@babel/helper-plugin-utils": "^7.24.7", ++ "regenerator-transform": "^0.15.2" + }, + "engines": { + "node": ">=6.9.0" @@ -17498,13 +69906,13 @@ + "@babel/core": "^7.0.0-0" + } + }, -+ "node_modules/@babel/plugin-syntax-top-level-await": { -+ "version": "7.14.5", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", -+ "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", ++ "node_modules/@babel/plugin-transform-reserved-words": { ++ "version": "7.24.7", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.7.tgz", ++ "integrity": "sha512-0DUq0pHcPKbjFZCfTss/pGkYMfy3vFWydkUBd9r0GHpIyfs2eCDENvqadMycRS9wZCXR41wucAfJHJmwA0UmoQ==", + "dev": true, + "dependencies": { -+ "@babel/helper-plugin-utils": "^7.14.5" ++ "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" @@ -17513,10 +69921,10 @@ + "@babel/core": "^7.0.0-0" + } + }, -+ "node_modules/@babel/plugin-syntax-typescript": { ++ "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.7.tgz", -+ "integrity": "sha512-c/+fVeJBB0FeKsFvwytYiUD+LBvhHjGSI0g446PRGdSVGZLRNArBUno2PETbAly3tpiNAQR5XaZ+JslxkotsbA==", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.7.tgz", ++ "integrity": "sha512-KsDsevZMDsigzbA09+vacnLpmPH4aWjcZjXdyFKGzpplxhbeB4wYtury3vglQkg6KM/xEPKt73eCjPPf1PgXBA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" @@ -17528,26 +69936,26 @@ + "@babel/core": "^7.0.0-0" + } + }, -+ "node_modules/@babel/plugin-syntax-unicode-sets-regex": { -+ "version": "7.18.6", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", -+ "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", ++ "node_modules/@babel/plugin-transform-spread": { ++ "version": "7.24.7", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.7.tgz", ++ "integrity": "sha512-x96oO0I09dgMDxJaANcRyD4ellXFLLiWhuwDxKZX5g2rWP1bTPkBSwCYv96VDXVT1bD9aPj8tppr5ITIh8hBng==", + "dev": true, + "dependencies": { -+ "@babel/helper-create-regexp-features-plugin": "^7.18.6", -+ "@babel/helper-plugin-utils": "^7.18.6" ++ "@babel/helper-plugin-utils": "^7.24.7", ++ "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { -+ "@babel/core": "^7.0.0" ++ "@babel/core": "^7.0.0-0" + } + }, -+ "node_modules/@babel/plugin-transform-arrow-functions": { ++ "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.7.tgz", -+ "integrity": "sha512-Dt9LQs6iEY++gXUwY03DNFat5C2NbO48jj+j/bSAz6b3HgPs39qcPiYt77fDObIcFwj3/C2ICX9YMwGflUoSHQ==", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.7.tgz", ++ "integrity": "sha512-kHPSIJc9v24zEml5geKg9Mjx5ULpfncj0wRpYtxbvKyTtHCYDkVE3aHQ03FrpEo4gEe2vrJJS1Y9CJTaThA52g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" @@ -17559,16 +69967,13 @@ + "@babel/core": "^7.0.0-0" + } + }, -+ "node_modules/@babel/plugin-transform-async-generator-functions": { ++ "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.24.7.tgz", -+ "integrity": "sha512-o+iF77e3u7ZS4AoAuJvapz9Fm001PuD2V3Lp6OSE4FYQke+cSewYtnek+THqGRWyQloRCyvWL1OkyfNEl9vr/g==", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.7.tgz", ++ "integrity": "sha512-AfDTQmClklHCOLxtGoP7HkeMw56k1/bTQjwsfhL6pppo/M4TOBSq+jjBUBLmV/4oeFg4GWMavIl44ZeCtmmZTw==", + "dev": true, + "dependencies": { -+ "@babel/helper-environment-visitor": "^7.24.7", -+ "@babel/helper-plugin-utils": "^7.24.7", -+ "@babel/helper-remap-async-to-generator": "^7.24.7", -+ "@babel/plugin-syntax-async-generators": "^7.8.4" ++ "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" @@ -17577,15 +69982,13 @@ + "@babel/core": "^7.0.0-0" + } + }, -+ "node_modules/@babel/plugin-transform-async-to-generator": { -+ "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.7.tgz", -+ "integrity": "sha512-SQY01PcJfmQ+4Ash7NE+rpbLFbmqA2GPIgqzxfFTL4t1FKRq4zTms/7htKpoCUI9OcFYgzqfmCdH53s6/jn5fA==", ++ "node_modules/@babel/plugin-transform-typeof-symbol": { ++ "version": "7.24.8", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.8.tgz", ++ "integrity": "sha512-adNTUpDCVnmAE58VEqKlAA6ZBlNkMnWD0ZcW76lyNFN3MJniyGFZfNwERVk8Ap56MCnXztmDr19T4mPTztcuaw==", + "dev": true, + "dependencies": { -+ "@babel/helper-module-imports": "^7.24.7", -+ "@babel/helper-plugin-utils": "^7.24.7", -+ "@babel/helper-remap-async-to-generator": "^7.24.7" ++ "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" @@ -17594,10 +69997,10 @@ + "@babel/core": "^7.0.0-0" + } + }, -+ "node_modules/@babel/plugin-transform-block-scoped-functions": { ++ "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.7.tgz", -+ "integrity": "sha512-yO7RAz6EsVQDaBH18IDJcMB1HnrUn2FJ/Jslc/WtPPWcjhpUJXU/rjbwmluzp7v/ZzWcEhTMXELnnsz8djWDwQ==", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.7.tgz", ++ "integrity": "sha512-U3ap1gm5+4edc2Q/P+9VrBNhGkfnf+8ZqppY71Bo/pzZmXhhLdqgaUl6cuB07O1+AQJtCLfaOmswiNbSQ9ivhw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" @@ -17609,12 +70012,13 @@ + "@babel/core": "^7.0.0-0" + } + }, -+ "node_modules/@babel/plugin-transform-block-scoping": { ++ "node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.7.tgz", -+ "integrity": "sha512-Nd5CvgMbWc+oWzBsuaMcbwjJWAcp5qzrbg69SZdHSP7AMY0AbWFqFO0WTFCA1jxhMCwodRwvRec8k0QUbZk7RQ==", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.7.tgz", ++ "integrity": "sha512-uH2O4OV5M9FZYQrwc7NdVmMxQJOCCzFeYudlZSzUAHRFeOujQefa92E74TQDVskNHCzOXoigEuoyzHDhaEaK5w==", + "dev": true, + "dependencies": { ++ "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { @@ -17624,13 +70028,13 @@ + "@babel/core": "^7.0.0-0" + } + }, -+ "node_modules/@babel/plugin-transform-class-properties": { ++ "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.7.tgz", -+ "integrity": "sha512-vKbfawVYayKcSeSR5YYzzyXvsDFWU2mD8U5TFeXtbCPLFUqe7GyCgvO6XDHzje862ODrOwy6WCPmKeWHbCFJ4w==", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.7.tgz", ++ "integrity": "sha512-hlQ96MBZSAXUq7ltkjtu3FJCCSMx/j629ns3hA3pXnBXjanNP0LHi+JpPeA81zaWgVK1VGH95Xuy7u0RyQ8kMg==", + "dev": true, + "dependencies": { -+ "@babel/helper-create-class-features-plugin": "^7.24.7", ++ "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { @@ -17640,37 +70044,109 @@ + "@babel/core": "^7.0.0-0" + } + }, -+ "node_modules/@babel/plugin-transform-class-static-block": { ++ "node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.7.tgz", -+ "integrity": "sha512-HMXK3WbBPpZQufbMG4B46A90PkuuhN9vBCb5T8+VAHqvAqvcLi+2cKoukcpmUYkszLhScU3l1iudhrks3DggRQ==", ++ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.24.7.tgz", ++ "integrity": "sha512-2G8aAvF4wy1w/AGZkemprdGMRg5o6zPNhbHVImRz3lss55TYCBd6xStN19rt8XJHq20sqV0JbyWjOWwQRwV/wg==", + "dev": true, + "dependencies": { -+ "@babel/helper-create-class-features-plugin": "^7.24.7", -+ "@babel/helper-plugin-utils": "^7.24.7", -+ "@babel/plugin-syntax-class-static-block": "^7.14.5" ++ "@babel/helper-create-regexp-features-plugin": "^7.24.7", ++ "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { -+ "@babel/core": "^7.12.0" ++ "@babel/core": "^7.0.0" + } + }, -+ "node_modules/@babel/plugin-transform-classes": { ++ "node_modules/@babel/preset-env": { + "version": "7.24.8", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.8.tgz", -+ "integrity": "sha512-VXy91c47uujj758ud9wx+OMgheXm4qJfyhj1P18YvlrQkNOSrwsteHk+EFS3OMGfhMhpZa0A+81eE7G4QC+3CA==", ++ "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.24.8.tgz", ++ "integrity": "sha512-vObvMZB6hNWuDxhSaEPTKCwcqkAIuDtE+bQGn4XMXne1DSLzFVY8Vmj1bm+mUQXYNN8NmaQEO+r8MMbzPr1jBQ==", + "dev": true, + "dependencies": { -+ "@babel/helper-annotate-as-pure": "^7.24.7", ++ "@babel/compat-data": "^7.24.8", + "@babel/helper-compilation-targets": "^7.24.8", -+ "@babel/helper-environment-visitor": "^7.24.7", -+ "@babel/helper-function-name": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.8", -+ "@babel/helper-replace-supers": "^7.24.7", -+ "@babel/helper-split-export-declaration": "^7.24.7", -+ "globals": "^11.1.0" ++ "@babel/helper-validator-option": "^7.24.8", ++ "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.24.7", ++ "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.24.7", ++ "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.7", ++ "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.24.7", ++ "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", ++ "@babel/plugin-syntax-async-generators": "^7.8.4", ++ "@babel/plugin-syntax-class-properties": "^7.12.13", ++ "@babel/plugin-syntax-class-static-block": "^7.14.5", ++ "@babel/plugin-syntax-dynamic-import": "^7.8.3", ++ "@babel/plugin-syntax-export-namespace-from": "^7.8.3", ++ "@babel/plugin-syntax-import-assertions": "^7.24.7", ++ "@babel/plugin-syntax-import-attributes": "^7.24.7", ++ "@babel/plugin-syntax-import-meta": "^7.10.4", ++ "@babel/plugin-syntax-json-strings": "^7.8.3", ++ "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", ++ "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", ++ "@babel/plugin-syntax-numeric-separator": "^7.10.4", ++ "@babel/plugin-syntax-object-rest-spread": "^7.8.3", ++ "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", ++ "@babel/plugin-syntax-optional-chaining": "^7.8.3", ++ "@babel/plugin-syntax-private-property-in-object": "^7.14.5", ++ "@babel/plugin-syntax-top-level-await": "^7.14.5", ++ "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", ++ "@babel/plugin-transform-arrow-functions": "^7.24.7", ++ "@babel/plugin-transform-async-generator-functions": "^7.24.7", ++ "@babel/plugin-transform-async-to-generator": "^7.24.7", ++ "@babel/plugin-transform-block-scoped-functions": "^7.24.7", ++ "@babel/plugin-transform-block-scoping": "^7.24.7", ++ "@babel/plugin-transform-class-properties": "^7.24.7", ++ "@babel/plugin-transform-class-static-block": "^7.24.7", ++ "@babel/plugin-transform-classes": "^7.24.8", ++ "@babel/plugin-transform-computed-properties": "^7.24.7", ++ "@babel/plugin-transform-destructuring": "^7.24.8", ++ "@babel/plugin-transform-dotall-regex": "^7.24.7", ++ "@babel/plugin-transform-duplicate-keys": "^7.24.7", ++ "@babel/plugin-transform-dynamic-import": "^7.24.7", ++ "@babel/plugin-transform-exponentiation-operator": "^7.24.7", ++ "@babel/plugin-transform-export-namespace-from": "^7.24.7", ++ "@babel/plugin-transform-for-of": "^7.24.7", ++ "@babel/plugin-transform-function-name": "^7.24.7", ++ "@babel/plugin-transform-json-strings": "^7.24.7", ++ "@babel/plugin-transform-literals": "^7.24.7", ++ "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", ++ "@babel/plugin-transform-member-expression-literals": "^7.24.7", ++ "@babel/plugin-transform-modules-amd": "^7.24.7", ++ "@babel/plugin-transform-modules-commonjs": "^7.24.8", ++ "@babel/plugin-transform-modules-systemjs": "^7.24.7", ++ "@babel/plugin-transform-modules-umd": "^7.24.7", ++ "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", ++ "@babel/plugin-transform-new-target": "^7.24.7", ++ "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", ++ "@babel/plugin-transform-numeric-separator": "^7.24.7", ++ "@babel/plugin-transform-object-rest-spread": "^7.24.7", ++ "@babel/plugin-transform-object-super": "^7.24.7", ++ "@babel/plugin-transform-optional-catch-binding": "^7.24.7", ++ "@babel/plugin-transform-optional-chaining": "^7.24.8", ++ "@babel/plugin-transform-parameters": "^7.24.7", ++ "@babel/plugin-transform-private-methods": "^7.24.7", ++ "@babel/plugin-transform-private-property-in-object": "^7.24.7", ++ "@babel/plugin-transform-property-literals": "^7.24.7", ++ "@babel/plugin-transform-regenerator": "^7.24.7", ++ "@babel/plugin-transform-reserved-words": "^7.24.7", ++ "@babel/plugin-transform-shorthand-properties": "^7.24.7", ++ "@babel/plugin-transform-spread": "^7.24.7", ++ "@babel/plugin-transform-sticky-regex": "^7.24.7", ++ "@babel/plugin-transform-template-literals": "^7.24.7", ++ "@babel/plugin-transform-typeof-symbol": "^7.24.8", ++ "@babel/plugin-transform-unicode-escapes": "^7.24.7", ++ "@babel/plugin-transform-unicode-property-regex": "^7.24.7", ++ "@babel/plugin-transform-unicode-regex": "^7.24.7", ++ "@babel/plugin-transform-unicode-sets-regex": "^7.24.7", ++ "@babel/preset-modules": "0.1.6-no-external-plugins", ++ "babel-plugin-polyfill-corejs2": "^0.4.10", ++ "babel-plugin-polyfill-corejs3": "^0.10.4", ++ "babel-plugin-polyfill-regenerator": "^0.6.1", ++ "core-js-compat": "^3.37.1", ++ "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" @@ -17679,984 +70155,1105 @@ + "@babel/core": "^7.0.0-0" + } + }, -+ "node_modules/@babel/plugin-transform-computed-properties": { -+ "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.7.tgz", -+ "integrity": "sha512-25cS7v+707Gu6Ds2oY6tCkUwsJ9YIDbggd9+cu9jzzDgiNq7hR/8dkzxWfKWnTic26vsI3EsCXNd4iEB6e8esQ==", ++ "node_modules/@babel/preset-modules": { ++ "version": "0.1.6-no-external-plugins", ++ "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", ++ "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "dev": true, + "dependencies": { -+ "@babel/helper-plugin-utils": "^7.24.7", -+ "@babel/template": "^7.24.7" -+ }, -+ "engines": { -+ "node": ">=6.9.0" ++ "@babel/helper-plugin-utils": "^7.0.0", ++ "@babel/types": "^7.4.4", ++ "esutils": "^2.0.2" + }, + "peerDependencies": { -+ "@babel/core": "^7.0.0-0" ++ "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" + } + }, -+ "node_modules/@babel/plugin-transform-destructuring": { ++ "node_modules/@babel/regjsgen": { ++ "version": "0.8.0", ++ "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", ++ "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", ++ "dev": true ++ }, ++ "node_modules/@babel/runtime": { + "version": "7.24.8", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.8.tgz", -+ "integrity": "sha512-36e87mfY8TnRxc7yc6M9g9gOB7rKgSahqkIKwLpz4Ppk2+zC2Cy1is0uwtuSG6AE4zlTOUa+7JGz9jCJGLqQFQ==", ++ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.8.tgz", ++ "integrity": "sha512-5F7SDGs1T72ZczbRwbGO9lQi0NLjQxzl6i4lJxLxfW9U5UluCSyEJeniWvnhl3/euNiqQVbo8zruhsDfid0esA==", + "dev": true, + "dependencies": { -+ "@babel/helper-plugin-utils": "^7.24.8" ++ "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" -+ }, -+ "peerDependencies": { -+ "@babel/core": "^7.0.0-0" + } + }, -+ "node_modules/@babel/plugin-transform-dotall-regex": { ++ "node_modules/@babel/template": { + "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.7.tgz", -+ "integrity": "sha512-ZOA3W+1RRTSWvyqcMJDLqbchh7U4NRGqwRfFSVbOLS/ePIP4vHB5e8T8eXcuqyN1QkgKyj5wuW0lcS85v4CrSw==", ++ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.7.tgz", ++ "integrity": "sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig==", + "dev": true, + "dependencies": { -+ "@babel/helper-create-regexp-features-plugin": "^7.24.7", -+ "@babel/helper-plugin-utils": "^7.24.7" ++ "@babel/code-frame": "^7.24.7", ++ "@babel/parser": "^7.24.7", ++ "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" ++ } ++ }, ++ "node_modules/@babel/traverse": { ++ "version": "7.24.8", ++ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.8.tgz", ++ "integrity": "sha512-t0P1xxAPzEDcEPmjprAQq19NWum4K0EQPjMwZQZbHt+GiZqvjCHjj755Weq1YRPVzBI+3zSfvScfpnuIecVFJQ==", ++ "dev": true, ++ "dependencies": { ++ "@babel/code-frame": "^7.24.7", ++ "@babel/generator": "^7.24.8", ++ "@babel/helper-environment-visitor": "^7.24.7", ++ "@babel/helper-function-name": "^7.24.7", ++ "@babel/helper-hoist-variables": "^7.24.7", ++ "@babel/helper-split-export-declaration": "^7.24.7", ++ "@babel/parser": "^7.24.8", ++ "@babel/types": "^7.24.8", ++ "debug": "^4.3.1", ++ "globals": "^11.1.0" + }, -+ "peerDependencies": { -+ "@babel/core": "^7.0.0-0" ++ "engines": { ++ "node": ">=6.9.0" + } + }, -+ "node_modules/@babel/plugin-transform-duplicate-keys": { -+ "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.7.tgz", -+ "integrity": "sha512-JdYfXyCRihAe46jUIliuL2/s0x0wObgwwiGxw/UbgJBr20gQBThrokO4nYKgWkD7uBaqM7+9x5TU7NkExZJyzw==", ++ "node_modules/@babel/types": { ++ "version": "7.24.9", ++ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.9.tgz", ++ "integrity": "sha512-xm8XrMKz0IlUdocVbYJe0Z9xEgidU7msskG8BbhnTPK/HZ2z/7FP7ykqPgrUH+C+r414mNfNWam1f2vqOjqjYQ==", + "dev": true, + "dependencies": { -+ "@babel/helper-plugin-utils": "^7.24.7" ++ "@babel/helper-string-parser": "^7.24.8", ++ "@babel/helper-validator-identifier": "^7.24.7", ++ "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" ++ } ++ }, ++ "node_modules/@bcoe/v8-coverage": { ++ "version": "0.2.3", ++ "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", ++ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", ++ "dev": true ++ }, ++ "node_modules/@istanbuljs/load-nyc-config": { ++ "version": "1.1.0", ++ "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", ++ "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", ++ "dev": true, ++ "dependencies": { ++ "camelcase": "^5.3.1", ++ "find-up": "^4.1.0", ++ "get-package-type": "^0.1.0", ++ "js-yaml": "^3.13.1", ++ "resolve-from": "^5.0.0" + }, -+ "peerDependencies": { -+ "@babel/core": "^7.0.0-0" ++ "engines": { ++ "node": ">=8" + } + }, -+ "node_modules/@babel/plugin-transform-dynamic-import": { -+ "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.7.tgz", -+ "integrity": "sha512-sc3X26PhZQDb3JhORmakcbvkeInvxz+A8oda99lj7J60QRuPZvNAk9wQlTBS1ZynelDrDmTU4pw1tyc5d5ZMUg==", ++ "node_modules/@istanbuljs/schema": { ++ "version": "0.1.3", ++ "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", ++ "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", ++ "dev": true, ++ "engines": { ++ "node": ">=8" ++ } ++ }, ++ "node_modules/@jest/console": { ++ "version": "29.7.0", ++ "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", ++ "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "dev": true, + "dependencies": { -+ "@babel/helper-plugin-utils": "^7.24.7", -+ "@babel/plugin-syntax-dynamic-import": "^7.8.3" ++ "@jest/types": "^29.6.3", ++ "@types/node": "*", ++ "chalk": "^4.0.0", ++ "jest-message-util": "^29.7.0", ++ "jest-util": "^29.7.0", ++ "slash": "^3.0.0" + }, + "engines": { -+ "node": ">=6.9.0" ++ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" ++ } ++ }, ++ "node_modules/@jest/console/node_modules/ansi-styles": { ++ "version": "4.3.0", ++ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", ++ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", ++ "dev": true, ++ "dependencies": { ++ "color-convert": "^2.0.1" ++ }, ++ "engines": { ++ "node": ">=8" ++ }, ++ "funding": { ++ "url": "https://github.com/chalk/ansi-styles?sponsor=1" ++ } ++ }, ++ "node_modules/@jest/console/node_modules/chalk": { ++ "version": "4.1.2", ++ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", ++ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", ++ "dev": true, ++ "dependencies": { ++ "ansi-styles": "^4.1.0", ++ "supports-color": "^7.1.0" ++ }, ++ "engines": { ++ "node": ">=10" ++ }, ++ "funding": { ++ "url": "https://github.com/chalk/chalk?sponsor=1" ++ } ++ }, ++ "node_modules/@jest/console/node_modules/color-convert": { ++ "version": "2.0.1", ++ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", ++ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", ++ "dev": true, ++ "dependencies": { ++ "color-name": "~1.1.4" ++ }, ++ "engines": { ++ "node": ">=7.0.0" ++ } ++ }, ++ "node_modules/@jest/console/node_modules/color-name": { ++ "version": "1.1.4", ++ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", ++ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", ++ "dev": true ++ }, ++ "node_modules/@jest/console/node_modules/has-flag": { ++ "version": "4.0.0", ++ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", ++ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", ++ "dev": true, ++ "engines": { ++ "node": ">=8" ++ } ++ }, ++ "node_modules/@jest/console/node_modules/supports-color": { ++ "version": "7.2.0", ++ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", ++ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", ++ "dev": true, ++ "dependencies": { ++ "has-flag": "^4.0.0" ++ }, ++ "engines": { ++ "node": ">=8" ++ } ++ }, ++ "node_modules/@jest/core": { ++ "version": "29.7.0", ++ "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", ++ "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", ++ "dev": true, ++ "dependencies": { ++ "@jest/console": "^29.7.0", ++ "@jest/reporters": "^29.7.0", ++ "@jest/test-result": "^29.7.0", ++ "@jest/transform": "^29.7.0", ++ "@jest/types": "^29.6.3", ++ "@types/node": "*", ++ "ansi-escapes": "^4.2.1", ++ "chalk": "^4.0.0", ++ "ci-info": "^3.2.0", ++ "exit": "^0.1.2", ++ "graceful-fs": "^4.2.9", ++ "jest-changed-files": "^29.7.0", ++ "jest-config": "^29.7.0", ++ "jest-haste-map": "^29.7.0", ++ "jest-message-util": "^29.7.0", ++ "jest-regex-util": "^29.6.3", ++ "jest-resolve": "^29.7.0", ++ "jest-resolve-dependencies": "^29.7.0", ++ "jest-runner": "^29.7.0", ++ "jest-runtime": "^29.7.0", ++ "jest-snapshot": "^29.7.0", ++ "jest-util": "^29.7.0", ++ "jest-validate": "^29.7.0", ++ "jest-watcher": "^29.7.0", ++ "micromatch": "^4.0.4", ++ "pretty-format": "^29.7.0", ++ "slash": "^3.0.0", ++ "strip-ansi": "^6.0.0" ++ }, ++ "engines": { ++ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { -+ "@babel/core": "^7.0.0-0" ++ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" ++ }, ++ "peerDependenciesMeta": { ++ "node-notifier": { ++ "optional": true ++ } + } + }, -+ "node_modules/@babel/plugin-transform-exponentiation-operator": { -+ "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.7.tgz", -+ "integrity": "sha512-Rqe/vSc9OYgDajNIK35u7ot+KeCoetqQYFXM4Epf7M7ez3lWlOjrDjrwMei6caCVhfdw+mIKD4cgdGNy5JQotQ==", ++ "node_modules/@jest/core/node_modules/ansi-styles": { ++ "version": "4.3.0", ++ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", ++ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", ++ "dev": true, ++ "dependencies": { ++ "color-convert": "^2.0.1" ++ }, ++ "engines": { ++ "node": ">=8" ++ }, ++ "funding": { ++ "url": "https://github.com/chalk/ansi-styles?sponsor=1" ++ } ++ }, ++ "node_modules/@jest/core/node_modules/chalk": { ++ "version": "4.1.2", ++ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", ++ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", ++ "dev": true, ++ "dependencies": { ++ "ansi-styles": "^4.1.0", ++ "supports-color": "^7.1.0" ++ }, ++ "engines": { ++ "node": ">=10" ++ }, ++ "funding": { ++ "url": "https://github.com/chalk/chalk?sponsor=1" ++ } ++ }, ++ "node_modules/@jest/core/node_modules/color-convert": { ++ "version": "2.0.1", ++ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", ++ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", ++ "dev": true, ++ "dependencies": { ++ "color-name": "~1.1.4" ++ }, ++ "engines": { ++ "node": ">=7.0.0" ++ } ++ }, ++ "node_modules/@jest/core/node_modules/color-name": { ++ "version": "1.1.4", ++ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", ++ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", ++ "dev": true ++ }, ++ "node_modules/@jest/core/node_modules/has-flag": { ++ "version": "4.0.0", ++ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", ++ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", ++ "dev": true, ++ "engines": { ++ "node": ">=8" ++ } ++ }, ++ "node_modules/@jest/core/node_modules/supports-color": { ++ "version": "7.2.0", ++ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", ++ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { -+ "@babel/helper-builder-binary-assignment-operator-visitor": "^7.24.7", -+ "@babel/helper-plugin-utils": "^7.24.7" ++ "has-flag": "^4.0.0" + }, + "engines": { -+ "node": ">=6.9.0" -+ }, -+ "peerDependencies": { -+ "@babel/core": "^7.0.0-0" ++ "node": ">=8" + } + }, -+ "node_modules/@babel/plugin-transform-export-namespace-from": { -+ "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.7.tgz", -+ "integrity": "sha512-v0K9uNYsPL3oXZ/7F9NNIbAj2jv1whUEtyA6aujhekLs56R++JDQuzRcP2/z4WX5Vg/c5lE9uWZA0/iUoFhLTA==", ++ "node_modules/@jest/environment": { ++ "version": "29.7.0", ++ "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", ++ "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "dev": true, + "dependencies": { -+ "@babel/helper-plugin-utils": "^7.24.7", -+ "@babel/plugin-syntax-export-namespace-from": "^7.8.3" ++ "@jest/fake-timers": "^29.7.0", ++ "@jest/types": "^29.6.3", ++ "@types/node": "*", ++ "jest-mock": "^29.7.0" + }, + "engines": { -+ "node": ">=6.9.0" -+ }, -+ "peerDependencies": { -+ "@babel/core": "^7.0.0-0" ++ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, -+ "node_modules/@babel/plugin-transform-for-of": { -+ "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.7.tgz", -+ "integrity": "sha512-wo9ogrDG1ITTTBsy46oGiN1dS9A7MROBTcYsfS8DtsImMkHk9JXJ3EWQM6X2SUw4x80uGPlwj0o00Uoc6nEE3g==", ++ "node_modules/@jest/expect": { ++ "version": "29.7.0", ++ "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", ++ "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "dev": true, + "dependencies": { -+ "@babel/helper-plugin-utils": "^7.24.7", -+ "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" ++ "expect": "^29.7.0", ++ "jest-snapshot": "^29.7.0" + }, + "engines": { -+ "node": ">=6.9.0" -+ }, -+ "peerDependencies": { -+ "@babel/core": "^7.0.0-0" ++ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, -+ "node_modules/@babel/plugin-transform-function-name": { -+ "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.24.7.tgz", -+ "integrity": "sha512-U9FcnA821YoILngSmYkW6FjyQe2TyZD5pHt4EVIhmcTkrJw/3KqcrRSxuOo5tFZJi7TE19iDyI1u+weTI7bn2w==", ++ "node_modules/@jest/expect-utils": { ++ "version": "29.7.0", ++ "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", ++ "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "dev": true, + "dependencies": { -+ "@babel/helper-compilation-targets": "^7.24.7", -+ "@babel/helper-function-name": "^7.24.7", -+ "@babel/helper-plugin-utils": "^7.24.7" ++ "jest-get-type": "^29.6.3" + }, + "engines": { -+ "node": ">=6.9.0" -+ }, -+ "peerDependencies": { -+ "@babel/core": "^7.0.0-0" ++ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, -+ "node_modules/@babel/plugin-transform-json-strings": { -+ "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.7.tgz", -+ "integrity": "sha512-2yFnBGDvRuxAaE/f0vfBKvtnvvqU8tGpMHqMNpTN2oWMKIR3NqFkjaAgGwawhqK/pIN2T3XdjGPdaG0vDhOBGw==", ++ "node_modules/@jest/fake-timers": { ++ "version": "29.7.0", ++ "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", ++ "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "dev": true, + "dependencies": { -+ "@babel/helper-plugin-utils": "^7.24.7", -+ "@babel/plugin-syntax-json-strings": "^7.8.3" ++ "@jest/types": "^29.6.3", ++ "@sinonjs/fake-timers": "^10.0.2", ++ "@types/node": "*", ++ "jest-message-util": "^29.7.0", ++ "jest-mock": "^29.7.0", ++ "jest-util": "^29.7.0" + }, + "engines": { -+ "node": ">=6.9.0" -+ }, -+ "peerDependencies": { -+ "@babel/core": "^7.0.0-0" ++ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, -+ "node_modules/@babel/plugin-transform-literals": { -+ "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.24.7.tgz", -+ "integrity": "sha512-vcwCbb4HDH+hWi8Pqenwnjy+UiklO4Kt1vfspcQYFhJdpthSnW8XvWGyDZWKNVrVbVViI/S7K9PDJZiUmP2fYQ==", ++ "node_modules/@jest/globals": { ++ "version": "29.7.0", ++ "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", ++ "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "dev": true, + "dependencies": { -+ "@babel/helper-plugin-utils": "^7.24.7" ++ "@jest/environment": "^29.7.0", ++ "@jest/expect": "^29.7.0", ++ "@jest/types": "^29.6.3", ++ "jest-mock": "^29.7.0" + }, + "engines": { -+ "node": ">=6.9.0" -+ }, -+ "peerDependencies": { -+ "@babel/core": "^7.0.0-0" ++ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, -+ "node_modules/@babel/plugin-transform-logical-assignment-operators": { -+ "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.7.tgz", -+ "integrity": "sha512-4D2tpwlQ1odXmTEIFWy9ELJcZHqrStlzK/dAOWYyxX3zT0iXQB6banjgeOJQXzEc4S0E0a5A+hahxPaEFYftsw==", ++ "node_modules/@jest/reporters": { ++ "version": "29.7.0", ++ "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", ++ "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "dev": true, + "dependencies": { -+ "@babel/helper-plugin-utils": "^7.24.7", -+ "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" ++ "@bcoe/v8-coverage": "^0.2.3", ++ "@jest/console": "^29.7.0", ++ "@jest/test-result": "^29.7.0", ++ "@jest/transform": "^29.7.0", ++ "@jest/types": "^29.6.3", ++ "@jridgewell/trace-mapping": "^0.3.18", ++ "@types/node": "*", ++ "chalk": "^4.0.0", ++ "collect-v8-coverage": "^1.0.0", ++ "exit": "^0.1.2", ++ "glob": "^7.1.3", ++ "graceful-fs": "^4.2.9", ++ "istanbul-lib-coverage": "^3.0.0", ++ "istanbul-lib-instrument": "^6.0.0", ++ "istanbul-lib-report": "^3.0.0", ++ "istanbul-lib-source-maps": "^4.0.0", ++ "istanbul-reports": "^3.1.3", ++ "jest-message-util": "^29.7.0", ++ "jest-util": "^29.7.0", ++ "jest-worker": "^29.7.0", ++ "slash": "^3.0.0", ++ "string-length": "^4.0.1", ++ "strip-ansi": "^6.0.0", ++ "v8-to-istanbul": "^9.0.1" + }, + "engines": { -+ "node": ">=6.9.0" ++ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { -+ "@babel/core": "^7.0.0-0" ++ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" ++ }, ++ "peerDependenciesMeta": { ++ "node-notifier": { ++ "optional": true ++ } + } + }, -+ "node_modules/@babel/plugin-transform-member-expression-literals": { -+ "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.7.tgz", -+ "integrity": "sha512-T/hRC1uqrzXMKLQ6UCwMT85S3EvqaBXDGf0FaMf4446Qx9vKwlghvee0+uuZcDUCZU5RuNi4781UQ7R308zzBw==", ++ "node_modules/@jest/reporters/node_modules/ansi-styles": { ++ "version": "4.3.0", ++ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", ++ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { -+ "@babel/helper-plugin-utils": "^7.24.7" ++ "color-convert": "^2.0.1" + }, + "engines": { -+ "node": ">=6.9.0" ++ "node": ">=8" + }, -+ "peerDependencies": { -+ "@babel/core": "^7.0.0-0" ++ "funding": { ++ "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, -+ "node_modules/@babel/plugin-transform-modules-amd": { -+ "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.7.tgz", -+ "integrity": "sha512-9+pB1qxV3vs/8Hdmz/CulFB8w2tuu6EB94JZFsjdqxQokwGa9Unap7Bo2gGBGIvPmDIVvQrom7r5m/TCDMURhg==", ++ "node_modules/@jest/reporters/node_modules/chalk": { ++ "version": "4.1.2", ++ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", ++ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { -+ "@babel/helper-module-transforms": "^7.24.7", -+ "@babel/helper-plugin-utils": "^7.24.7" ++ "ansi-styles": "^4.1.0", ++ "supports-color": "^7.1.0" + }, + "engines": { -+ "node": ">=6.9.0" ++ "node": ">=10" + }, -+ "peerDependencies": { -+ "@babel/core": "^7.0.0-0" ++ "funding": { ++ "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, -+ "node_modules/@babel/plugin-transform-modules-commonjs": { -+ "version": "7.24.8", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.8.tgz", -+ "integrity": "sha512-WHsk9H8XxRs3JXKWFiqtQebdh9b/pTk4EgueygFzYlTKAg0Ud985mSevdNjdXdFBATSKVJGQXP1tv6aGbssLKA==", ++ "node_modules/@jest/reporters/node_modules/color-convert": { ++ "version": "2.0.1", ++ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", ++ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { -+ "@babel/helper-module-transforms": "^7.24.8", -+ "@babel/helper-plugin-utils": "^7.24.8", -+ "@babel/helper-simple-access": "^7.24.7" ++ "color-name": "~1.1.4" + }, + "engines": { -+ "node": ">=6.9.0" -+ }, -+ "peerDependencies": { -+ "@babel/core": "^7.0.0-0" ++ "node": ">=7.0.0" + } + }, -+ "node_modules/@babel/plugin-transform-modules-systemjs": { -+ "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.24.7.tgz", -+ "integrity": "sha512-GYQE0tW7YoaN13qFh3O1NCY4MPkUiAH3fiF7UcV/I3ajmDKEdG3l+UOcbAm4zUE3gnvUU+Eni7XrVKo9eO9auw==", ++ "node_modules/@jest/reporters/node_modules/color-name": { ++ "version": "1.1.4", ++ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", ++ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", ++ "dev": true ++ }, ++ "node_modules/@jest/reporters/node_modules/has-flag": { ++ "version": "4.0.0", ++ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", ++ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, -+ "dependencies": { -+ "@babel/helper-hoist-variables": "^7.24.7", -+ "@babel/helper-module-transforms": "^7.24.7", -+ "@babel/helper-plugin-utils": "^7.24.7", -+ "@babel/helper-validator-identifier": "^7.24.7" -+ }, + "engines": { -+ "node": ">=6.9.0" -+ }, -+ "peerDependencies": { -+ "@babel/core": "^7.0.0-0" ++ "node": ">=8" + } + }, -+ "node_modules/@babel/plugin-transform-modules-umd": { -+ "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.7.tgz", -+ "integrity": "sha512-3aytQvqJ/h9z4g8AsKPLvD4Zqi2qT+L3j7XoFFu1XBlZWEl2/1kWnhmAbxpLgPrHSY0M6UA02jyTiwUVtiKR6A==", ++ "node_modules/@jest/reporters/node_modules/istanbul-lib-instrument": { ++ "version": "6.0.3", ++ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", ++ "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", + "dev": true, + "dependencies": { -+ "@babel/helper-module-transforms": "^7.24.7", -+ "@babel/helper-plugin-utils": "^7.24.7" ++ "@babel/core": "^7.23.9", ++ "@babel/parser": "^7.23.9", ++ "@istanbuljs/schema": "^0.1.3", ++ "istanbul-lib-coverage": "^3.2.0", ++ "semver": "^7.5.4" + }, + "engines": { -+ "node": ">=6.9.0" -+ }, -+ "peerDependencies": { -+ "@babel/core": "^7.0.0-0" ++ "node": ">=10" + } + }, -+ "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { -+ "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.24.7.tgz", -+ "integrity": "sha512-/jr7h/EWeJtk1U/uz2jlsCioHkZk1JJZVcc8oQsJ1dUlaJD83f4/6Zeh2aHt9BIFokHIsSeDfhUmju0+1GPd6g==", ++ "node_modules/@jest/reporters/node_modules/semver": { ++ "version": "7.6.3", ++ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", ++ "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, -+ "dependencies": { -+ "@babel/helper-create-regexp-features-plugin": "^7.24.7", -+ "@babel/helper-plugin-utils": "^7.24.7" ++ "bin": { ++ "semver": "bin/semver.js" + }, + "engines": { -+ "node": ">=6.9.0" -+ }, -+ "peerDependencies": { -+ "@babel/core": "^7.0.0" ++ "node": ">=10" + } + }, -+ "node_modules/@babel/plugin-transform-new-target": { -+ "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.7.tgz", -+ "integrity": "sha512-RNKwfRIXg4Ls/8mMTza5oPF5RkOW8Wy/WgMAp1/F1yZ8mMbtwXW+HDoJiOsagWrAhI5f57Vncrmr9XeT4CVapA==", ++ "node_modules/@jest/reporters/node_modules/supports-color": { ++ "version": "7.2.0", ++ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", ++ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { -+ "@babel/helper-plugin-utils": "^7.24.7" ++ "has-flag": "^4.0.0" + }, + "engines": { -+ "node": ">=6.9.0" -+ }, -+ "peerDependencies": { -+ "@babel/core": "^7.0.0-0" ++ "node": ">=8" + } + }, -+ "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { -+ "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.7.tgz", -+ "integrity": "sha512-Ts7xQVk1OEocqzm8rHMXHlxvsfZ0cEF2yomUqpKENHWMF4zKk175Y4q8H5knJes6PgYad50uuRmt3UJuhBw8pQ==", ++ "node_modules/@jest/schemas": { ++ "version": "29.6.3", ++ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", ++ "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "dependencies": { -+ "@babel/helper-plugin-utils": "^7.24.7", -+ "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" ++ "@sinclair/typebox": "^0.27.8" + }, + "engines": { -+ "node": ">=6.9.0" -+ }, -+ "peerDependencies": { -+ "@babel/core": "^7.0.0-0" ++ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, -+ "node_modules/@babel/plugin-transform-numeric-separator": { -+ "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.7.tgz", -+ "integrity": "sha512-e6q1TiVUzvH9KRvicuxdBTUj4AdKSRwzIyFFnfnezpCfP2/7Qmbb8qbU2j7GODbl4JMkblitCQjKYUaX/qkkwA==", ++ "node_modules/@jest/source-map": { ++ "version": "29.6.3", ++ "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", ++ "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "dev": true, + "dependencies": { -+ "@babel/helper-plugin-utils": "^7.24.7", -+ "@babel/plugin-syntax-numeric-separator": "^7.10.4" ++ "@jridgewell/trace-mapping": "^0.3.18", ++ "callsites": "^3.0.0", ++ "graceful-fs": "^4.2.9" + }, + "engines": { -+ "node": ">=6.9.0" -+ }, -+ "peerDependencies": { -+ "@babel/core": "^7.0.0-0" ++ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, -+ "node_modules/@babel/plugin-transform-object-rest-spread": { -+ "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.7.tgz", -+ "integrity": "sha512-4QrHAr0aXQCEFni2q4DqKLD31n2DL+RxcwnNjDFkSG0eNQ/xCavnRkfCUjsyqGC2OviNJvZOF/mQqZBw7i2C5Q==", ++ "node_modules/@jest/test-result": { ++ "version": "29.7.0", ++ "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", ++ "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "dev": true, + "dependencies": { -+ "@babel/helper-compilation-targets": "^7.24.7", -+ "@babel/helper-plugin-utils": "^7.24.7", -+ "@babel/plugin-syntax-object-rest-spread": "^7.8.3", -+ "@babel/plugin-transform-parameters": "^7.24.7" ++ "@jest/console": "^29.7.0", ++ "@jest/types": "^29.6.3", ++ "@types/istanbul-lib-coverage": "^2.0.0", ++ "collect-v8-coverage": "^1.0.0" + }, + "engines": { -+ "node": ">=6.9.0" -+ }, -+ "peerDependencies": { -+ "@babel/core": "^7.0.0-0" ++ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, -+ "node_modules/@babel/plugin-transform-object-super": { -+ "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.7.tgz", -+ "integrity": "sha512-A/vVLwN6lBrMFmMDmPPz0jnE6ZGx7Jq7d6sT/Ev4H65RER6pZ+kczlf1DthF5N0qaPHBsI7UXiE8Zy66nmAovg==", ++ "node_modules/@jest/test-sequencer": { ++ "version": "29.7.0", ++ "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", ++ "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "dev": true, + "dependencies": { -+ "@babel/helper-plugin-utils": "^7.24.7", -+ "@babel/helper-replace-supers": "^7.24.7" ++ "@jest/test-result": "^29.7.0", ++ "graceful-fs": "^4.2.9", ++ "jest-haste-map": "^29.7.0", ++ "slash": "^3.0.0" + }, + "engines": { -+ "node": ">=6.9.0" -+ }, -+ "peerDependencies": { -+ "@babel/core": "^7.0.0-0" ++ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, -+ "node_modules/@babel/plugin-transform-optional-catch-binding": { -+ "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.7.tgz", -+ "integrity": "sha512-uLEndKqP5BfBbC/5jTwPxLh9kqPWWgzN/f8w6UwAIirAEqiIVJWWY312X72Eub09g5KF9+Zn7+hT7sDxmhRuKA==", ++ "node_modules/@jest/transform": { ++ "version": "29.7.0", ++ "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", ++ "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dev": true, + "dependencies": { -+ "@babel/helper-plugin-utils": "^7.24.7", -+ "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" ++ "@babel/core": "^7.11.6", ++ "@jest/types": "^29.6.3", ++ "@jridgewell/trace-mapping": "^0.3.18", ++ "babel-plugin-istanbul": "^6.1.1", ++ "chalk": "^4.0.0", ++ "convert-source-map": "^2.0.0", ++ "fast-json-stable-stringify": "^2.1.0", ++ "graceful-fs": "^4.2.9", ++ "jest-haste-map": "^29.7.0", ++ "jest-regex-util": "^29.6.3", ++ "jest-util": "^29.7.0", ++ "micromatch": "^4.0.4", ++ "pirates": "^4.0.4", ++ "slash": "^3.0.0", ++ "write-file-atomic": "^4.0.2" + }, + "engines": { -+ "node": ">=6.9.0" -+ }, -+ "peerDependencies": { -+ "@babel/core": "^7.0.0-0" ++ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, -+ "node_modules/@babel/plugin-transform-optional-chaining": { -+ "version": "7.24.8", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.8.tgz", -+ "integrity": "sha512-5cTOLSMs9eypEy8JUVvIKOu6NgvbJMnpG62VpIHrTmROdQ+L5mDAaI40g25k5vXti55JWNX5jCkq3HZxXBQANw==", ++ "node_modules/@jest/transform/node_modules/ansi-styles": { ++ "version": "4.3.0", ++ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", ++ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { -+ "@babel/helper-plugin-utils": "^7.24.8", -+ "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", -+ "@babel/plugin-syntax-optional-chaining": "^7.8.3" ++ "color-convert": "^2.0.1" + }, + "engines": { -+ "node": ">=6.9.0" ++ "node": ">=8" + }, -+ "peerDependencies": { -+ "@babel/core": "^7.0.0-0" ++ "funding": { ++ "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, -+ "node_modules/@babel/plugin-transform-parameters": { -+ "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.7.tgz", -+ "integrity": "sha512-yGWW5Rr+sQOhK0Ot8hjDJuxU3XLRQGflvT4lhlSY0DFvdb3TwKaY26CJzHtYllU0vT9j58hc37ndFPsqT1SrzA==", ++ "node_modules/@jest/transform/node_modules/chalk": { ++ "version": "4.1.2", ++ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", ++ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { -+ "@babel/helper-plugin-utils": "^7.24.7" ++ "ansi-styles": "^4.1.0", ++ "supports-color": "^7.1.0" + }, + "engines": { -+ "node": ">=6.9.0" ++ "node": ">=10" + }, -+ "peerDependencies": { -+ "@babel/core": "^7.0.0-0" ++ "funding": { ++ "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, -+ "node_modules/@babel/plugin-transform-private-methods": { -+ "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.7.tgz", -+ "integrity": "sha512-COTCOkG2hn4JKGEKBADkA8WNb35TGkkRbI5iT845dB+NyqgO8Hn+ajPbSnIQznneJTa3d30scb6iz/DhH8GsJQ==", ++ "node_modules/@jest/transform/node_modules/color-convert": { ++ "version": "2.0.1", ++ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", ++ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { -+ "@babel/helper-create-class-features-plugin": "^7.24.7", -+ "@babel/helper-plugin-utils": "^7.24.7" ++ "color-name": "~1.1.4" + }, + "engines": { -+ "node": ">=6.9.0" -+ }, -+ "peerDependencies": { -+ "@babel/core": "^7.0.0-0" ++ "node": ">=7.0.0" + } + }, -+ "node_modules/@babel/plugin-transform-private-property-in-object": { -+ "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.7.tgz", -+ "integrity": "sha512-9z76mxwnwFxMyxZWEgdgECQglF2Q7cFLm0kMf8pGwt+GSJsY0cONKj/UuO4bOH0w/uAel3ekS4ra5CEAyJRmDA==", ++ "node_modules/@jest/transform/node_modules/color-name": { ++ "version": "1.1.4", ++ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", ++ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", ++ "dev": true ++ }, ++ "node_modules/@jest/transform/node_modules/has-flag": { ++ "version": "4.0.0", ++ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", ++ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, -+ "dependencies": { -+ "@babel/helper-annotate-as-pure": "^7.24.7", -+ "@babel/helper-create-class-features-plugin": "^7.24.7", -+ "@babel/helper-plugin-utils": "^7.24.7", -+ "@babel/plugin-syntax-private-property-in-object": "^7.14.5" -+ }, + "engines": { -+ "node": ">=6.9.0" -+ }, -+ "peerDependencies": { -+ "@babel/core": "^7.0.0-0" ++ "node": ">=8" + } + }, -+ "node_modules/@babel/plugin-transform-property-literals": { -+ "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.7.tgz", -+ "integrity": "sha512-EMi4MLQSHfd2nrCqQEWxFdha2gBCqU4ZcCng4WBGZ5CJL4bBRW0ptdqqDdeirGZcpALazVVNJqRmsO8/+oNCBA==", ++ "node_modules/@jest/transform/node_modules/supports-color": { ++ "version": "7.2.0", ++ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", ++ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { -+ "@babel/helper-plugin-utils": "^7.24.7" ++ "has-flag": "^4.0.0" + }, + "engines": { -+ "node": ">=6.9.0" -+ }, -+ "peerDependencies": { -+ "@babel/core": "^7.0.0-0" ++ "node": ">=8" + } + }, -+ "node_modules/@babel/plugin-transform-regenerator": { -+ "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.7.tgz", -+ "integrity": "sha512-lq3fvXPdimDrlg6LWBoqj+r/DEWgONuwjuOuQCSYgRroXDH/IdM1C0IZf59fL5cHLpjEH/O6opIRBbqv7ELnuA==", ++ "node_modules/@jest/types": { ++ "version": "29.6.3", ++ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", ++ "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "dependencies": { -+ "@babel/helper-plugin-utils": "^7.24.7", -+ "regenerator-transform": "^0.15.2" ++ "@jest/schemas": "^29.6.3", ++ "@types/istanbul-lib-coverage": "^2.0.0", ++ "@types/istanbul-reports": "^3.0.0", ++ "@types/node": "*", ++ "@types/yargs": "^17.0.8", ++ "chalk": "^4.0.0" + }, + "engines": { -+ "node": ">=6.9.0" -+ }, -+ "peerDependencies": { -+ "@babel/core": "^7.0.0-0" ++ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, -+ "node_modules/@babel/plugin-transform-reserved-words": { -+ "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.7.tgz", -+ "integrity": "sha512-0DUq0pHcPKbjFZCfTss/pGkYMfy3vFWydkUBd9r0GHpIyfs2eCDENvqadMycRS9wZCXR41wucAfJHJmwA0UmoQ==", ++ "node_modules/@jest/types/node_modules/ansi-styles": { ++ "version": "4.3.0", ++ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", ++ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { -+ "@babel/helper-plugin-utils": "^7.24.7" ++ "color-convert": "^2.0.1" + }, + "engines": { -+ "node": ">=6.9.0" ++ "node": ">=8" + }, -+ "peerDependencies": { -+ "@babel/core": "^7.0.0-0" ++ "funding": { ++ "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } -+ }, -+ "node_modules/@babel/plugin-transform-shorthand-properties": { -+ "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.7.tgz", -+ "integrity": "sha512-KsDsevZMDsigzbA09+vacnLpmPH4aWjcZjXdyFKGzpplxhbeB4wYtury3vglQkg6KM/xEPKt73eCjPPf1PgXBA==", ++ }, ++ "node_modules/@jest/types/node_modules/chalk": { ++ "version": "4.1.2", ++ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", ++ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { -+ "@babel/helper-plugin-utils": "^7.24.7" ++ "ansi-styles": "^4.1.0", ++ "supports-color": "^7.1.0" + }, + "engines": { -+ "node": ">=6.9.0" ++ "node": ">=10" + }, -+ "peerDependencies": { -+ "@babel/core": "^7.0.0-0" ++ "funding": { ++ "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, -+ "node_modules/@babel/plugin-transform-spread": { -+ "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.7.tgz", -+ "integrity": "sha512-x96oO0I09dgMDxJaANcRyD4ellXFLLiWhuwDxKZX5g2rWP1bTPkBSwCYv96VDXVT1bD9aPj8tppr5ITIh8hBng==", ++ "node_modules/@jest/types/node_modules/color-convert": { ++ "version": "2.0.1", ++ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", ++ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { -+ "@babel/helper-plugin-utils": "^7.24.7", -+ "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" ++ "color-name": "~1.1.4" + }, + "engines": { -+ "node": ">=6.9.0" -+ }, -+ "peerDependencies": { -+ "@babel/core": "^7.0.0-0" ++ "node": ">=7.0.0" + } + }, -+ "node_modules/@babel/plugin-transform-sticky-regex": { -+ "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.7.tgz", -+ "integrity": "sha512-kHPSIJc9v24zEml5geKg9Mjx5ULpfncj0wRpYtxbvKyTtHCYDkVE3aHQ03FrpEo4gEe2vrJJS1Y9CJTaThA52g==", ++ "node_modules/@jest/types/node_modules/color-name": { ++ "version": "1.1.4", ++ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", ++ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", ++ "dev": true ++ }, ++ "node_modules/@jest/types/node_modules/has-flag": { ++ "version": "4.0.0", ++ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", ++ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, -+ "dependencies": { -+ "@babel/helper-plugin-utils": "^7.24.7" -+ }, + "engines": { -+ "node": ">=6.9.0" -+ }, -+ "peerDependencies": { -+ "@babel/core": "^7.0.0-0" ++ "node": ">=8" + } + }, -+ "node_modules/@babel/plugin-transform-template-literals": { -+ "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.7.tgz", -+ "integrity": "sha512-AfDTQmClklHCOLxtGoP7HkeMw56k1/bTQjwsfhL6pppo/M4TOBSq+jjBUBLmV/4oeFg4GWMavIl44ZeCtmmZTw==", ++ "node_modules/@jest/types/node_modules/supports-color": { ++ "version": "7.2.0", ++ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", ++ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { -+ "@babel/helper-plugin-utils": "^7.24.7" ++ "has-flag": "^4.0.0" + }, + "engines": { -+ "node": ">=6.9.0" -+ }, -+ "peerDependencies": { -+ "@babel/core": "^7.0.0-0" ++ "node": ">=8" + } + }, -+ "node_modules/@babel/plugin-transform-typeof-symbol": { -+ "version": "7.24.8", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.8.tgz", -+ "integrity": "sha512-adNTUpDCVnmAE58VEqKlAA6ZBlNkMnWD0ZcW76lyNFN3MJniyGFZfNwERVk8Ap56MCnXztmDr19T4mPTztcuaw==", ++ "node_modules/@jridgewell/gen-mapping": { ++ "version": "0.3.5", ++ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", ++ "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dev": true, + "dependencies": { -+ "@babel/helper-plugin-utils": "^7.24.8" ++ "@jridgewell/set-array": "^1.2.1", ++ "@jridgewell/sourcemap-codec": "^1.4.10", ++ "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { -+ "node": ">=6.9.0" -+ }, -+ "peerDependencies": { -+ "@babel/core": "^7.0.0-0" ++ "node": ">=6.0.0" + } + }, -+ "node_modules/@babel/plugin-transform-unicode-escapes": { -+ "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.7.tgz", -+ "integrity": "sha512-U3ap1gm5+4edc2Q/P+9VrBNhGkfnf+8ZqppY71Bo/pzZmXhhLdqgaUl6cuB07O1+AQJtCLfaOmswiNbSQ9ivhw==", ++ "node_modules/@jridgewell/resolve-uri": { ++ "version": "3.1.2", ++ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", ++ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, -+ "dependencies": { -+ "@babel/helper-plugin-utils": "^7.24.7" -+ }, + "engines": { -+ "node": ">=6.9.0" -+ }, -+ "peerDependencies": { -+ "@babel/core": "^7.0.0-0" ++ "node": ">=6.0.0" + } + }, -+ "node_modules/@babel/plugin-transform-unicode-property-regex": { -+ "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.7.tgz", -+ "integrity": "sha512-uH2O4OV5M9FZYQrwc7NdVmMxQJOCCzFeYudlZSzUAHRFeOujQefa92E74TQDVskNHCzOXoigEuoyzHDhaEaK5w==", ++ "node_modules/@jridgewell/set-array": { ++ "version": "1.2.1", ++ "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", ++ "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "dev": true, -+ "dependencies": { -+ "@babel/helper-create-regexp-features-plugin": "^7.24.7", -+ "@babel/helper-plugin-utils": "^7.24.7" -+ }, + "engines": { -+ "node": ">=6.9.0" -+ }, -+ "peerDependencies": { -+ "@babel/core": "^7.0.0-0" ++ "node": ">=6.0.0" + } + }, -+ "node_modules/@babel/plugin-transform-unicode-regex": { -+ "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.7.tgz", -+ "integrity": "sha512-hlQ96MBZSAXUq7ltkjtu3FJCCSMx/j629ns3hA3pXnBXjanNP0LHi+JpPeA81zaWgVK1VGH95Xuy7u0RyQ8kMg==", ++ "node_modules/@jridgewell/sourcemap-codec": { ++ "version": "1.5.0", ++ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", ++ "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", ++ "dev": true ++ }, ++ "node_modules/@jridgewell/trace-mapping": { ++ "version": "0.3.25", ++ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", ++ "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "dependencies": { -+ "@babel/helper-create-regexp-features-plugin": "^7.24.7", -+ "@babel/helper-plugin-utils": "^7.24.7" ++ "@jridgewell/resolve-uri": "^3.1.0", ++ "@jridgewell/sourcemap-codec": "^1.4.14" ++ } ++ }, ++ "node_modules/@noble/curves": { ++ "version": "1.4.0", ++ "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.0.tgz", ++ "integrity": "sha512-p+4cb332SFCrReJkCYe8Xzm0OWi4Jji5jVdIZRL/PmacmDkFNw6MrrV+gGpiPxLHbV+zKFRywUWbaseT+tZRXg==", ++ "dependencies": { ++ "@noble/hashes": "1.4.0" + }, ++ "funding": { ++ "url": "https://paulmillr.com/funding/" ++ } ++ }, ++ "node_modules/@noble/hashes": { ++ "version": "1.4.0", ++ "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", ++ "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "engines": { -+ "node": ">=6.9.0" ++ "node": ">= 16" + }, -+ "peerDependencies": { -+ "@babel/core": "^7.0.0-0" ++ "funding": { ++ "url": "https://paulmillr.com/funding/" + } + }, -+ "node_modules/@babel/plugin-transform-unicode-sets-regex": { -+ "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.24.7.tgz", -+ "integrity": "sha512-2G8aAvF4wy1w/AGZkemprdGMRg5o6zPNhbHVImRz3lss55TYCBd6xStN19rt8XJHq20sqV0JbyWjOWwQRwV/wg==", -+ "dev": true, ++ "node_modules/@scure/base": { ++ "version": "1.1.7", ++ "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.7.tgz", ++ "integrity": "sha512-PPNYBslrLNNUQ/Yad37MHYsNQtK67EhWb6WtSvNLLPo7SdVZgkUjD6Dg+5On7zNwmskf8OX7I7Nx5oN+MIWE0g==", ++ "funding": { ++ "url": "https://paulmillr.com/funding/" ++ } ++ }, ++ "node_modules/@scure/bip32": { ++ "version": "1.4.0", ++ "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.4.0.tgz", ++ "integrity": "sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg==", + "dependencies": { -+ "@babel/helper-create-regexp-features-plugin": "^7.24.7", -+ "@babel/helper-plugin-utils": "^7.24.7" ++ "@noble/curves": "~1.4.0", ++ "@noble/hashes": "~1.4.0", ++ "@scure/base": "~1.1.6" + }, -+ "engines": { -+ "node": ">=6.9.0" ++ "funding": { ++ "url": "https://paulmillr.com/funding/" ++ } ++ }, ++ "node_modules/@scure/bip39": { ++ "version": "1.3.0", ++ "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.3.0.tgz", ++ "integrity": "sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ==", ++ "dependencies": { ++ "@noble/hashes": "~1.4.0", ++ "@scure/base": "~1.1.6" + }, -+ "peerDependencies": { -+ "@babel/core": "^7.0.0" ++ "funding": { ++ "url": "https://paulmillr.com/funding/" + } + }, -+ "node_modules/@babel/preset-env": { -+ "version": "7.24.8", -+ "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.24.8.tgz", -+ "integrity": "sha512-vObvMZB6hNWuDxhSaEPTKCwcqkAIuDtE+bQGn4XMXne1DSLzFVY8Vmj1bm+mUQXYNN8NmaQEO+r8MMbzPr1jBQ==", ++ "node_modules/@sinclair/typebox": { ++ "version": "0.27.8", ++ "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", ++ "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", ++ "dev": true ++ }, ++ "node_modules/@sinonjs/commons": { ++ "version": "3.0.1", ++ "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", ++ "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "dependencies": { -+ "@babel/compat-data": "^7.24.8", -+ "@babel/helper-compilation-targets": "^7.24.8", -+ "@babel/helper-plugin-utils": "^7.24.8", -+ "@babel/helper-validator-option": "^7.24.8", -+ "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.24.7", -+ "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.24.7", -+ "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.7", -+ "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.24.7", -+ "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", -+ "@babel/plugin-syntax-async-generators": "^7.8.4", -+ "@babel/plugin-syntax-class-properties": "^7.12.13", -+ "@babel/plugin-syntax-class-static-block": "^7.14.5", -+ "@babel/plugin-syntax-dynamic-import": "^7.8.3", -+ "@babel/plugin-syntax-export-namespace-from": "^7.8.3", -+ "@babel/plugin-syntax-import-assertions": "^7.24.7", -+ "@babel/plugin-syntax-import-attributes": "^7.24.7", -+ "@babel/plugin-syntax-import-meta": "^7.10.4", -+ "@babel/plugin-syntax-json-strings": "^7.8.3", -+ "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", -+ "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", -+ "@babel/plugin-syntax-numeric-separator": "^7.10.4", -+ "@babel/plugin-syntax-object-rest-spread": "^7.8.3", -+ "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", -+ "@babel/plugin-syntax-optional-chaining": "^7.8.3", -+ "@babel/plugin-syntax-private-property-in-object": "^7.14.5", -+ "@babel/plugin-syntax-top-level-await": "^7.14.5", -+ "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", -+ "@babel/plugin-transform-arrow-functions": "^7.24.7", -+ "@babel/plugin-transform-async-generator-functions": "^7.24.7", -+ "@babel/plugin-transform-async-to-generator": "^7.24.7", -+ "@babel/plugin-transform-block-scoped-functions": "^7.24.7", -+ "@babel/plugin-transform-block-scoping": "^7.24.7", -+ "@babel/plugin-transform-class-properties": "^7.24.7", -+ "@babel/plugin-transform-class-static-block": "^7.24.7", -+ "@babel/plugin-transform-classes": "^7.24.8", -+ "@babel/plugin-transform-computed-properties": "^7.24.7", -+ "@babel/plugin-transform-destructuring": "^7.24.8", -+ "@babel/plugin-transform-dotall-regex": "^7.24.7", -+ "@babel/plugin-transform-duplicate-keys": "^7.24.7", -+ "@babel/plugin-transform-dynamic-import": "^7.24.7", -+ "@babel/plugin-transform-exponentiation-operator": "^7.24.7", -+ "@babel/plugin-transform-export-namespace-from": "^7.24.7", -+ "@babel/plugin-transform-for-of": "^7.24.7", -+ "@babel/plugin-transform-function-name": "^7.24.7", -+ "@babel/plugin-transform-json-strings": "^7.24.7", -+ "@babel/plugin-transform-literals": "^7.24.7", -+ "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", -+ "@babel/plugin-transform-member-expression-literals": "^7.24.7", -+ "@babel/plugin-transform-modules-amd": "^7.24.7", -+ "@babel/plugin-transform-modules-commonjs": "^7.24.8", -+ "@babel/plugin-transform-modules-systemjs": "^7.24.7", -+ "@babel/plugin-transform-modules-umd": "^7.24.7", -+ "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", -+ "@babel/plugin-transform-new-target": "^7.24.7", -+ "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", -+ "@babel/plugin-transform-numeric-separator": "^7.24.7", -+ "@babel/plugin-transform-object-rest-spread": "^7.24.7", -+ "@babel/plugin-transform-object-super": "^7.24.7", -+ "@babel/plugin-transform-optional-catch-binding": "^7.24.7", -+ "@babel/plugin-transform-optional-chaining": "^7.24.8", -+ "@babel/plugin-transform-parameters": "^7.24.7", -+ "@babel/plugin-transform-private-methods": "^7.24.7", -+ "@babel/plugin-transform-private-property-in-object": "^7.24.7", -+ "@babel/plugin-transform-property-literals": "^7.24.7", -+ "@babel/plugin-transform-regenerator": "^7.24.7", -+ "@babel/plugin-transform-reserved-words": "^7.24.7", -+ "@babel/plugin-transform-shorthand-properties": "^7.24.7", -+ "@babel/plugin-transform-spread": "^7.24.7", -+ "@babel/plugin-transform-sticky-regex": "^7.24.7", -+ "@babel/plugin-transform-template-literals": "^7.24.7", -+ "@babel/plugin-transform-typeof-symbol": "^7.24.8", -+ "@babel/plugin-transform-unicode-escapes": "^7.24.7", -+ "@babel/plugin-transform-unicode-property-regex": "^7.24.7", -+ "@babel/plugin-transform-unicode-regex": "^7.24.7", -+ "@babel/plugin-transform-unicode-sets-regex": "^7.24.7", -+ "@babel/preset-modules": "0.1.6-no-external-plugins", -+ "babel-plugin-polyfill-corejs2": "^0.4.10", -+ "babel-plugin-polyfill-corejs3": "^0.10.4", -+ "babel-plugin-polyfill-regenerator": "^0.6.1", -+ "core-js-compat": "^3.37.1", -+ "semver": "^6.3.1" -+ }, -+ "engines": { -+ "node": ">=6.9.0" -+ }, -+ "peerDependencies": { -+ "@babel/core": "^7.0.0-0" ++ "type-detect": "4.0.8" + } + }, -+ "node_modules/@babel/preset-modules": { -+ "version": "0.1.6-no-external-plugins", -+ "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", -+ "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", ++ "node_modules/@sinonjs/fake-timers": { ++ "version": "10.3.0", ++ "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", ++ "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "dependencies": { -+ "@babel/helper-plugin-utils": "^7.0.0", -+ "@babel/types": "^7.4.4", -+ "esutils": "^2.0.2" -+ }, -+ "peerDependencies": { -+ "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" ++ "@sinonjs/commons": "^3.0.0" + } + }, -+ "node_modules/@babel/regjsgen": { -+ "version": "0.8.0", -+ "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", -+ "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", -+ "dev": true ++ "node_modules/@types/babel__core": { ++ "version": "7.20.5", ++ "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", ++ "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", ++ "dev": true, ++ "dependencies": { ++ "@babel/parser": "^7.20.7", ++ "@babel/types": "^7.20.7", ++ "@types/babel__generator": "*", ++ "@types/babel__template": "*", ++ "@types/babel__traverse": "*" ++ } + }, -+ "node_modules/@babel/runtime": { -+ "version": "7.24.8", -+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.8.tgz", -+ "integrity": "sha512-5F7SDGs1T72ZczbRwbGO9lQi0NLjQxzl6i4lJxLxfW9U5UluCSyEJeniWvnhl3/euNiqQVbo8zruhsDfid0esA==", ++ "node_modules/@types/babel__generator": { ++ "version": "7.6.8", ++ "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", ++ "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dev": true, + "dependencies": { -+ "regenerator-runtime": "^0.14.0" -+ }, -+ "engines": { -+ "node": ">=6.9.0" ++ "@babel/types": "^7.0.0" + } + }, -+ "node_modules/@babel/template": { -+ "version": "7.24.7", -+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.7.tgz", -+ "integrity": "sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig==", ++ "node_modules/@types/babel__template": { ++ "version": "7.4.4", ++ "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", ++ "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "dependencies": { -+ "@babel/code-frame": "^7.24.7", -+ "@babel/parser": "^7.24.7", -+ "@babel/types": "^7.24.7" -+ }, -+ "engines": { -+ "node": ">=6.9.0" ++ "@babel/parser": "^7.1.0", ++ "@babel/types": "^7.0.0" + } + }, -+ "node_modules/@babel/traverse": { -+ "version": "7.24.8", -+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.8.tgz", -+ "integrity": "sha512-t0P1xxAPzEDcEPmjprAQq19NWum4K0EQPjMwZQZbHt+GiZqvjCHjj755Weq1YRPVzBI+3zSfvScfpnuIecVFJQ==", ++ "node_modules/@types/babel__traverse": { ++ "version": "7.20.6", ++ "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", ++ "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", + "dev": true, + "dependencies": { -+ "@babel/code-frame": "^7.24.7", -+ "@babel/generator": "^7.24.8", -+ "@babel/helper-environment-visitor": "^7.24.7", -+ "@babel/helper-function-name": "^7.24.7", -+ "@babel/helper-hoist-variables": "^7.24.7", -+ "@babel/helper-split-export-declaration": "^7.24.7", -+ "@babel/parser": "^7.24.8", -+ "@babel/types": "^7.24.8", -+ "debug": "^4.3.1", -+ "globals": "^11.1.0" -+ }, -+ "engines": { -+ "node": ">=6.9.0" ++ "@babel/types": "^7.20.7" + } + }, -+ "node_modules/@babel/types": { -+ "version": "7.24.9", -+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.9.tgz", -+ "integrity": "sha512-xm8XrMKz0IlUdocVbYJe0Z9xEgidU7msskG8BbhnTPK/HZ2z/7FP7ykqPgrUH+C+r414mNfNWam1f2vqOjqjYQ==", ++ "node_modules/@types/graceful-fs": { ++ "version": "4.1.9", ++ "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", ++ "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "dev": true, + "dependencies": { -+ "@babel/helper-string-parser": "^7.24.8", -+ "@babel/helper-validator-identifier": "^7.24.7", -+ "to-fast-properties": "^2.0.0" -+ }, -+ "engines": { -+ "node": ">=6.9.0" ++ "@types/node": "*" + } + }, -+ "node_modules/@bcoe/v8-coverage": { -+ "version": "0.2.3", -+ "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", -+ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", ++ "node_modules/@types/istanbul-lib-coverage": { ++ "version": "2.0.6", ++ "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", ++ "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true + }, -+ "node_modules/@istanbuljs/load-nyc-config": { -+ "version": "1.1.0", -+ "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", -+ "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", ++ "node_modules/@types/istanbul-lib-report": { ++ "version": "3.0.3", ++ "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", ++ "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dev": true, + "dependencies": { -+ "camelcase": "^5.3.1", -+ "find-up": "^4.1.0", -+ "get-package-type": "^0.1.0", -+ "js-yaml": "^3.13.1", -+ "resolve-from": "^5.0.0" -+ }, -+ "engines": { -+ "node": ">=8" ++ "@types/istanbul-lib-coverage": "*" + } + }, -+ "node_modules/@istanbuljs/schema": { -+ "version": "0.1.3", -+ "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", -+ "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", ++ "node_modules/@types/istanbul-reports": { ++ "version": "3.0.4", ++ "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", ++ "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "dev": true, -+ "engines": { -+ "node": ">=8" ++ "dependencies": { ++ "@types/istanbul-lib-report": "*" + } + }, -+ "node_modules/@jest/console": { -+ "version": "29.7.0", -+ "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", -+ "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", ++ "node_modules/@types/node": { ++ "version": "20.14.11", ++ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.11.tgz", ++ "integrity": "sha512-kprQpL8MMeszbz6ojB5/tU8PLN4kesnN8Gjzw349rDlNgsSzg90lAVj3llK99Dh7JON+t9AuscPPFW6mPbTnSA==", + "dev": true, + "dependencies": { -+ "@jest/types": "^29.6.3", -+ "@types/node": "*", -+ "chalk": "^4.0.0", -+ "jest-message-util": "^29.7.0", -+ "jest-util": "^29.7.0", -+ "slash": "^3.0.0" -+ }, -+ "engines": { -+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" ++ "undici-types": "~5.26.4" + } + }, -+ "node_modules/@jest/console/node_modules/ansi-styles": { -+ "version": "4.3.0", -+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", -+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", ++ "node_modules/@types/stack-utils": { ++ "version": "2.0.3", ++ "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", ++ "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", ++ "dev": true ++ }, ++ "node_modules/@types/yargs": { ++ "version": "17.0.32", ++ "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", ++ "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", + "dev": true, + "dependencies": { -+ "color-convert": "^2.0.1" ++ "@types/yargs-parser": "*" ++ } ++ }, ++ "node_modules/@types/yargs-parser": { ++ "version": "21.0.3", ++ "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", ++ "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", ++ "dev": true ++ }, ++ "node_modules/abitype": { ++ "version": "1.0.5", ++ "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.0.5.tgz", ++ "integrity": "sha512-YzDhti7cjlfaBhHutMaboYB21Ha3rXR9QTkNJFzYC4kC8YclaiwPBBBJY8ejFdu2wnJeZCVZSMlQJ7fi8S6hsw==", ++ "funding": { ++ "url": "https://github.com/sponsors/wevm" + }, -+ "engines": { -+ "node": ">=8" ++ "peerDependencies": { ++ "typescript": ">=5.0.4", ++ "zod": "^3 >=3.22.0" + }, -+ "funding": { -+ "url": "https://github.com/chalk/ansi-styles?sponsor=1" ++ "peerDependenciesMeta": { ++ "typescript": { ++ "optional": true ++ }, ++ "zod": { ++ "optional": true ++ } + } + }, -+ "node_modules/@jest/console/node_modules/chalk": { -+ "version": "4.1.2", -+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", -+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", ++ "node_modules/ansi-escapes": { ++ "version": "4.3.2", ++ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", ++ "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "dependencies": { -+ "ansi-styles": "^4.1.0", -+ "supports-color": "^7.1.0" ++ "type-fest": "^0.21.3" + }, + "engines": { -+ "node": ">=10" ++ "node": ">=8" + }, + "funding": { -+ "url": "https://github.com/chalk/chalk?sponsor=1" ++ "url": "https://github.com/sponsors/sindresorhus" + } + }, -+ "node_modules/@jest/console/node_modules/color-convert": { -+ "version": "2.0.1", -+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", -+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", ++ "node_modules/ansi-regex": { ++ "version": "5.0.1", ++ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", ++ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, -+ "dependencies": { -+ "color-name": "~1.1.4" -+ }, + "engines": { -+ "node": ">=7.0.0" ++ "node": ">=8" + } + }, -+ "node_modules/@jest/console/node_modules/color-name": { -+ "version": "1.1.4", -+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", -+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", -+ "dev": true -+ }, -+ "node_modules/@jest/console/node_modules/has-flag": { -+ "version": "4.0.0", -+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", -+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", ++ "node_modules/ansi-styles": { ++ "version": "3.2.1", ++ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", ++ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, ++ "dependencies": { ++ "color-convert": "^1.9.0" ++ }, + "engines": { -+ "node": ">=8" ++ "node": ">=4" + } + }, -+ "node_modules/@jest/console/node_modules/supports-color": { -+ "version": "7.2.0", -+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", -+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", ++ "node_modules/anymatch": { ++ "version": "3.1.3", ++ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", ++ "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { -+ "has-flag": "^4.0.0" ++ "normalize-path": "^3.0.0", ++ "picomatch": "^2.0.4" + }, + "engines": { -+ "node": ">=8" ++ "node": ">= 8" + } + }, -+ "node_modules/@jest/core": { ++ "node_modules/argparse": { ++ "version": "1.0.10", ++ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", ++ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", ++ "dev": true, ++ "dependencies": { ++ "sprintf-js": "~1.0.2" ++ } ++ }, ++ "node_modules/babel-jest": { + "version": "29.7.0", -+ "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", -+ "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", ++ "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", ++ "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "dev": true, + "dependencies": { -+ "@jest/console": "^29.7.0", -+ "@jest/reporters": "^29.7.0", -+ "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", -+ "@jest/types": "^29.6.3", -+ "@types/node": "*", -+ "ansi-escapes": "^4.2.1", ++ "@types/babel__core": "^7.1.14", ++ "babel-plugin-istanbul": "^6.1.1", ++ "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", -+ "ci-info": "^3.2.0", -+ "exit": "^0.1.2", + "graceful-fs": "^4.2.9", -+ "jest-changed-files": "^29.7.0", -+ "jest-config": "^29.7.0", -+ "jest-haste-map": "^29.7.0", -+ "jest-message-util": "^29.7.0", -+ "jest-regex-util": "^29.6.3", -+ "jest-resolve": "^29.7.0", -+ "jest-resolve-dependencies": "^29.7.0", -+ "jest-runner": "^29.7.0", -+ "jest-runtime": "^29.7.0", -+ "jest-snapshot": "^29.7.0", -+ "jest-util": "^29.7.0", -+ "jest-validate": "^29.7.0", -+ "jest-watcher": "^29.7.0", -+ "micromatch": "^4.0.4", -+ "pretty-format": "^29.7.0", -+ "slash": "^3.0.0", -+ "strip-ansi": "^6.0.0" ++ "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { -+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" -+ }, -+ "peerDependenciesMeta": { -+ "node-notifier": { -+ "optional": true -+ } ++ "@babel/core": "^7.8.0" + } + }, -+ "node_modules/@jest/core/node_modules/ansi-styles": { ++ "node_modules/babel-jest/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", @@ -18671,7 +71268,7 @@ + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, -+ "node_modules/@jest/core/node_modules/chalk": { ++ "node_modules/babel-jest/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", @@ -18687,7 +71284,7 @@ + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, -+ "node_modules/@jest/core/node_modules/color-convert": { ++ "node_modules/babel-jest/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", @@ -18699,13 +71296,13 @@ + "node": ">=7.0.0" + } + }, -+ "node_modules/@jest/core/node_modules/color-name": { ++ "node_modules/babel-jest/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, -+ "node_modules/@jest/core/node_modules/has-flag": { ++ "node_modules/babel-jest/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", @@ -18714,7 +71311,7 @@ + "node": ">=8" + } + }, -+ "node_modules/@jest/core/node_modules/supports-color": { ++ "node_modules/babel-jest/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", @@ -18726,302 +71323,364 @@ + "node": ">=8" + } + }, -+ "node_modules/@jest/environment": { -+ "version": "29.7.0", -+ "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", -+ "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", ++ "node_modules/babel-plugin-istanbul": { ++ "version": "6.1.1", ++ "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", ++ "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "dependencies": { -+ "@jest/fake-timers": "^29.7.0", -+ "@jest/types": "^29.6.3", -+ "@types/node": "*", -+ "jest-mock": "^29.7.0" ++ "@babel/helper-plugin-utils": "^7.0.0", ++ "@istanbuljs/load-nyc-config": "^1.0.0", ++ "@istanbuljs/schema": "^0.1.2", ++ "istanbul-lib-instrument": "^5.0.4", ++ "test-exclude": "^6.0.0" + }, + "engines": { -+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" ++ "node": ">=8" + } + }, -+ "node_modules/@jest/expect": { -+ "version": "29.7.0", -+ "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", -+ "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", ++ "node_modules/babel-plugin-jest-hoist": { ++ "version": "29.6.3", ++ "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", ++ "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "dev": true, + "dependencies": { -+ "expect": "^29.7.0", -+ "jest-snapshot": "^29.7.0" ++ "@babel/template": "^7.3.3", ++ "@babel/types": "^7.3.3", ++ "@types/babel__core": "^7.1.14", ++ "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, -+ "node_modules/@jest/expect-utils": { -+ "version": "29.7.0", -+ "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", -+ "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", ++ "node_modules/babel-plugin-polyfill-corejs2": { ++ "version": "0.4.11", ++ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", ++ "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", + "dev": true, + "dependencies": { -+ "jest-get-type": "^29.6.3" ++ "@babel/compat-data": "^7.22.6", ++ "@babel/helper-define-polyfill-provider": "^0.6.2", ++ "semver": "^6.3.1" + }, -+ "engines": { -+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" ++ "peerDependencies": { ++ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, -+ "node_modules/@jest/fake-timers": { -+ "version": "29.7.0", -+ "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", -+ "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", ++ "node_modules/babel-plugin-polyfill-corejs3": { ++ "version": "0.10.4", ++ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.4.tgz", ++ "integrity": "sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg==", + "dev": true, + "dependencies": { -+ "@jest/types": "^29.6.3", -+ "@sinonjs/fake-timers": "^10.0.2", -+ "@types/node": "*", -+ "jest-message-util": "^29.7.0", -+ "jest-mock": "^29.7.0", -+ "jest-util": "^29.7.0" ++ "@babel/helper-define-polyfill-provider": "^0.6.1", ++ "core-js-compat": "^3.36.1" + }, -+ "engines": { -+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" ++ "peerDependencies": { ++ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, -+ "node_modules/@jest/globals": { -+ "version": "29.7.0", -+ "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", -+ "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", ++ "node_modules/babel-plugin-polyfill-regenerator": { ++ "version": "0.6.2", ++ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", ++ "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", + "dev": true, + "dependencies": { -+ "@jest/environment": "^29.7.0", -+ "@jest/expect": "^29.7.0", -+ "@jest/types": "^29.6.3", -+ "jest-mock": "^29.7.0" ++ "@babel/helper-define-polyfill-provider": "^0.6.2" + }, -+ "engines": { -+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" ++ "peerDependencies": { ++ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, -+ "node_modules/@jest/reporters": { -+ "version": "29.7.0", -+ "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", -+ "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", ++ "node_modules/babel-preset-current-node-syntax": { ++ "version": "1.0.1", ++ "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", ++ "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "dev": true, + "dependencies": { -+ "@bcoe/v8-coverage": "^0.2.3", -+ "@jest/console": "^29.7.0", -+ "@jest/test-result": "^29.7.0", -+ "@jest/transform": "^29.7.0", -+ "@jest/types": "^29.6.3", -+ "@jridgewell/trace-mapping": "^0.3.18", -+ "@types/node": "*", -+ "chalk": "^4.0.0", -+ "collect-v8-coverage": "^1.0.0", -+ "exit": "^0.1.2", -+ "glob": "^7.1.3", -+ "graceful-fs": "^4.2.9", -+ "istanbul-lib-coverage": "^3.0.0", -+ "istanbul-lib-instrument": "^6.0.0", -+ "istanbul-lib-report": "^3.0.0", -+ "istanbul-lib-source-maps": "^4.0.0", -+ "istanbul-reports": "^3.1.3", -+ "jest-message-util": "^29.7.0", -+ "jest-util": "^29.7.0", -+ "jest-worker": "^29.7.0", -+ "slash": "^3.0.0", -+ "string-length": "^4.0.1", -+ "strip-ansi": "^6.0.0", -+ "v8-to-istanbul": "^9.0.1" ++ "@babel/plugin-syntax-async-generators": "^7.8.4", ++ "@babel/plugin-syntax-bigint": "^7.8.3", ++ "@babel/plugin-syntax-class-properties": "^7.8.3", ++ "@babel/plugin-syntax-import-meta": "^7.8.3", ++ "@babel/plugin-syntax-json-strings": "^7.8.3", ++ "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", ++ "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", ++ "@babel/plugin-syntax-numeric-separator": "^7.8.3", ++ "@babel/plugin-syntax-object-rest-spread": "^7.8.3", ++ "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", ++ "@babel/plugin-syntax-optional-chaining": "^7.8.3", ++ "@babel/plugin-syntax-top-level-await": "^7.8.3" ++ }, ++ "peerDependencies": { ++ "@babel/core": "^7.0.0" ++ } ++ }, ++ "node_modules/babel-preset-jest": { ++ "version": "29.6.3", ++ "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", ++ "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", ++ "dev": true, ++ "dependencies": { ++ "babel-plugin-jest-hoist": "^29.6.3", ++ "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { -+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" -+ }, -+ "peerDependenciesMeta": { -+ "node-notifier": { -+ "optional": true -+ } ++ "@babel/core": "^7.0.0" + } + }, -+ "node_modules/@jest/reporters/node_modules/ansi-styles": { -+ "version": "4.3.0", -+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", -+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", ++ "node_modules/balanced-match": { ++ "version": "1.0.2", ++ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", ++ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", ++ "dev": true ++ }, ++ "node_modules/brace-expansion": { ++ "version": "1.1.11", ++ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", ++ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { -+ "color-convert": "^2.0.1" ++ "balanced-match": "^1.0.0", ++ "concat-map": "0.0.1" ++ } ++ }, ++ "node_modules/braces": { ++ "version": "3.0.3", ++ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", ++ "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", ++ "dev": true, ++ "dependencies": { ++ "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" -+ }, -+ "funding": { -+ "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, -+ "node_modules/@jest/reporters/node_modules/chalk": { -+ "version": "4.1.2", -+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", -+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", ++ "node_modules/browserslist": { ++ "version": "4.23.2", ++ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.2.tgz", ++ "integrity": "sha512-qkqSyistMYdxAcw+CzbZwlBy8AGmS/eEWs+sEV5TnLRGDOL+C5M2EnH6tlZyg0YoAxGJAFKh61En9BR941GnHA==", + "dev": true, ++ "funding": [ ++ { ++ "type": "opencollective", ++ "url": "https://opencollective.com/browserslist" ++ }, ++ { ++ "type": "tidelift", ++ "url": "https://tidelift.com/funding/github/npm/browserslist" ++ }, ++ { ++ "type": "github", ++ "url": "https://github.com/sponsors/ai" ++ } ++ ], + "dependencies": { -+ "ansi-styles": "^4.1.0", -+ "supports-color": "^7.1.0" ++ "caniuse-lite": "^1.0.30001640", ++ "electron-to-chromium": "^1.4.820", ++ "node-releases": "^2.0.14", ++ "update-browserslist-db": "^1.1.0" + }, -+ "engines": { -+ "node": ">=10" ++ "bin": { ++ "browserslist": "cli.js" + }, -+ "funding": { -+ "url": "https://github.com/chalk/chalk?sponsor=1" ++ "engines": { ++ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, -+ "node_modules/@jest/reporters/node_modules/color-convert": { -+ "version": "2.0.1", -+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", -+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", ++ "node_modules/bser": { ++ "version": "2.1.1", ++ "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", ++ "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "dependencies": { -+ "color-name": "~1.1.4" -+ }, -+ "engines": { -+ "node": ">=7.0.0" ++ "node-int64": "^0.4.0" + } + }, -+ "node_modules/@jest/reporters/node_modules/color-name": { -+ "version": "1.1.4", -+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", -+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", ++ "node_modules/buffer-from": { ++ "version": "1.1.2", ++ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", ++ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, -+ "node_modules/@jest/reporters/node_modules/has-flag": { -+ "version": "4.0.0", -+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", -+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", ++ "node_modules/callsites": { ++ "version": "3.1.0", ++ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", ++ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { -+ "node": ">=8" ++ "node": ">=6" + } + }, -+ "node_modules/@jest/reporters/node_modules/istanbul-lib-instrument": { -+ "version": "6.0.3", -+ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", -+ "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", ++ "node_modules/camelcase": { ++ "version": "5.3.1", ++ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", ++ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", ++ "dev": true, ++ "engines": { ++ "node": ">=6" ++ } ++ }, ++ "node_modules/caniuse-lite": { ++ "version": "1.0.30001642", ++ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001642.tgz", ++ "integrity": "sha512-3XQ0DoRgLijXJErLSl+bLnJ+Et4KqV1PY6JJBGAFlsNsz31zeAIncyeZfLCabHK/jtSh+671RM9YMldxjUPZtA==", ++ "dev": true, ++ "funding": [ ++ { ++ "type": "opencollective", ++ "url": "https://opencollective.com/browserslist" ++ }, ++ { ++ "type": "tidelift", ++ "url": "https://tidelift.com/funding/github/npm/caniuse-lite" ++ }, ++ { ++ "type": "github", ++ "url": "https://github.com/sponsors/ai" ++ } ++ ] ++ }, ++ "node_modules/chalk": { ++ "version": "2.4.2", ++ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", ++ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { -+ "@babel/core": "^7.23.9", -+ "@babel/parser": "^7.23.9", -+ "@istanbuljs/schema": "^0.1.3", -+ "istanbul-lib-coverage": "^3.2.0", -+ "semver": "^7.5.4" ++ "ansi-styles": "^3.2.1", ++ "escape-string-regexp": "^1.0.5", ++ "supports-color": "^5.3.0" + }, + "engines": { -+ "node": ">=10" ++ "node": ">=4" + } + }, -+ "node_modules/@jest/reporters/node_modules/semver": { -+ "version": "7.6.3", -+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", -+ "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", ++ "node_modules/char-regex": { ++ "version": "1.0.2", ++ "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", ++ "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, -+ "bin": { -+ "semver": "bin/semver.js" -+ }, + "engines": { + "node": ">=10" + } + }, -+ "node_modules/@jest/reporters/node_modules/supports-color": { -+ "version": "7.2.0", -+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", -+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", ++ "node_modules/ci-info": { ++ "version": "3.9.0", ++ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", ++ "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, -+ "dependencies": { -+ "has-flag": "^4.0.0" -+ }, ++ "funding": [ ++ { ++ "type": "github", ++ "url": "https://github.com/sponsors/sibiraj-s" ++ } ++ ], + "engines": { + "node": ">=8" + } + }, -+ "node_modules/@jest/schemas": { -+ "version": "29.6.3", -+ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", -+ "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", ++ "node_modules/cjs-module-lexer": { ++ "version": "1.3.1", ++ "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.3.1.tgz", ++ "integrity": "sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q==", ++ "dev": true ++ }, ++ "node_modules/cliui": { ++ "version": "8.0.1", ++ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", ++ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "dependencies": { -+ "@sinclair/typebox": "^0.27.8" ++ "string-width": "^4.2.0", ++ "strip-ansi": "^6.0.1", ++ "wrap-ansi": "^7.0.0" + }, + "engines": { -+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" ++ "node": ">=12" + } + }, -+ "node_modules/@jest/source-map": { -+ "version": "29.6.3", -+ "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", -+ "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", ++ "node_modules/co": { ++ "version": "4.6.0", ++ "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", ++ "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true, -+ "dependencies": { -+ "@jridgewell/trace-mapping": "^0.3.18", -+ "callsites": "^3.0.0", -+ "graceful-fs": "^4.2.9" -+ }, + "engines": { -+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" ++ "iojs": ">= 1.0.0", ++ "node": ">= 0.12.0" + } + }, -+ "node_modules/@jest/test-result": { -+ "version": "29.7.0", -+ "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", -+ "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", ++ "node_modules/collect-v8-coverage": { ++ "version": "1.0.2", ++ "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", ++ "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", ++ "dev": true ++ }, ++ "node_modules/color-convert": { ++ "version": "1.9.3", ++ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", ++ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { -+ "@jest/console": "^29.7.0", -+ "@jest/types": "^29.6.3", -+ "@types/istanbul-lib-coverage": "^2.0.0", -+ "collect-v8-coverage": "^1.0.0" -+ }, -+ "engines": { -+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" ++ "color-name": "1.1.3" + } + }, -+ "node_modules/@jest/test-sequencer": { -+ "version": "29.7.0", -+ "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", -+ "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", ++ "node_modules/color-name": { ++ "version": "1.1.3", ++ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", ++ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", ++ "dev": true ++ }, ++ "node_modules/concat-map": { ++ "version": "0.0.1", ++ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", ++ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", ++ "dev": true ++ }, ++ "node_modules/convert-source-map": { ++ "version": "2.0.0", ++ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", ++ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", ++ "dev": true ++ }, ++ "node_modules/core-js-compat": { ++ "version": "3.37.1", ++ "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.37.1.tgz", ++ "integrity": "sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg==", + "dev": true, + "dependencies": { -+ "@jest/test-result": "^29.7.0", -+ "graceful-fs": "^4.2.9", -+ "jest-haste-map": "^29.7.0", -+ "slash": "^3.0.0" ++ "browserslist": "^4.23.0" + }, -+ "engines": { -+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" ++ "funding": { ++ "type": "opencollective", ++ "url": "https://opencollective.com/core-js" + } + }, -+ "node_modules/@jest/transform": { ++ "node_modules/create-jest": { + "version": "29.7.0", -+ "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", -+ "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", ++ "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", ++ "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dev": true, + "dependencies": { -+ "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", -+ "@jridgewell/trace-mapping": "^0.3.18", -+ "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", -+ "convert-source-map": "^2.0.0", -+ "fast-json-stable-stringify": "^2.1.0", ++ "exit": "^0.1.2", + "graceful-fs": "^4.2.9", -+ "jest-haste-map": "^29.7.0", -+ "jest-regex-util": "^29.6.3", ++ "jest-config": "^29.7.0", + "jest-util": "^29.7.0", -+ "micromatch": "^4.0.4", -+ "pirates": "^4.0.4", -+ "slash": "^3.0.0", -+ "write-file-atomic": "^4.0.2" ++ "prompts": "^2.0.1" ++ }, ++ "bin": { ++ "create-jest": "bin/create-jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, -+ "node_modules/@jest/transform/node_modules/ansi-styles": { ++ "node_modules/create-jest/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", @@ -19036,7 +71695,7 @@ + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, -+ "node_modules/@jest/transform/node_modules/chalk": { ++ "node_modules/create-jest/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", @@ -19052,7 +71711,7 @@ + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, -+ "node_modules/@jest/transform/node_modules/color-convert": { ++ "node_modules/create-jest/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", @@ -19064,13 +71723,13 @@ + "node": ">=7.0.0" + } + }, -+ "node_modules/@jest/transform/node_modules/color-name": { ++ "node_modules/create-jest/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, -+ "node_modules/@jest/transform/node_modules/has-flag": { ++ "node_modules/create-jest/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", @@ -19079,7 +71738,7 @@ + "node": ">=8" + } + }, -+ "node_modules/@jest/transform/node_modules/supports-color": { ++ "node_modules/create-jest/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", @@ -19091,354 +71750,390 @@ + "node": ">=8" + } + }, -+ "node_modules/@jest/types": { -+ "version": "29.6.3", -+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", -+ "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", ++ "node_modules/cross-spawn": { ++ "version": "7.0.3", ++ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", ++ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { -+ "@jest/schemas": "^29.6.3", -+ "@types/istanbul-lib-coverage": "^2.0.0", -+ "@types/istanbul-reports": "^3.0.0", -+ "@types/node": "*", -+ "@types/yargs": "^17.0.8", -+ "chalk": "^4.0.0" ++ "path-key": "^3.1.0", ++ "shebang-command": "^2.0.0", ++ "which": "^2.0.1" + }, + "engines": { -+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" ++ "node": ">= 8" + } + }, -+ "node_modules/@jest/types/node_modules/ansi-styles": { -+ "version": "4.3.0", -+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", -+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", ++ "node_modules/debug": { ++ "version": "4.3.5", ++ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", ++ "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dev": true, + "dependencies": { -+ "color-convert": "^2.0.1" ++ "ms": "2.1.2" + }, + "engines": { -+ "node": ">=8" ++ "node": ">=6.0" + }, -+ "funding": { -+ "url": "https://github.com/chalk/ansi-styles?sponsor=1" ++ "peerDependenciesMeta": { ++ "supports-color": { ++ "optional": true ++ } + } + }, -+ "node_modules/@jest/types/node_modules/chalk": { -+ "version": "4.1.2", -+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", -+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", ++ "node_modules/dedent": { ++ "version": "1.5.3", ++ "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", ++ "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", + "dev": true, -+ "dependencies": { -+ "ansi-styles": "^4.1.0", -+ "supports-color": "^7.1.0" -+ }, -+ "engines": { -+ "node": ">=10" ++ "peerDependencies": { ++ "babel-plugin-macros": "^3.1.0" + }, -+ "funding": { -+ "url": "https://github.com/chalk/chalk?sponsor=1" ++ "peerDependenciesMeta": { ++ "babel-plugin-macros": { ++ "optional": true ++ } + } + }, -+ "node_modules/@jest/types/node_modules/color-convert": { -+ "version": "2.0.1", -+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", -+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", ++ "node_modules/deepmerge": { ++ "version": "4.3.1", ++ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", ++ "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, -+ "dependencies": { -+ "color-name": "~1.1.4" -+ }, + "engines": { -+ "node": ">=7.0.0" ++ "node": ">=0.10.0" + } + }, -+ "node_modules/@jest/types/node_modules/color-name": { -+ "version": "1.1.4", -+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", -+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", -+ "dev": true -+ }, -+ "node_modules/@jest/types/node_modules/has-flag": { -+ "version": "4.0.0", -+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", -+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", ++ "node_modules/detect-newline": { ++ "version": "3.1.0", ++ "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", ++ "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, -+ "node_modules/@jest/types/node_modules/supports-color": { -+ "version": "7.2.0", -+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", -+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", ++ "node_modules/diff-sequences": { ++ "version": "29.6.3", ++ "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", ++ "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, -+ "dependencies": { -+ "has-flag": "^4.0.0" -+ }, + "engines": { -+ "node": ">=8" ++ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, -+ "node_modules/@jridgewell/gen-mapping": { -+ "version": "0.3.5", -+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", -+ "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", ++ "node_modules/electron-to-chromium": { ++ "version": "1.4.829", ++ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.829.tgz", ++ "integrity": "sha512-5qp1N2POAfW0u1qGAxXEtz6P7bO1m6gpZr5hdf5ve6lxpLM7MpiM4jIPz7xcrNlClQMafbyUDDWjlIQZ1Mw0Rw==", ++ "dev": true ++ }, ++ "node_modules/emittery": { ++ "version": "0.13.1", ++ "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", ++ "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true, -+ "dependencies": { -+ "@jridgewell/set-array": "^1.2.1", -+ "@jridgewell/sourcemap-codec": "^1.4.10", -+ "@jridgewell/trace-mapping": "^0.3.24" -+ }, + "engines": { -+ "node": ">=6.0.0" ++ "node": ">=12" ++ }, ++ "funding": { ++ "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, -+ "node_modules/@jridgewell/resolve-uri": { ++ "node_modules/emoji-regex": { ++ "version": "8.0.0", ++ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", ++ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", ++ "dev": true ++ }, ++ "node_modules/error-ex": { ++ "version": "1.3.2", ++ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", ++ "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", ++ "dev": true, ++ "dependencies": { ++ "is-arrayish": "^0.2.1" ++ } ++ }, ++ "node_modules/escalade": { + "version": "3.1.2", -+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", -+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", ++ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", ++ "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "dev": true, + "engines": { -+ "node": ">=6.0.0" ++ "node": ">=6" + } + }, -+ "node_modules/@jridgewell/set-array": { -+ "version": "1.2.1", -+ "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", -+ "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", ++ "node_modules/escape-string-regexp": { ++ "version": "1.0.5", ++ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", ++ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { -+ "node": ">=6.0.0" ++ "node": ">=0.8.0" + } + }, -+ "node_modules/@jridgewell/sourcemap-codec": { -+ "version": "1.5.0", -+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", -+ "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", -+ "dev": true ++ "node_modules/esprima": { ++ "version": "4.0.1", ++ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", ++ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", ++ "dev": true, ++ "bin": { ++ "esparse": "bin/esparse.js", ++ "esvalidate": "bin/esvalidate.js" ++ }, ++ "engines": { ++ "node": ">=4" ++ } + }, -+ "node_modules/@jridgewell/trace-mapping": { -+ "version": "0.3.25", -+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", -+ "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", ++ "node_modules/esutils": { ++ "version": "2.0.3", ++ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", ++ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, -+ "dependencies": { -+ "@jridgewell/resolve-uri": "^3.1.0", -+ "@jridgewell/sourcemap-codec": "^1.4.14" ++ "engines": { ++ "node": ">=0.10.0" + } + }, -+ "node_modules/@noble/curves": { -+ "version": "1.6.0", -+ "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.6.0.tgz", -+ "integrity": "sha512-TlaHRXDehJuRNR9TfZDNQ45mMEd5dwUwmicsafcIX4SsNiqnCHKjE/1alYPd/lDRVhxdhUAlv8uEhMCI5zjIJQ==", ++ "node_modules/execa": { ++ "version": "5.1.1", ++ "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", ++ "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", ++ "dev": true, + "dependencies": { -+ "@noble/hashes": "1.5.0" ++ "cross-spawn": "^7.0.3", ++ "get-stream": "^6.0.0", ++ "human-signals": "^2.1.0", ++ "is-stream": "^2.0.0", ++ "merge-stream": "^2.0.0", ++ "npm-run-path": "^4.0.1", ++ "onetime": "^5.1.2", ++ "signal-exit": "^3.0.3", ++ "strip-final-newline": "^2.0.0" + }, + "engines": { -+ "node": "^14.21.3 || >=16" ++ "node": ">=10" + }, + "funding": { -+ "url": "https://paulmillr.com/funding/" ++ "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, -+ "node_modules/@noble/hashes": { -+ "version": "1.5.0", -+ "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.5.0.tgz", -+ "integrity": "sha512-1j6kQFb7QRru7eKN3ZDvRcP13rugwdxZqCjbiAVZfIJwgj2A65UmT4TgARXGlXgnRkORLTDTrO19ZErt7+QXgA==", ++ "node_modules/exit": { ++ "version": "0.1.2", ++ "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", ++ "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", ++ "dev": true, + "engines": { -+ "node": "^14.21.3 || >=16" -+ }, -+ "funding": { -+ "url": "https://paulmillr.com/funding/" -+ } -+ }, -+ "node_modules/@scure/base": { -+ "version": "1.1.9", -+ "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.9.tgz", -+ "integrity": "sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==", -+ "funding": { -+ "url": "https://paulmillr.com/funding/" -+ } -+ }, -+ "node_modules/@scure/bip32": { -+ "version": "1.5.0", -+ "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.5.0.tgz", -+ "integrity": "sha512-8EnFYkqEQdnkuGBVpCzKxyIwDCBLDVj3oiX0EKUFre/tOjL/Hqba1D6n/8RcmaQy4f95qQFrO2A8Sr6ybh4NRw==", -+ "dependencies": { -+ "@noble/curves": "~1.6.0", -+ "@noble/hashes": "~1.5.0", -+ "@scure/base": "~1.1.7" -+ }, -+ "funding": { -+ "url": "https://paulmillr.com/funding/" ++ "node": ">= 0.8.0" + } + }, -+ "node_modules/@scure/bip39": { -+ "version": "1.4.0", -+ "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.4.0.tgz", -+ "integrity": "sha512-BEEm6p8IueV/ZTfQLp/0vhw4NPnT9oWf5+28nvmeUICjP99f4vr2d+qc7AVGDDtwRep6ifR43Yed9ERVmiITzw==", ++ "node_modules/expect": { ++ "version": "29.7.0", ++ "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", ++ "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", ++ "dev": true, + "dependencies": { -+ "@noble/hashes": "~1.5.0", -+ "@scure/base": "~1.1.8" ++ "@jest/expect-utils": "^29.7.0", ++ "jest-get-type": "^29.6.3", ++ "jest-matcher-utils": "^29.7.0", ++ "jest-message-util": "^29.7.0", ++ "jest-util": "^29.7.0" + }, -+ "funding": { -+ "url": "https://paulmillr.com/funding/" ++ "engines": { ++ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, -+ "node_modules/@sinclair/typebox": { -+ "version": "0.27.8", -+ "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", -+ "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", ++ "node_modules/fast-json-stable-stringify": { ++ "version": "2.1.0", ++ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", ++ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, -+ "node_modules/@sinonjs/commons": { -+ "version": "3.0.1", -+ "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", -+ "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", ++ "node_modules/fb-watchman": { ++ "version": "2.0.2", ++ "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", ++ "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "dependencies": { -+ "type-detect": "4.0.8" ++ "bser": "2.1.1" + } + }, -+ "node_modules/@sinonjs/fake-timers": { -+ "version": "10.3.0", -+ "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", -+ "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", ++ "node_modules/fill-range": { ++ "version": "7.1.1", ++ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", ++ "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "dependencies": { -+ "@sinonjs/commons": "^3.0.0" ++ "to-regex-range": "^5.0.1" ++ }, ++ "engines": { ++ "node": ">=8" + } + }, -+ "node_modules/@types/babel__core": { -+ "version": "7.20.5", -+ "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", -+ "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", ++ "node_modules/find-up": { ++ "version": "4.1.0", ++ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", ++ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { -+ "@babel/parser": "^7.20.7", -+ "@babel/types": "^7.20.7", -+ "@types/babel__generator": "*", -+ "@types/babel__template": "*", -+ "@types/babel__traverse": "*" ++ "locate-path": "^5.0.0", ++ "path-exists": "^4.0.0" ++ }, ++ "engines": { ++ "node": ">=8" + } + }, -+ "node_modules/@types/babel__generator": { -+ "version": "7.6.8", -+ "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", -+ "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", ++ "node_modules/fs.realpath": { ++ "version": "1.0.0", ++ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", ++ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", ++ "dev": true ++ }, ++ "node_modules/fsevents": { ++ "version": "2.3.3", ++ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", ++ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, -+ "dependencies": { -+ "@babel/types": "^7.0.0" ++ "hasInstallScript": true, ++ "optional": true, ++ "os": [ ++ "darwin" ++ ], ++ "engines": { ++ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, -+ "node_modules/@types/babel__template": { -+ "version": "7.4.4", -+ "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", -+ "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", ++ "node_modules/function-bind": { ++ "version": "1.1.2", ++ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", ++ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, -+ "dependencies": { -+ "@babel/parser": "^7.1.0", -+ "@babel/types": "^7.0.0" ++ "funding": { ++ "url": "https://github.com/sponsors/ljharb" + } + }, -+ "node_modules/@types/babel__traverse": { -+ "version": "7.20.6", -+ "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", -+ "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", ++ "node_modules/gensync": { ++ "version": "1.0.0-beta.2", ++ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", ++ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, -+ "dependencies": { -+ "@babel/types": "^7.20.7" ++ "engines": { ++ "node": ">=6.9.0" + } + }, -+ "node_modules/@types/graceful-fs": { -+ "version": "4.1.9", -+ "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", -+ "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", ++ "node_modules/get-caller-file": { ++ "version": "2.0.5", ++ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", ++ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, -+ "dependencies": { -+ "@types/node": "*" ++ "engines": { ++ "node": "6.* || 8.* || >= 10.*" + } + }, -+ "node_modules/@types/istanbul-lib-coverage": { -+ "version": "2.0.6", -+ "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", -+ "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", -+ "dev": true ++ "node_modules/get-package-type": { ++ "version": "0.1.0", ++ "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", ++ "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", ++ "dev": true, ++ "engines": { ++ "node": ">=8.0.0" ++ } + }, -+ "node_modules/@types/istanbul-lib-report": { -+ "version": "3.0.3", -+ "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", -+ "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", ++ "node_modules/get-stream": { ++ "version": "6.0.1", ++ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", ++ "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, -+ "dependencies": { -+ "@types/istanbul-lib-coverage": "*" ++ "engines": { ++ "node": ">=10" ++ }, ++ "funding": { ++ "url": "https://github.com/sponsors/sindresorhus" + } + }, -+ "node_modules/@types/istanbul-reports": { -+ "version": "3.0.4", -+ "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", -+ "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", ++ "node_modules/glob": { ++ "version": "7.2.3", ++ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", ++ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", ++ "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "dependencies": { -+ "@types/istanbul-lib-report": "*" ++ "fs.realpath": "^1.0.0", ++ "inflight": "^1.0.4", ++ "inherits": "2", ++ "minimatch": "^3.1.1", ++ "once": "^1.3.0", ++ "path-is-absolute": "^1.0.0" ++ }, ++ "engines": { ++ "node": "*" ++ }, ++ "funding": { ++ "url": "https://github.com/sponsors/isaacs" + } + }, -+ "node_modules/@types/node": { -+ "version": "20.14.11", -+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.11.tgz", -+ "integrity": "sha512-kprQpL8MMeszbz6ojB5/tU8PLN4kesnN8Gjzw349rDlNgsSzg90lAVj3llK99Dh7JON+t9AuscPPFW6mPbTnSA==", ++ "node_modules/globals": { ++ "version": "11.12.0", ++ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", ++ "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, -+ "dependencies": { -+ "undici-types": "~5.26.4" ++ "engines": { ++ "node": ">=4" + } + }, -+ "node_modules/@types/stack-utils": { -+ "version": "2.0.3", -+ "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", -+ "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", ++ "node_modules/graceful-fs": { ++ "version": "4.2.11", ++ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", ++ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, -+ "node_modules/@types/yargs": { -+ "version": "17.0.32", -+ "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", -+ "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", ++ "node_modules/has-flag": { ++ "version": "3.0.0", ++ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", ++ "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", ++ "dev": true, ++ "engines": { ++ "node": ">=4" ++ } ++ }, ++ "node_modules/hasown": { ++ "version": "2.0.2", ++ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", ++ "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "dependencies": { -+ "@types/yargs-parser": "*" ++ "function-bind": "^1.1.2" ++ }, ++ "engines": { ++ "node": ">= 0.4" + } + }, -+ "node_modules/@types/yargs-parser": { -+ "version": "21.0.3", -+ "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", -+ "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", ++ "node_modules/html-escaper": { ++ "version": "2.0.2", ++ "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", ++ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, -+ "node_modules/abitype": { -+ "version": "1.0.6", -+ "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.0.6.tgz", -+ "integrity": "sha512-MMSqYh4+C/aVqI2RQaWqbvI4Kxo5cQV40WQ4QFtDnNzCkqChm8MuENhElmynZlO0qUy/ObkEUaXtKqYnx1Kp3A==", -+ "funding": { -+ "url": "https://github.com/sponsors/wevm" -+ }, -+ "peerDependencies": { -+ "typescript": ">=5.0.4", -+ "zod": "^3 >=3.22.0" -+ }, -+ "peerDependenciesMeta": { -+ "typescript": { -+ "optional": true -+ }, -+ "zod": { -+ "optional": true -+ } ++ "node_modules/human-signals": { ++ "version": "2.1.0", ++ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", ++ "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", ++ "dev": true, ++ "engines": { ++ "node": ">=10.17.0" + } + }, -+ "node_modules/ansi-escapes": { -+ "version": "4.3.2", -+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", -+ "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", ++ "node_modules/import-local": { ++ "version": "3.1.0", ++ "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", ++ "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "dev": true, + "dependencies": { -+ "type-fest": "^0.21.3" ++ "pkg-dir": "^4.2.0", ++ "resolve-cwd": "^3.0.0" ++ }, ++ "bin": { ++ "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" @@ -19447,120 +72142,152 @@ + "url": "https://github.com/sponsors/sindresorhus" + } + }, -+ "node_modules/ansi-regex": { -+ "version": "5.0.1", -+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", -+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", ++ "node_modules/imurmurhash": { ++ "version": "0.1.4", ++ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", ++ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { -+ "node": ">=8" ++ "node": ">=0.8.19" + } + }, -+ "node_modules/ansi-styles": { -+ "version": "3.2.1", -+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", -+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", ++ "node_modules/inflight": { ++ "version": "1.0.6", ++ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", ++ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", ++ "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "dependencies": { -+ "color-convert": "^1.9.0" -+ }, -+ "engines": { -+ "node": ">=4" ++ "once": "^1.3.0", ++ "wrappy": "1" + } + }, -+ "node_modules/anymatch": { -+ "version": "3.1.3", -+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", -+ "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", ++ "node_modules/inherits": { ++ "version": "2.0.4", ++ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", ++ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", ++ "dev": true ++ }, ++ "node_modules/is-arrayish": { ++ "version": "0.2.1", ++ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", ++ "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", ++ "dev": true ++ }, ++ "node_modules/is-core-module": { ++ "version": "2.14.0", ++ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.14.0.tgz", ++ "integrity": "sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A==", + "dev": true, + "dependencies": { -+ "normalize-path": "^3.0.0", -+ "picomatch": "^2.0.4" ++ "hasown": "^2.0.2" + }, + "engines": { -+ "node": ">= 8" ++ "node": ">= 0.4" ++ }, ++ "funding": { ++ "url": "https://github.com/sponsors/ljharb" + } + }, -+ "node_modules/argparse": { -+ "version": "1.0.10", -+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", -+ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", ++ "node_modules/is-fullwidth-code-point": { ++ "version": "3.0.0", ++ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", ++ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, -+ "dependencies": { -+ "sprintf-js": "~1.0.2" ++ "engines": { ++ "node": ">=8" + } + }, -+ "node_modules/babel-jest": { -+ "version": "29.7.0", -+ "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", -+ "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", ++ "node_modules/is-generator-fn": { ++ "version": "2.1.0", ++ "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", ++ "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, -+ "dependencies": { -+ "@jest/transform": "^29.7.0", -+ "@types/babel__core": "^7.1.14", -+ "babel-plugin-istanbul": "^6.1.1", -+ "babel-preset-jest": "^29.6.3", -+ "chalk": "^4.0.0", -+ "graceful-fs": "^4.2.9", -+ "slash": "^3.0.0" -+ }, + "engines": { -+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" -+ }, -+ "peerDependencies": { -+ "@babel/core": "^7.8.0" ++ "node": ">=6" + } + }, -+ "node_modules/babel-jest/node_modules/ansi-styles": { -+ "version": "4.3.0", -+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", -+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", ++ "node_modules/is-number": { ++ "version": "7.0.0", ++ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", ++ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", ++ "dev": true, ++ "engines": { ++ "node": ">=0.12.0" ++ } ++ }, ++ "node_modules/is-stream": { ++ "version": "2.0.1", ++ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", ++ "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, -+ "dependencies": { -+ "color-convert": "^2.0.1" -+ }, + "engines": { + "node": ">=8" + }, + "funding": { -+ "url": "https://github.com/chalk/ansi-styles?sponsor=1" ++ "url": "https://github.com/sponsors/sindresorhus" + } + }, -+ "node_modules/babel-jest/node_modules/chalk": { -+ "version": "4.1.2", -+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", -+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", ++ "node_modules/isexe": { ++ "version": "2.0.0", ++ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", ++ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", ++ "dev": true ++ }, ++ "node_modules/isows": { ++ "version": "1.0.4", ++ "resolved": "https://registry.npmjs.org/isows/-/isows-1.0.4.tgz", ++ "integrity": "sha512-hEzjY+x9u9hPmBom9IIAqdJCwNLax+xrPb51vEPpERoFlIxgmZcHzsT5jKG06nvInKOBGvReAVz80Umed5CczQ==", ++ "funding": [ ++ { ++ "type": "github", ++ "url": "https://github.com/sponsors/wagmi-dev" ++ } ++ ], ++ "peerDependencies": { ++ "ws": "*" ++ } ++ }, ++ "node_modules/istanbul-lib-coverage": { ++ "version": "3.2.2", ++ "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", ++ "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", ++ "dev": true, ++ "engines": { ++ "node": ">=8" ++ } ++ }, ++ "node_modules/istanbul-lib-instrument": { ++ "version": "5.2.1", ++ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", ++ "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "dependencies": { -+ "ansi-styles": "^4.1.0", -+ "supports-color": "^7.1.0" ++ "@babel/core": "^7.12.3", ++ "@babel/parser": "^7.14.7", ++ "@istanbuljs/schema": "^0.1.2", ++ "istanbul-lib-coverage": "^3.2.0", ++ "semver": "^6.3.0" + }, + "engines": { -+ "node": ">=10" -+ }, -+ "funding": { -+ "url": "https://github.com/chalk/chalk?sponsor=1" ++ "node": ">=8" + } + }, -+ "node_modules/babel-jest/node_modules/color-convert": { -+ "version": "2.0.1", -+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", -+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", ++ "node_modules/istanbul-lib-report": { ++ "version": "3.0.1", ++ "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", ++ "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "dependencies": { -+ "color-name": "~1.1.4" ++ "istanbul-lib-coverage": "^3.0.0", ++ "make-dir": "^4.0.0", ++ "supports-color": "^7.1.0" + }, + "engines": { -+ "node": ">=7.0.0" ++ "node": ">=10" + } + }, -+ "node_modules/babel-jest/node_modules/color-name": { -+ "version": "1.1.4", -+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", -+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", -+ "dev": true -+ }, -+ "node_modules/babel-jest/node_modules/has-flag": { ++ "node_modules/istanbul-lib-report/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", @@ -19569,7 +72296,7 @@ + "node": ">=8" + } + }, -+ "node_modules/babel-jest/node_modules/supports-color": { ++ "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", @@ -19581,364 +72308,208 @@ + "node": ">=8" + } + }, -+ "node_modules/babel-plugin-istanbul": { -+ "version": "6.1.1", -+ "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", -+ "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", ++ "node_modules/istanbul-lib-source-maps": { ++ "version": "4.0.1", ++ "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", ++ "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "dependencies": { -+ "@babel/helper-plugin-utils": "^7.0.0", -+ "@istanbuljs/load-nyc-config": "^1.0.0", -+ "@istanbuljs/schema": "^0.1.2", -+ "istanbul-lib-instrument": "^5.0.4", -+ "test-exclude": "^6.0.0" ++ "debug": "^4.1.1", ++ "istanbul-lib-coverage": "^3.0.0", ++ "source-map": "^0.6.1" + }, + "engines": { -+ "node": ">=8" ++ "node": ">=10" + } + }, -+ "node_modules/babel-plugin-jest-hoist": { -+ "version": "29.6.3", -+ "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", -+ "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", ++ "node_modules/istanbul-reports": { ++ "version": "3.1.7", ++ "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", ++ "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", + "dev": true, + "dependencies": { -+ "@babel/template": "^7.3.3", -+ "@babel/types": "^7.3.3", -+ "@types/babel__core": "^7.1.14", -+ "@types/babel__traverse": "^7.0.6" ++ "html-escaper": "^2.0.0", ++ "istanbul-lib-report": "^3.0.0" + }, + "engines": { -+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" ++ "node": ">=8" + } + }, -+ "node_modules/babel-plugin-polyfill-corejs2": { -+ "version": "0.4.11", -+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", -+ "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", ++ "node_modules/jest": { ++ "version": "29.7.0", ++ "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", ++ "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "dev": true, + "dependencies": { -+ "@babel/compat-data": "^7.22.6", -+ "@babel/helper-define-polyfill-provider": "^0.6.2", -+ "semver": "^6.3.1" ++ "@jest/core": "^29.7.0", ++ "@jest/types": "^29.6.3", ++ "import-local": "^3.0.2", ++ "jest-cli": "^29.7.0" + }, -+ "peerDependencies": { -+ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" -+ } -+ }, -+ "node_modules/babel-plugin-polyfill-corejs3": { -+ "version": "0.10.4", -+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.4.tgz", -+ "integrity": "sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg==", -+ "dev": true, -+ "dependencies": { -+ "@babel/helper-define-polyfill-provider": "^0.6.1", -+ "core-js-compat": "^3.36.1" ++ "bin": { ++ "jest": "bin/jest.js" + }, -+ "peerDependencies": { -+ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" -+ } -+ }, -+ "node_modules/babel-plugin-polyfill-regenerator": { -+ "version": "0.6.2", -+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", -+ "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", -+ "dev": true, -+ "dependencies": { -+ "@babel/helper-define-polyfill-provider": "^0.6.2" ++ "engines": { ++ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { -+ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" -+ } -+ }, -+ "node_modules/babel-preset-current-node-syntax": { -+ "version": "1.0.1", -+ "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", -+ "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", -+ "dev": true, -+ "dependencies": { -+ "@babel/plugin-syntax-async-generators": "^7.8.4", -+ "@babel/plugin-syntax-bigint": "^7.8.3", -+ "@babel/plugin-syntax-class-properties": "^7.8.3", -+ "@babel/plugin-syntax-import-meta": "^7.8.3", -+ "@babel/plugin-syntax-json-strings": "^7.8.3", -+ "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", -+ "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", -+ "@babel/plugin-syntax-numeric-separator": "^7.8.3", -+ "@babel/plugin-syntax-object-rest-spread": "^7.8.3", -+ "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", -+ "@babel/plugin-syntax-optional-chaining": "^7.8.3", -+ "@babel/plugin-syntax-top-level-await": "^7.8.3" ++ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, -+ "peerDependencies": { -+ "@babel/core": "^7.0.0" ++ "peerDependenciesMeta": { ++ "node-notifier": { ++ "optional": true ++ } + } + }, -+ "node_modules/babel-preset-jest": { -+ "version": "29.6.3", -+ "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", -+ "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", ++ "node_modules/jest-changed-files": { ++ "version": "29.7.0", ++ "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", ++ "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", + "dev": true, + "dependencies": { -+ "babel-plugin-jest-hoist": "^29.6.3", -+ "babel-preset-current-node-syntax": "^1.0.0" ++ "execa": "^5.0.0", ++ "jest-util": "^29.7.0", ++ "p-limit": "^3.1.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" -+ }, -+ "peerDependencies": { -+ "@babel/core": "^7.0.0" -+ } -+ }, -+ "node_modules/balanced-match": { -+ "version": "1.0.2", -+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", -+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", -+ "dev": true -+ }, -+ "node_modules/brace-expansion": { -+ "version": "1.1.11", -+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", -+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", -+ "dev": true, -+ "dependencies": { -+ "balanced-match": "^1.0.0", -+ "concat-map": "0.0.1" + } + }, -+ "node_modules/braces": { -+ "version": "3.0.3", -+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", -+ "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", ++ "node_modules/jest-circus": { ++ "version": "29.7.0", ++ "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", ++ "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "dev": true, + "dependencies": { -+ "fill-range": "^7.1.1" ++ "@jest/environment": "^29.7.0", ++ "@jest/expect": "^29.7.0", ++ "@jest/test-result": "^29.7.0", ++ "@jest/types": "^29.6.3", ++ "@types/node": "*", ++ "chalk": "^4.0.0", ++ "co": "^4.6.0", ++ "dedent": "^1.0.0", ++ "is-generator-fn": "^2.0.0", ++ "jest-each": "^29.7.0", ++ "jest-matcher-utils": "^29.7.0", ++ "jest-message-util": "^29.7.0", ++ "jest-runtime": "^29.7.0", ++ "jest-snapshot": "^29.7.0", ++ "jest-util": "^29.7.0", ++ "p-limit": "^3.1.0", ++ "pretty-format": "^29.7.0", ++ "pure-rand": "^6.0.0", ++ "slash": "^3.0.0", ++ "stack-utils": "^2.0.3" + }, + "engines": { -+ "node": ">=8" ++ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, -+ "node_modules/browserslist": { -+ "version": "4.23.2", -+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.2.tgz", -+ "integrity": "sha512-qkqSyistMYdxAcw+CzbZwlBy8AGmS/eEWs+sEV5TnLRGDOL+C5M2EnH6tlZyg0YoAxGJAFKh61En9BR941GnHA==", ++ "node_modules/jest-circus/node_modules/ansi-styles": { ++ "version": "4.3.0", ++ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", ++ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, -+ "funding": [ -+ { -+ "type": "opencollective", -+ "url": "https://opencollective.com/browserslist" -+ }, -+ { -+ "type": "tidelift", -+ "url": "https://tidelift.com/funding/github/npm/browserslist" -+ }, -+ { -+ "type": "github", -+ "url": "https://github.com/sponsors/ai" -+ } -+ ], + "dependencies": { -+ "caniuse-lite": "^1.0.30001640", -+ "electron-to-chromium": "^1.4.820", -+ "node-releases": "^2.0.14", -+ "update-browserslist-db": "^1.1.0" -+ }, -+ "bin": { -+ "browserslist": "cli.js" ++ "color-convert": "^2.0.1" + }, + "engines": { -+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" -+ } -+ }, -+ "node_modules/bser": { -+ "version": "2.1.1", -+ "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", -+ "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", -+ "dev": true, -+ "dependencies": { -+ "node-int64": "^0.4.0" -+ } -+ }, -+ "node_modules/buffer-from": { -+ "version": "1.1.2", -+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", -+ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", -+ "dev": true -+ }, -+ "node_modules/callsites": { -+ "version": "3.1.0", -+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", -+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", -+ "dev": true, -+ "engines": { -+ "node": ">=6" -+ } -+ }, -+ "node_modules/camelcase": { -+ "version": "5.3.1", -+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", -+ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", -+ "dev": true, -+ "engines": { -+ "node": ">=6" ++ "node": ">=8" ++ }, ++ "funding": { ++ "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, -+ "node_modules/caniuse-lite": { -+ "version": "1.0.30001642", -+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001642.tgz", -+ "integrity": "sha512-3XQ0DoRgLijXJErLSl+bLnJ+Et4KqV1PY6JJBGAFlsNsz31zeAIncyeZfLCabHK/jtSh+671RM9YMldxjUPZtA==", -+ "dev": true, -+ "funding": [ -+ { -+ "type": "opencollective", -+ "url": "https://opencollective.com/browserslist" -+ }, -+ { -+ "type": "tidelift", -+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite" -+ }, -+ { -+ "type": "github", -+ "url": "https://github.com/sponsors/ai" -+ } -+ ] -+ }, -+ "node_modules/chalk": { -+ "version": "2.4.2", -+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", -+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", ++ "node_modules/jest-circus/node_modules/chalk": { ++ "version": "4.1.2", ++ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", ++ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { -+ "ansi-styles": "^3.2.1", -+ "escape-string-regexp": "^1.0.5", -+ "supports-color": "^5.3.0" ++ "ansi-styles": "^4.1.0", ++ "supports-color": "^7.1.0" + }, + "engines": { -+ "node": ">=4" -+ } -+ }, -+ "node_modules/char-regex": { -+ "version": "1.0.2", -+ "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", -+ "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", -+ "dev": true, -+ "engines": { + "node": ">=10" -+ } -+ }, -+ "node_modules/ci-info": { -+ "version": "3.9.0", -+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", -+ "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", -+ "dev": true, -+ "funding": [ -+ { -+ "type": "github", -+ "url": "https://github.com/sponsors/sibiraj-s" -+ } -+ ], -+ "engines": { -+ "node": ">=8" -+ } -+ }, -+ "node_modules/cjs-module-lexer": { -+ "version": "1.3.1", -+ "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.3.1.tgz", -+ "integrity": "sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q==", -+ "dev": true -+ }, -+ "node_modules/cliui": { -+ "version": "8.0.1", -+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", -+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", -+ "dev": true, -+ "dependencies": { -+ "string-width": "^4.2.0", -+ "strip-ansi": "^6.0.1", -+ "wrap-ansi": "^7.0.0" + }, -+ "engines": { -+ "node": ">=12" -+ } -+ }, -+ "node_modules/co": { -+ "version": "4.6.0", -+ "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", -+ "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", -+ "dev": true, -+ "engines": { -+ "iojs": ">= 1.0.0", -+ "node": ">= 0.12.0" ++ "funding": { ++ "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, -+ "node_modules/collect-v8-coverage": { -+ "version": "1.0.2", -+ "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", -+ "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", -+ "dev": true -+ }, -+ "node_modules/color-convert": { -+ "version": "1.9.3", -+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", -+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", ++ "node_modules/jest-circus/node_modules/color-convert": { ++ "version": "2.0.1", ++ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", ++ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { -+ "color-name": "1.1.3" ++ "color-name": "~1.1.4" ++ }, ++ "engines": { ++ "node": ">=7.0.0" + } + }, -+ "node_modules/color-name": { -+ "version": "1.1.3", -+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", -+ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", -+ "dev": true -+ }, -+ "node_modules/concat-map": { -+ "version": "0.0.1", -+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", -+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", ++ "node_modules/jest-circus/node_modules/color-name": { ++ "version": "1.1.4", ++ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", ++ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, -+ "node_modules/convert-source-map": { -+ "version": "2.0.0", -+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", -+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", -+ "dev": true ++ "node_modules/jest-circus/node_modules/has-flag": { ++ "version": "4.0.0", ++ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", ++ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", ++ "dev": true, ++ "engines": { ++ "node": ">=8" ++ } + }, -+ "node_modules/core-js-compat": { -+ "version": "3.37.1", -+ "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.37.1.tgz", -+ "integrity": "sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg==", ++ "node_modules/jest-circus/node_modules/supports-color": { ++ "version": "7.2.0", ++ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", ++ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { -+ "browserslist": "^4.23.0" ++ "has-flag": "^4.0.0" + }, -+ "funding": { -+ "type": "opencollective", -+ "url": "https://opencollective.com/core-js" ++ "engines": { ++ "node": ">=8" + } + }, -+ "node_modules/create-jest": { ++ "node_modules/jest-cli": { + "version": "29.7.0", -+ "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", -+ "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", ++ "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", ++ "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "dev": true, + "dependencies": { ++ "@jest/core": "^29.7.0", ++ "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", ++ "create-jest": "^29.7.0", + "exit": "^0.1.2", -+ "graceful-fs": "^4.2.9", ++ "import-local": "^3.0.2", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", -+ "prompts": "^2.0.1" ++ "jest-validate": "^29.7.0", ++ "yargs": "^17.3.1" + }, + "bin": { -+ "create-jest": "bin/create-jest.js" ++ "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" ++ }, ++ "peerDependencies": { ++ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" ++ }, ++ "peerDependenciesMeta": { ++ "node-notifier": { ++ "optional": true ++ } + } + }, -+ "node_modules/create-jest/node_modules/ansi-styles": { ++ "node_modules/jest-cli/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", @@ -19953,7 +72524,7 @@ + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, -+ "node_modules/create-jest/node_modules/chalk": { ++ "node_modules/jest-cli/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", @@ -19969,7 +72540,7 @@ + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, -+ "node_modules/create-jest/node_modules/color-convert": { ++ "node_modules/jest-cli/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", @@ -19981,13 +72552,13 @@ + "node": ">=7.0.0" + } + }, -+ "node_modules/create-jest/node_modules/color-name": { ++ "node_modules/jest-cli/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, -+ "node_modules/create-jest/node_modules/has-flag": { ++ "node_modules/jest-cli/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", @@ -19996,7 +72567,7 @@ + "node": ">=8" + } + }, -+ "node_modules/create-jest/node_modules/supports-color": { ++ "node_modules/jest-cli/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", @@ -20008,544 +72579,666 @@ + "node": ">=8" + } + }, -+ "node_modules/cross-spawn": { -+ "version": "7.0.3", -+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", -+ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", ++ "node_modules/jest-config": { ++ "version": "29.7.0", ++ "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", ++ "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "dev": true, + "dependencies": { -+ "path-key": "^3.1.0", -+ "shebang-command": "^2.0.0", -+ "which": "^2.0.1" ++ "@babel/core": "^7.11.6", ++ "@jest/test-sequencer": "^29.7.0", ++ "@jest/types": "^29.6.3", ++ "babel-jest": "^29.7.0", ++ "chalk": "^4.0.0", ++ "ci-info": "^3.2.0", ++ "deepmerge": "^4.2.2", ++ "glob": "^7.1.3", ++ "graceful-fs": "^4.2.9", ++ "jest-circus": "^29.7.0", ++ "jest-environment-node": "^29.7.0", ++ "jest-get-type": "^29.6.3", ++ "jest-regex-util": "^29.6.3", ++ "jest-resolve": "^29.7.0", ++ "jest-runner": "^29.7.0", ++ "jest-util": "^29.7.0", ++ "jest-validate": "^29.7.0", ++ "micromatch": "^4.0.4", ++ "parse-json": "^5.2.0", ++ "pretty-format": "^29.7.0", ++ "slash": "^3.0.0", ++ "strip-json-comments": "^3.1.1" + }, + "engines": { -+ "node": ">= 8" ++ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" ++ }, ++ "peerDependencies": { ++ "@types/node": "*", ++ "ts-node": ">=9.0.0" ++ }, ++ "peerDependenciesMeta": { ++ "@types/node": { ++ "optional": true ++ }, ++ "ts-node": { ++ "optional": true ++ } + } + }, -+ "node_modules/debug": { -+ "version": "4.3.5", -+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", -+ "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", ++ "node_modules/jest-config/node_modules/ansi-styles": { ++ "version": "4.3.0", ++ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", ++ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { -+ "ms": "2.1.2" ++ "color-convert": "^2.0.1" + }, + "engines": { -+ "node": ">=6.0" ++ "node": ">=8" + }, -+ "peerDependenciesMeta": { -+ "supports-color": { -+ "optional": true -+ } ++ "funding": { ++ "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, -+ "node_modules/dedent": { -+ "version": "1.5.3", -+ "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", -+ "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", ++ "node_modules/jest-config/node_modules/chalk": { ++ "version": "4.1.2", ++ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", ++ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, -+ "peerDependencies": { -+ "babel-plugin-macros": "^3.1.0" ++ "dependencies": { ++ "ansi-styles": "^4.1.0", ++ "supports-color": "^7.1.0" + }, -+ "peerDependenciesMeta": { -+ "babel-plugin-macros": { -+ "optional": true -+ } ++ "engines": { ++ "node": ">=10" ++ }, ++ "funding": { ++ "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, -+ "node_modules/deepmerge": { -+ "version": "4.3.1", -+ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", -+ "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", ++ "node_modules/jest-config/node_modules/color-convert": { ++ "version": "2.0.1", ++ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", ++ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, ++ "dependencies": { ++ "color-name": "~1.1.4" ++ }, + "engines": { -+ "node": ">=0.10.0" ++ "node": ">=7.0.0" + } + }, -+ "node_modules/detect-newline": { -+ "version": "3.1.0", -+ "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", -+ "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", ++ "node_modules/jest-config/node_modules/color-name": { ++ "version": "1.1.4", ++ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", ++ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", ++ "dev": true ++ }, ++ "node_modules/jest-config/node_modules/has-flag": { ++ "version": "4.0.0", ++ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", ++ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, -+ "node_modules/diff-sequences": { -+ "version": "29.6.3", -+ "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", -+ "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", ++ "node_modules/jest-config/node_modules/supports-color": { ++ "version": "7.2.0", ++ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", ++ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, ++ "dependencies": { ++ "has-flag": "^4.0.0" ++ }, + "engines": { -+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" ++ "node": ">=8" + } + }, -+ "node_modules/electron-to-chromium": { -+ "version": "1.4.829", -+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.829.tgz", -+ "integrity": "sha512-5qp1N2POAfW0u1qGAxXEtz6P7bO1m6gpZr5hdf5ve6lxpLM7MpiM4jIPz7xcrNlClQMafbyUDDWjlIQZ1Mw0Rw==", -+ "dev": true ++ "node_modules/jest-diff": { ++ "version": "29.7.0", ++ "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", ++ "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", ++ "dev": true, ++ "dependencies": { ++ "chalk": "^4.0.0", ++ "diff-sequences": "^29.6.3", ++ "jest-get-type": "^29.6.3", ++ "pretty-format": "^29.7.0" ++ }, ++ "engines": { ++ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" ++ } + }, -+ "node_modules/emittery": { -+ "version": "0.13.1", -+ "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", -+ "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", ++ "node_modules/jest-diff/node_modules/ansi-styles": { ++ "version": "4.3.0", ++ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", ++ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, ++ "dependencies": { ++ "color-convert": "^2.0.1" ++ }, + "engines": { -+ "node": ">=12" ++ "node": ">=8" + }, + "funding": { -+ "url": "https://github.com/sindresorhus/emittery?sponsor=1" ++ "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, -+ "node_modules/emoji-regex": { -+ "version": "8.0.0", -+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", -+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", -+ "dev": true ++ "node_modules/jest-diff/node_modules/chalk": { ++ "version": "4.1.2", ++ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", ++ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", ++ "dev": true, ++ "dependencies": { ++ "ansi-styles": "^4.1.0", ++ "supports-color": "^7.1.0" ++ }, ++ "engines": { ++ "node": ">=10" ++ }, ++ "funding": { ++ "url": "https://github.com/chalk/chalk?sponsor=1" ++ } + }, -+ "node_modules/error-ex": { -+ "version": "1.3.2", -+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", -+ "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", ++ "node_modules/jest-diff/node_modules/color-convert": { ++ "version": "2.0.1", ++ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", ++ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { -+ "is-arrayish": "^0.2.1" ++ "color-name": "~1.1.4" ++ }, ++ "engines": { ++ "node": ">=7.0.0" + } + }, -+ "node_modules/escalade": { -+ "version": "3.1.2", -+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", -+ "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", ++ "node_modules/jest-diff/node_modules/color-name": { ++ "version": "1.1.4", ++ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", ++ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", ++ "dev": true ++ }, ++ "node_modules/jest-diff/node_modules/has-flag": { ++ "version": "4.0.0", ++ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", ++ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { -+ "node": ">=6" ++ "node": ">=8" + } + }, -+ "node_modules/escape-string-regexp": { -+ "version": "1.0.5", -+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", -+ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", ++ "node_modules/jest-diff/node_modules/supports-color": { ++ "version": "7.2.0", ++ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", ++ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, ++ "dependencies": { ++ "has-flag": "^4.0.0" ++ }, + "engines": { -+ "node": ">=0.8.0" ++ "node": ">=8" + } + }, -+ "node_modules/esprima": { -+ "version": "4.0.1", -+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", -+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", ++ "node_modules/jest-docblock": { ++ "version": "29.7.0", ++ "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", ++ "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", + "dev": true, -+ "bin": { -+ "esparse": "bin/esparse.js", -+ "esvalidate": "bin/esvalidate.js" ++ "dependencies": { ++ "detect-newline": "^3.0.0" + }, + "engines": { -+ "node": ">=4" ++ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, -+ "node_modules/esutils": { -+ "version": "2.0.3", -+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", -+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", ++ "node_modules/jest-each": { ++ "version": "29.7.0", ++ "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", ++ "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", + "dev": true, ++ "dependencies": { ++ "@jest/types": "^29.6.3", ++ "chalk": "^4.0.0", ++ "jest-get-type": "^29.6.3", ++ "jest-util": "^29.7.0", ++ "pretty-format": "^29.7.0" ++ }, + "engines": { -+ "node": ">=0.10.0" ++ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, -+ "node_modules/execa": { -+ "version": "5.1.1", -+ "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", -+ "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", ++ "node_modules/jest-each/node_modules/ansi-styles": { ++ "version": "4.3.0", ++ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", ++ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { -+ "cross-spawn": "^7.0.3", -+ "get-stream": "^6.0.0", -+ "human-signals": "^2.1.0", -+ "is-stream": "^2.0.0", -+ "merge-stream": "^2.0.0", -+ "npm-run-path": "^4.0.1", -+ "onetime": "^5.1.2", -+ "signal-exit": "^3.0.3", -+ "strip-final-newline": "^2.0.0" ++ "color-convert": "^2.0.1" + }, + "engines": { -+ "node": ">=10" ++ "node": ">=8" + }, + "funding": { -+ "url": "https://github.com/sindresorhus/execa?sponsor=1" ++ "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, -+ "node_modules/exit": { -+ "version": "0.1.2", -+ "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", -+ "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", ++ "node_modules/jest-each/node_modules/chalk": { ++ "version": "4.1.2", ++ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", ++ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, ++ "dependencies": { ++ "ansi-styles": "^4.1.0", ++ "supports-color": "^7.1.0" ++ }, + "engines": { -+ "node": ">= 0.8.0" ++ "node": ">=10" ++ }, ++ "funding": { ++ "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, -+ "node_modules/expect": { -+ "version": "29.7.0", -+ "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", -+ "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", ++ "node_modules/jest-each/node_modules/color-convert": { ++ "version": "2.0.1", ++ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", ++ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { -+ "@jest/expect-utils": "^29.7.0", -+ "jest-get-type": "^29.6.3", -+ "jest-matcher-utils": "^29.7.0", -+ "jest-message-util": "^29.7.0", -+ "jest-util": "^29.7.0" ++ "color-name": "~1.1.4" + }, + "engines": { -+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" ++ "node": ">=7.0.0" + } + }, -+ "node_modules/fast-json-stable-stringify": { -+ "version": "2.1.0", -+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", -+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", ++ "node_modules/jest-each/node_modules/color-name": { ++ "version": "1.1.4", ++ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", ++ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, -+ "node_modules/fb-watchman": { -+ "version": "2.0.2", -+ "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", -+ "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", ++ "node_modules/jest-each/node_modules/has-flag": { ++ "version": "4.0.0", ++ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", ++ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, -+ "dependencies": { -+ "bser": "2.1.1" ++ "engines": { ++ "node": ">=8" + } + }, -+ "node_modules/fill-range": { -+ "version": "7.1.1", -+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", -+ "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", ++ "node_modules/jest-each/node_modules/supports-color": { ++ "version": "7.2.0", ++ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", ++ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { -+ "to-regex-range": "^5.0.1" ++ "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, -+ "node_modules/find-up": { -+ "version": "4.1.0", -+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", -+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", ++ "node_modules/jest-environment-node": { ++ "version": "29.7.0", ++ "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", ++ "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "dev": true, + "dependencies": { -+ "locate-path": "^5.0.0", -+ "path-exists": "^4.0.0" ++ "@jest/environment": "^29.7.0", ++ "@jest/fake-timers": "^29.7.0", ++ "@jest/types": "^29.6.3", ++ "@types/node": "*", ++ "jest-mock": "^29.7.0", ++ "jest-util": "^29.7.0" + }, + "engines": { -+ "node": ">=8" ++ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, -+ "node_modules/fs.realpath": { -+ "version": "1.0.0", -+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", -+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", -+ "dev": true -+ }, -+ "node_modules/fsevents": { -+ "version": "2.3.3", -+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", -+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", ++ "node_modules/jest-get-type": { ++ "version": "29.6.3", ++ "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", ++ "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "dev": true, -+ "hasInstallScript": true, -+ "optional": true, -+ "os": [ -+ "darwin" -+ ], + "engines": { -+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" -+ } -+ }, -+ "node_modules/function-bind": { -+ "version": "1.1.2", -+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", -+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", -+ "dev": true, -+ "funding": { -+ "url": "https://github.com/sponsors/ljharb" ++ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, -+ "node_modules/gensync": { -+ "version": "1.0.0-beta.2", -+ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", -+ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", ++ "node_modules/jest-haste-map": { ++ "version": "29.7.0", ++ "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", ++ "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "dev": true, ++ "dependencies": { ++ "@jest/types": "^29.6.3", ++ "@types/graceful-fs": "^4.1.3", ++ "@types/node": "*", ++ "anymatch": "^3.0.3", ++ "fb-watchman": "^2.0.0", ++ "graceful-fs": "^4.2.9", ++ "jest-regex-util": "^29.6.3", ++ "jest-util": "^29.7.0", ++ "jest-worker": "^29.7.0", ++ "micromatch": "^4.0.4", ++ "walker": "^1.0.8" ++ }, + "engines": { -+ "node": ">=6.9.0" ++ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" ++ }, ++ "optionalDependencies": { ++ "fsevents": "^2.3.2" + } + }, -+ "node_modules/get-caller-file": { -+ "version": "2.0.5", -+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", -+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", ++ "node_modules/jest-leak-detector": { ++ "version": "29.7.0", ++ "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", ++ "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", + "dev": true, ++ "dependencies": { ++ "jest-get-type": "^29.6.3", ++ "pretty-format": "^29.7.0" ++ }, + "engines": { -+ "node": "6.* || 8.* || >= 10.*" ++ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, -+ "node_modules/get-package-type": { -+ "version": "0.1.0", -+ "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", -+ "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", ++ "node_modules/jest-matcher-utils": { ++ "version": "29.7.0", ++ "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", ++ "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "dev": true, ++ "dependencies": { ++ "chalk": "^4.0.0", ++ "jest-diff": "^29.7.0", ++ "jest-get-type": "^29.6.3", ++ "pretty-format": "^29.7.0" ++ }, + "engines": { -+ "node": ">=8.0.0" ++ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, -+ "node_modules/get-stream": { -+ "version": "6.0.1", -+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", -+ "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", ++ "node_modules/jest-matcher-utils/node_modules/ansi-styles": { ++ "version": "4.3.0", ++ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", ++ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, ++ "dependencies": { ++ "color-convert": "^2.0.1" ++ }, + "engines": { -+ "node": ">=10" ++ "node": ">=8" + }, + "funding": { -+ "url": "https://github.com/sponsors/sindresorhus" ++ "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, -+ "node_modules/glob": { -+ "version": "7.2.3", -+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", -+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", -+ "deprecated": "Glob versions prior to v9 are no longer supported", ++ "node_modules/jest-matcher-utils/node_modules/chalk": { ++ "version": "4.1.2", ++ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", ++ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { -+ "fs.realpath": "^1.0.0", -+ "inflight": "^1.0.4", -+ "inherits": "2", -+ "minimatch": "^3.1.1", -+ "once": "^1.3.0", -+ "path-is-absolute": "^1.0.0" ++ "ansi-styles": "^4.1.0", ++ "supports-color": "^7.1.0" + }, + "engines": { -+ "node": "*" ++ "node": ">=10" + }, + "funding": { -+ "url": "https://github.com/sponsors/isaacs" ++ "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, -+ "node_modules/globals": { -+ "version": "11.12.0", -+ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", -+ "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", ++ "node_modules/jest-matcher-utils/node_modules/color-convert": { ++ "version": "2.0.1", ++ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", ++ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, ++ "dependencies": { ++ "color-name": "~1.1.4" ++ }, + "engines": { -+ "node": ">=4" ++ "node": ">=7.0.0" + } + }, -+ "node_modules/graceful-fs": { -+ "version": "4.2.11", -+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", -+ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", ++ "node_modules/jest-matcher-utils/node_modules/color-name": { ++ "version": "1.1.4", ++ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", ++ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, -+ "node_modules/has-flag": { -+ "version": "3.0.0", -+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", -+ "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", ++ "node_modules/jest-matcher-utils/node_modules/has-flag": { ++ "version": "4.0.0", ++ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", ++ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { -+ "node": ">=4" ++ "node": ">=8" + } + }, -+ "node_modules/hasown": { -+ "version": "2.0.2", -+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", -+ "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", ++ "node_modules/jest-matcher-utils/node_modules/supports-color": { ++ "version": "7.2.0", ++ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", ++ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { -+ "function-bind": "^1.1.2" ++ "has-flag": "^4.0.0" + }, + "engines": { -+ "node": ">= 0.4" ++ "node": ">=8" + } + }, -+ "node_modules/html-escaper": { -+ "version": "2.0.2", -+ "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", -+ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", -+ "dev": true -+ }, -+ "node_modules/human-signals": { -+ "version": "2.1.0", -+ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", -+ "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", ++ "node_modules/jest-message-util": { ++ "version": "29.7.0", ++ "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", ++ "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dev": true, ++ "dependencies": { ++ "@babel/code-frame": "^7.12.13", ++ "@jest/types": "^29.6.3", ++ "@types/stack-utils": "^2.0.0", ++ "chalk": "^4.0.0", ++ "graceful-fs": "^4.2.9", ++ "micromatch": "^4.0.4", ++ "pretty-format": "^29.7.0", ++ "slash": "^3.0.0", ++ "stack-utils": "^2.0.3" ++ }, + "engines": { -+ "node": ">=10.17.0" ++ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, -+ "node_modules/import-local": { -+ "version": "3.1.0", -+ "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", -+ "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", ++ "node_modules/jest-message-util/node_modules/ansi-styles": { ++ "version": "4.3.0", ++ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", ++ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { -+ "pkg-dir": "^4.2.0", -+ "resolve-cwd": "^3.0.0" -+ }, -+ "bin": { -+ "import-local-fixture": "fixtures/cli.js" ++ "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { -+ "url": "https://github.com/sponsors/sindresorhus" ++ "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, -+ "node_modules/imurmurhash": { -+ "version": "0.1.4", -+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", -+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", ++ "node_modules/jest-message-util/node_modules/chalk": { ++ "version": "4.1.2", ++ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", ++ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, ++ "dependencies": { ++ "ansi-styles": "^4.1.0", ++ "supports-color": "^7.1.0" ++ }, + "engines": { -+ "node": ">=0.8.19" ++ "node": ">=10" ++ }, ++ "funding": { ++ "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, -+ "node_modules/inflight": { -+ "version": "1.0.6", -+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", -+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", -+ "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", ++ "node_modules/jest-message-util/node_modules/color-convert": { ++ "version": "2.0.1", ++ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", ++ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { -+ "once": "^1.3.0", -+ "wrappy": "1" ++ "color-name": "~1.1.4" ++ }, ++ "engines": { ++ "node": ">=7.0.0" + } + }, -+ "node_modules/inherits": { -+ "version": "2.0.4", -+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", -+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", ++ "node_modules/jest-message-util/node_modules/color-name": { ++ "version": "1.1.4", ++ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", ++ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, -+ "node_modules/is-arrayish": { -+ "version": "0.2.1", -+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", -+ "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", -+ "dev": true ++ "node_modules/jest-message-util/node_modules/has-flag": { ++ "version": "4.0.0", ++ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", ++ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", ++ "dev": true, ++ "engines": { ++ "node": ">=8" ++ } + }, -+ "node_modules/is-core-module": { -+ "version": "2.14.0", -+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.14.0.tgz", -+ "integrity": "sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A==", ++ "node_modules/jest-message-util/node_modules/supports-color": { ++ "version": "7.2.0", ++ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", ++ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { -+ "hasown": "^2.0.2" ++ "has-flag": "^4.0.0" + }, + "engines": { -+ "node": ">= 0.4" -+ }, -+ "funding": { -+ "url": "https://github.com/sponsors/ljharb" ++ "node": ">=8" + } + }, -+ "node_modules/is-fullwidth-code-point": { -+ "version": "3.0.0", -+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", -+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", ++ "node_modules/jest-mock": { ++ "version": "29.7.0", ++ "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", ++ "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dev": true, ++ "dependencies": { ++ "@jest/types": "^29.6.3", ++ "@types/node": "*", ++ "jest-util": "^29.7.0" ++ }, + "engines": { -+ "node": ">=8" ++ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, -+ "node_modules/is-generator-fn": { -+ "version": "2.1.0", -+ "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", -+ "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", ++ "node_modules/jest-pnp-resolver": { ++ "version": "1.2.3", ++ "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", ++ "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "dev": true, + "engines": { + "node": ">=6" ++ }, ++ "peerDependencies": { ++ "jest-resolve": "*" ++ }, ++ "peerDependenciesMeta": { ++ "jest-resolve": { ++ "optional": true ++ } + } + }, -+ "node_modules/is-number": { -+ "version": "7.0.0", -+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", -+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", ++ "node_modules/jest-regex-util": { ++ "version": "29.6.3", ++ "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", ++ "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "dev": true, + "engines": { -+ "node": ">=0.12.0" ++ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, -+ "node_modules/is-stream": { -+ "version": "2.0.1", -+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", -+ "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", ++ "node_modules/jest-resolve": { ++ "version": "29.7.0", ++ "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", ++ "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", + "dev": true, -+ "engines": { -+ "node": ">=8" ++ "dependencies": { ++ "chalk": "^4.0.0", ++ "graceful-fs": "^4.2.9", ++ "jest-haste-map": "^29.7.0", ++ "jest-pnp-resolver": "^1.2.2", ++ "jest-util": "^29.7.0", ++ "jest-validate": "^29.7.0", ++ "resolve": "^1.20.0", ++ "resolve.exports": "^2.0.0", ++ "slash": "^3.0.0" + }, -+ "funding": { -+ "url": "https://github.com/sponsors/sindresorhus" -+ } -+ }, -+ "node_modules/isexe": { -+ "version": "2.0.0", -+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", -+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", -+ "dev": true -+ }, -+ "node_modules/isows": { -+ "version": "1.0.6", -+ "resolved": "https://registry.npmjs.org/isows/-/isows-1.0.6.tgz", -+ "integrity": "sha512-lPHCayd40oW98/I0uvgaHKWCSvkzY27LjWLbtzOm64yQ+G3Q5npjjbdppU65iZXkK1Zt+kH9pfegli0AYfwYYw==", -+ "funding": [ -+ { -+ "type": "github", -+ "url": "https://github.com/sponsors/wevm" -+ } -+ ], -+ "peerDependencies": { -+ "ws": "*" ++ "engines": { ++ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, -+ "node_modules/istanbul-lib-coverage": { -+ "version": "3.2.2", -+ "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", -+ "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", ++ "node_modules/jest-resolve-dependencies": { ++ "version": "29.7.0", ++ "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", ++ "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", + "dev": true, ++ "dependencies": { ++ "jest-regex-util": "^29.6.3", ++ "jest-snapshot": "^29.7.0" ++ }, + "engines": { -+ "node": ">=8" ++ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, -+ "node_modules/istanbul-lib-instrument": { -+ "version": "5.2.1", -+ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", -+ "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", ++ "node_modules/jest-resolve/node_modules/ansi-styles": { ++ "version": "4.3.0", ++ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", ++ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { -+ "@babel/core": "^7.12.3", -+ "@babel/parser": "^7.14.7", -+ "@istanbuljs/schema": "^0.1.2", -+ "istanbul-lib-coverage": "^3.2.0", -+ "semver": "^6.3.0" ++ "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" ++ }, ++ "funding": { ++ "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, -+ "node_modules/istanbul-lib-report": { -+ "version": "3.0.1", -+ "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", -+ "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", ++ "node_modules/jest-resolve/node_modules/chalk": { ++ "version": "4.1.2", ++ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", ++ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { -+ "istanbul-lib-coverage": "^3.0.0", -+ "make-dir": "^4.0.0", ++ "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" ++ }, ++ "funding": { ++ "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, -+ "node_modules/istanbul-lib-report/node_modules/has-flag": { ++ "node_modules/jest-resolve/node_modules/color-convert": { ++ "version": "2.0.1", ++ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", ++ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", ++ "dev": true, ++ "dependencies": { ++ "color-name": "~1.1.4" ++ }, ++ "engines": { ++ "node": ">=7.0.0" ++ } ++ }, ++ "node_modules/jest-resolve/node_modules/color-name": { ++ "version": "1.1.4", ++ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", ++ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", ++ "dev": true ++ }, ++ "node_modules/jest-resolve/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", @@ -20554,7 +73247,7 @@ + "node": ">=8" + } + }, -+ "node_modules/istanbul-lib-report/node_modules/supports-color": { ++ "node_modules/jest-resolve/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", @@ -20566,105 +73259,142 @@ + "node": ">=8" + } + }, -+ "node_modules/istanbul-lib-source-maps": { -+ "version": "4.0.1", -+ "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", -+ "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", ++ "node_modules/jest-runner": { ++ "version": "29.7.0", ++ "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", ++ "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", + "dev": true, + "dependencies": { -+ "debug": "^4.1.1", -+ "istanbul-lib-coverage": "^3.0.0", -+ "source-map": "^0.6.1" ++ "@jest/console": "^29.7.0", ++ "@jest/environment": "^29.7.0", ++ "@jest/test-result": "^29.7.0", ++ "@jest/transform": "^29.7.0", ++ "@jest/types": "^29.6.3", ++ "@types/node": "*", ++ "chalk": "^4.0.0", ++ "emittery": "^0.13.1", ++ "graceful-fs": "^4.2.9", ++ "jest-docblock": "^29.7.0", ++ "jest-environment-node": "^29.7.0", ++ "jest-haste-map": "^29.7.0", ++ "jest-leak-detector": "^29.7.0", ++ "jest-message-util": "^29.7.0", ++ "jest-resolve": "^29.7.0", ++ "jest-runtime": "^29.7.0", ++ "jest-util": "^29.7.0", ++ "jest-watcher": "^29.7.0", ++ "jest-worker": "^29.7.0", ++ "p-limit": "^3.1.0", ++ "source-map-support": "0.5.13" + }, + "engines": { -+ "node": ">=10" ++ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, -+ "node_modules/istanbul-reports": { -+ "version": "3.1.7", -+ "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", -+ "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", ++ "node_modules/jest-runner/node_modules/ansi-styles": { ++ "version": "4.3.0", ++ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", ++ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { -+ "html-escaper": "^2.0.0", -+ "istanbul-lib-report": "^3.0.0" ++ "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" ++ }, ++ "funding": { ++ "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, -+ "node_modules/jest": { -+ "version": "29.7.0", -+ "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", -+ "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", ++ "node_modules/jest-runner/node_modules/chalk": { ++ "version": "4.1.2", ++ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", ++ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { -+ "@jest/core": "^29.7.0", -+ "@jest/types": "^29.6.3", -+ "import-local": "^3.0.2", -+ "jest-cli": "^29.7.0" -+ }, -+ "bin": { -+ "jest": "bin/jest.js" ++ "ansi-styles": "^4.1.0", ++ "supports-color": "^7.1.0" + }, + "engines": { -+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" ++ "node": ">=10" + }, -+ "peerDependencies": { -+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" ++ "funding": { ++ "url": "https://github.com/chalk/chalk?sponsor=1" ++ } ++ }, ++ "node_modules/jest-runner/node_modules/color-convert": { ++ "version": "2.0.1", ++ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", ++ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", ++ "dev": true, ++ "dependencies": { ++ "color-name": "~1.1.4" + }, -+ "peerDependenciesMeta": { -+ "node-notifier": { -+ "optional": true -+ } ++ "engines": { ++ "node": ">=7.0.0" + } + }, -+ "node_modules/jest-changed-files": { -+ "version": "29.7.0", -+ "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", -+ "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", ++ "node_modules/jest-runner/node_modules/color-name": { ++ "version": "1.1.4", ++ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", ++ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", ++ "dev": true ++ }, ++ "node_modules/jest-runner/node_modules/has-flag": { ++ "version": "4.0.0", ++ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", ++ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", ++ "dev": true, ++ "engines": { ++ "node": ">=8" ++ } ++ }, ++ "node_modules/jest-runner/node_modules/supports-color": { ++ "version": "7.2.0", ++ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", ++ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { -+ "execa": "^5.0.0", -+ "jest-util": "^29.7.0", -+ "p-limit": "^3.1.0" ++ "has-flag": "^4.0.0" + }, + "engines": { -+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" ++ "node": ">=8" + } + }, -+ "node_modules/jest-circus": { ++ "node_modules/jest-runtime": { + "version": "29.7.0", -+ "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", -+ "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", ++ "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", ++ "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", -+ "@jest/expect": "^29.7.0", ++ "@jest/fake-timers": "^29.7.0", ++ "@jest/globals": "^29.7.0", ++ "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", ++ "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", -+ "co": "^4.6.0", -+ "dedent": "^1.0.0", -+ "is-generator-fn": "^2.0.0", -+ "jest-each": "^29.7.0", -+ "jest-matcher-utils": "^29.7.0", ++ "cjs-module-lexer": "^1.0.0", ++ "collect-v8-coverage": "^1.0.0", ++ "glob": "^7.1.3", ++ "graceful-fs": "^4.2.9", ++ "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", -+ "jest-runtime": "^29.7.0", ++ "jest-mock": "^29.7.0", ++ "jest-regex-util": "^29.6.3", ++ "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", -+ "p-limit": "^3.1.0", -+ "pretty-format": "^29.7.0", -+ "pure-rand": "^6.0.0", + "slash": "^3.0.0", -+ "stack-utils": "^2.0.3" ++ "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, -+ "node_modules/jest-circus/node_modules/ansi-styles": { ++ "node_modules/jest-runtime/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", @@ -20679,7 +73409,7 @@ + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, -+ "node_modules/jest-circus/node_modules/chalk": { ++ "node_modules/jest-runtime/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", @@ -20695,7 +73425,7 @@ + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, -+ "node_modules/jest-circus/node_modules/color-convert": { ++ "node_modules/jest-runtime/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", @@ -20707,13 +73437,13 @@ + "node": ">=7.0.0" + } + }, -+ "node_modules/jest-circus/node_modules/color-name": { ++ "node_modules/jest-runtime/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, -+ "node_modules/jest-circus/node_modules/has-flag": { ++ "node_modules/jest-runtime/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", @@ -20722,7 +73452,7 @@ + "node": ">=8" + } + }, -+ "node_modules/jest-circus/node_modules/supports-color": { ++ "node_modules/jest-runtime/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", @@ -20734,40 +73464,38 @@ + "node": ">=8" + } + }, -+ "node_modules/jest-cli": { ++ "node_modules/jest-snapshot": { + "version": "29.7.0", -+ "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", -+ "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", ++ "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", ++ "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "dev": true, + "dependencies": { -+ "@jest/core": "^29.7.0", -+ "@jest/test-result": "^29.7.0", ++ "@babel/core": "^7.11.6", ++ "@babel/generator": "^7.7.2", ++ "@babel/plugin-syntax-jsx": "^7.7.2", ++ "@babel/plugin-syntax-typescript": "^7.7.2", ++ "@babel/types": "^7.3.3", ++ "@jest/expect-utils": "^29.7.0", ++ "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", ++ "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", -+ "create-jest": "^29.7.0", -+ "exit": "^0.1.2", -+ "import-local": "^3.0.2", -+ "jest-config": "^29.7.0", ++ "expect": "^29.7.0", ++ "graceful-fs": "^4.2.9", ++ "jest-diff": "^29.7.0", ++ "jest-get-type": "^29.6.3", ++ "jest-matcher-utils": "^29.7.0", ++ "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", -+ "jest-validate": "^29.7.0", -+ "yargs": "^17.3.1" -+ }, -+ "bin": { -+ "jest": "bin/jest.js" ++ "natural-compare": "^1.4.0", ++ "pretty-format": "^29.7.0", ++ "semver": "^7.5.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" -+ }, -+ "peerDependencies": { -+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" -+ }, -+ "peerDependenciesMeta": { -+ "node-notifier": { -+ "optional": true -+ } + } + }, -+ "node_modules/jest-cli/node_modules/ansi-styles": { ++ "node_modules/jest-snapshot/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", @@ -20782,7 +73510,7 @@ + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, -+ "node_modules/jest-cli/node_modules/chalk": { ++ "node_modules/jest-snapshot/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", @@ -20798,7 +73526,7 @@ + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, -+ "node_modules/jest-cli/node_modules/color-convert": { ++ "node_modules/jest-snapshot/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", @@ -20810,13 +73538,13 @@ + "node": ">=7.0.0" + } + }, -+ "node_modules/jest-cli/node_modules/color-name": { ++ "node_modules/jest-snapshot/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, -+ "node_modules/jest-cli/node_modules/has-flag": { ++ "node_modules/jest-snapshot/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", @@ -20825,7 +73553,19 @@ + "node": ">=8" + } + }, -+ "node_modules/jest-cli/node_modules/supports-color": { ++ "node_modules/jest-snapshot/node_modules/semver": { ++ "version": "7.6.3", ++ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", ++ "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", ++ "dev": true, ++ "bin": { ++ "semver": "bin/semver.js" ++ }, ++ "engines": { ++ "node": ">=10" ++ } ++ }, ++ "node_modules/jest-snapshot/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", @@ -20837,52 +73577,24 @@ + "node": ">=8" + } + }, -+ "node_modules/jest-config": { ++ "node_modules/jest-util": { + "version": "29.7.0", -+ "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", -+ "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", ++ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", ++ "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dev": true, + "dependencies": { -+ "@babel/core": "^7.11.6", -+ "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", -+ "babel-jest": "^29.7.0", ++ "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", -+ "deepmerge": "^4.2.2", -+ "glob": "^7.1.3", + "graceful-fs": "^4.2.9", -+ "jest-circus": "^29.7.0", -+ "jest-environment-node": "^29.7.0", -+ "jest-get-type": "^29.6.3", -+ "jest-regex-util": "^29.6.3", -+ "jest-resolve": "^29.7.0", -+ "jest-runner": "^29.7.0", -+ "jest-util": "^29.7.0", -+ "jest-validate": "^29.7.0", -+ "micromatch": "^4.0.4", -+ "parse-json": "^5.2.0", -+ "pretty-format": "^29.7.0", -+ "slash": "^3.0.0", -+ "strip-json-comments": "^3.1.1" ++ "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" -+ }, -+ "peerDependencies": { -+ "@types/node": "*", -+ "ts-node": ">=9.0.0" -+ }, -+ "peerDependenciesMeta": { -+ "@types/node": { -+ "optional": true -+ }, -+ "ts-node": { -+ "optional": true -+ } + } + }, -+ "node_modules/jest-config/node_modules/ansi-styles": { ++ "node_modules/jest-util/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", @@ -20897,7 +73609,7 @@ + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, -+ "node_modules/jest-config/node_modules/chalk": { ++ "node_modules/jest-util/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", @@ -20913,7 +73625,7 @@ + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, -+ "node_modules/jest-config/node_modules/color-convert": { ++ "node_modules/jest-util/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", @@ -20925,13 +73637,13 @@ + "node": ">=7.0.0" + } + }, -+ "node_modules/jest-config/node_modules/color-name": { ++ "node_modules/jest-util/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, -+ "node_modules/jest-config/node_modules/has-flag": { ++ "node_modules/jest-util/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", @@ -20940,7 +73652,7 @@ + "node": ">=8" + } + }, -+ "node_modules/jest-config/node_modules/supports-color": { ++ "node_modules/jest-util/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", @@ -20952,22 +73664,24 @@ + "node": ">=8" + } + }, -+ "node_modules/jest-diff": { ++ "node_modules/jest-validate": { + "version": "29.7.0", -+ "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", -+ "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", ++ "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", ++ "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "dev": true, + "dependencies": { ++ "@jest/types": "^29.6.3", ++ "camelcase": "^6.2.0", + "chalk": "^4.0.0", -+ "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", ++ "leven": "^3.1.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, -+ "node_modules/jest-diff/node_modules/ansi-styles": { ++ "node_modules/jest-validate/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", @@ -20982,7 +73696,19 @@ + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, -+ "node_modules/jest-diff/node_modules/chalk": { ++ "node_modules/jest-validate/node_modules/camelcase": { ++ "version": "6.3.0", ++ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", ++ "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", ++ "dev": true, ++ "engines": { ++ "node": ">=10" ++ }, ++ "funding": { ++ "url": "https://github.com/sponsors/sindresorhus" ++ } ++ }, ++ "node_modules/jest-validate/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", @@ -20998,7 +73724,7 @@ + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, -+ "node_modules/jest-diff/node_modules/color-convert": { ++ "node_modules/jest-validate/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", @@ -21010,13 +73736,13 @@ + "node": ">=7.0.0" + } + }, -+ "node_modules/jest-diff/node_modules/color-name": { ++ "node_modules/jest-validate/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, -+ "node_modules/jest-diff/node_modules/has-flag": { ++ "node_modules/jest-validate/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", @@ -21025,7 +73751,7 @@ + "node": ">=8" + } + }, -+ "node_modules/jest-diff/node_modules/supports-color": { ++ "node_modules/jest-validate/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", @@ -21037,35 +73763,26 @@ + "node": ">=8" + } + }, -+ "node_modules/jest-docblock": { -+ "version": "29.7.0", -+ "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", -+ "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", -+ "dev": true, -+ "dependencies": { -+ "detect-newline": "^3.0.0" -+ }, -+ "engines": { -+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" -+ } -+ }, -+ "node_modules/jest-each": { ++ "node_modules/jest-watcher": { + "version": "29.7.0", -+ "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", -+ "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", ++ "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", ++ "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "dev": true, + "dependencies": { ++ "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", ++ "@types/node": "*", ++ "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", -+ "jest-get-type": "^29.6.3", ++ "emittery": "^0.13.1", + "jest-util": "^29.7.0", -+ "pretty-format": "^29.7.0" ++ "string-length": "^4.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, -+ "node_modules/jest-each/node_modules/ansi-styles": { ++ "node_modules/jest-watcher/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", @@ -21080,7 +73797,7 @@ + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, -+ "node_modules/jest-each/node_modules/chalk": { ++ "node_modules/jest-watcher/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", @@ -21096,7 +73813,7 @@ + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, -+ "node_modules/jest-each/node_modules/color-convert": { ++ "node_modules/jest-watcher/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", @@ -21108,13 +73825,13 @@ + "node": ">=7.0.0" + } + }, -+ "node_modules/jest-each/node_modules/color-name": { ++ "node_modules/jest-watcher/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, -+ "node_modules/jest-each/node_modules/has-flag": { ++ "node_modules/jest-watcher/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", @@ -21123,7 +73840,7 @@ + "node": ">=8" + } + }, -+ "node_modules/jest-each/node_modules/supports-color": { ++ "node_modules/jest-watcher/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", @@ -21135,912 +73852,1046 @@ + "node": ">=8" + } + }, -+ "node_modules/jest-environment-node": { ++ "node_modules/jest-worker": { + "version": "29.7.0", -+ "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", -+ "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", ++ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", ++ "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dev": true, + "dependencies": { -+ "@jest/environment": "^29.7.0", -+ "@jest/fake-timers": "^29.7.0", -+ "@jest/types": "^29.6.3", + "@types/node": "*", -+ "jest-mock": "^29.7.0", -+ "jest-util": "^29.7.0" ++ "jest-util": "^29.7.0", ++ "merge-stream": "^2.0.0", ++ "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, -+ "node_modules/jest-get-type": { -+ "version": "29.6.3", -+ "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", -+ "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", ++ "node_modules/jest-worker/node_modules/has-flag": { ++ "version": "4.0.0", ++ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", ++ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { -+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" ++ "node": ">=8" + } + }, -+ "node_modules/jest-haste-map": { -+ "version": "29.7.0", -+ "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", -+ "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", ++ "node_modules/jest-worker/node_modules/supports-color": { ++ "version": "8.1.1", ++ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", ++ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { -+ "@jest/types": "^29.6.3", -+ "@types/graceful-fs": "^4.1.3", -+ "@types/node": "*", -+ "anymatch": "^3.0.3", -+ "fb-watchman": "^2.0.0", -+ "graceful-fs": "^4.2.9", -+ "jest-regex-util": "^29.6.3", -+ "jest-util": "^29.7.0", -+ "jest-worker": "^29.7.0", -+ "micromatch": "^4.0.4", -+ "walker": "^1.0.8" ++ "has-flag": "^4.0.0" + }, + "engines": { -+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" ++ "node": ">=10" + }, -+ "optionalDependencies": { -+ "fsevents": "^2.3.2" ++ "funding": { ++ "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, -+ "node_modules/jest-leak-detector": { -+ "version": "29.7.0", -+ "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", -+ "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", ++ "node_modules/js-tokens": { ++ "version": "4.0.0", ++ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", ++ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", ++ "dev": true ++ }, ++ "node_modules/js-yaml": { ++ "version": "3.14.1", ++ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", ++ "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { -+ "jest-get-type": "^29.6.3", -+ "pretty-format": "^29.7.0" ++ "argparse": "^1.0.7", ++ "esprima": "^4.0.0" ++ }, ++ "bin": { ++ "js-yaml": "bin/js-yaml.js" ++ } ++ }, ++ "node_modules/jsesc": { ++ "version": "2.5.2", ++ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", ++ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", ++ "dev": true, ++ "bin": { ++ "jsesc": "bin/jsesc" + }, + "engines": { -+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" ++ "node": ">=4" + } + }, -+ "node_modules/jest-matcher-utils": { -+ "version": "29.7.0", -+ "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", -+ "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", ++ "node_modules/json-parse-even-better-errors": { ++ "version": "2.3.1", ++ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", ++ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", ++ "dev": true ++ }, ++ "node_modules/json5": { ++ "version": "2.2.3", ++ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", ++ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, -+ "dependencies": { -+ "chalk": "^4.0.0", -+ "jest-diff": "^29.7.0", -+ "jest-get-type": "^29.6.3", -+ "pretty-format": "^29.7.0" ++ "bin": { ++ "json5": "lib/cli.js" + }, + "engines": { -+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" ++ "node": ">=6" + } + }, -+ "node_modules/jest-matcher-utils/node_modules/ansi-styles": { -+ "version": "4.3.0", -+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", -+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", ++ "node_modules/kleur": { ++ "version": "3.0.3", ++ "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", ++ "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", ++ "dev": true, ++ "engines": { ++ "node": ">=6" ++ } ++ }, ++ "node_modules/leven": { ++ "version": "3.1.0", ++ "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", ++ "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", ++ "dev": true, ++ "engines": { ++ "node": ">=6" ++ } ++ }, ++ "node_modules/lines-and-columns": { ++ "version": "1.2.4", ++ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", ++ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", ++ "dev": true ++ }, ++ "node_modules/locate-path": { ++ "version": "5.0.0", ++ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", ++ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { -+ "color-convert": "^2.0.1" ++ "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" -+ }, -+ "funding": { -+ "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, -+ "node_modules/jest-matcher-utils/node_modules/chalk": { -+ "version": "4.1.2", -+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", -+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", ++ "node_modules/lodash.debounce": { ++ "version": "4.0.8", ++ "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", ++ "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", ++ "dev": true ++ }, ++ "node_modules/lru-cache": { ++ "version": "5.1.1", ++ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", ++ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { -+ "ansi-styles": "^4.1.0", -+ "supports-color": "^7.1.0" ++ "yallist": "^3.0.2" ++ } ++ }, ++ "node_modules/make-dir": { ++ "version": "4.0.0", ++ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", ++ "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", ++ "dev": true, ++ "dependencies": { ++ "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { -+ "url": "https://github.com/chalk/chalk?sponsor=1" ++ "url": "https://github.com/sponsors/sindresorhus" + } + }, -+ "node_modules/jest-matcher-utils/node_modules/color-convert": { -+ "version": "2.0.1", -+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", -+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", ++ "node_modules/make-dir/node_modules/semver": { ++ "version": "7.6.3", ++ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", ++ "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", ++ "dev": true, ++ "bin": { ++ "semver": "bin/semver.js" ++ }, ++ "engines": { ++ "node": ">=10" ++ } ++ }, ++ "node_modules/makeerror": { ++ "version": "1.0.12", ++ "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", ++ "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "dependencies": { -+ "color-name": "~1.1.4" ++ "tmpl": "1.0.5" ++ } ++ }, ++ "node_modules/merge-stream": { ++ "version": "2.0.0", ++ "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", ++ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", ++ "dev": true ++ }, ++ "node_modules/micromatch": { ++ "version": "4.0.7", ++ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", ++ "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", ++ "dev": true, ++ "dependencies": { ++ "braces": "^3.0.3", ++ "picomatch": "^2.3.1" + }, + "engines": { -+ "node": ">=7.0.0" ++ "node": ">=8.6" + } + }, -+ "node_modules/jest-matcher-utils/node_modules/color-name": { -+ "version": "1.1.4", -+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", -+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", ++ "node_modules/mimic-fn": { ++ "version": "2.1.0", ++ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", ++ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", ++ "dev": true, ++ "engines": { ++ "node": ">=6" ++ } ++ }, ++ "node_modules/minimatch": { ++ "version": "3.1.2", ++ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", ++ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", ++ "dev": true, ++ "dependencies": { ++ "brace-expansion": "^1.1.7" ++ }, ++ "engines": { ++ "node": "*" ++ } ++ }, ++ "node_modules/ms": { ++ "version": "2.1.2", ++ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", ++ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, -+ "node_modules/jest-matcher-utils/node_modules/has-flag": { -+ "version": "4.0.0", -+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", -+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", ++ "node_modules/natural-compare": { ++ "version": "1.4.0", ++ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", ++ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", ++ "dev": true ++ }, ++ "node_modules/node-int64": { ++ "version": "0.4.0", ++ "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", ++ "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", ++ "dev": true ++ }, ++ "node_modules/node-releases": { ++ "version": "2.0.17", ++ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.17.tgz", ++ "integrity": "sha512-Ww6ZlOiEQfPfXM45v17oabk77Z7mg5bOt7AjDyzy7RjK9OrLrLC8dyZQoAPEOtFX9SaNf1Tdvr5gRJWdTJj7GA==", ++ "dev": true ++ }, ++ "node_modules/normalize-path": { ++ "version": "3.0.0", ++ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", ++ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { -+ "node": ">=8" ++ "node": ">=0.10.0" + } + }, -+ "node_modules/jest-matcher-utils/node_modules/supports-color": { -+ "version": "7.2.0", -+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", -+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", ++ "node_modules/npm-run-path": { ++ "version": "4.0.1", ++ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", ++ "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { -+ "has-flag": "^4.0.0" ++ "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, -+ "node_modules/jest-message-util": { -+ "version": "29.7.0", -+ "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", -+ "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", ++ "node_modules/once": { ++ "version": "1.4.0", ++ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", ++ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { -+ "@babel/code-frame": "^7.12.13", -+ "@jest/types": "^29.6.3", -+ "@types/stack-utils": "^2.0.0", -+ "chalk": "^4.0.0", -+ "graceful-fs": "^4.2.9", -+ "micromatch": "^4.0.4", -+ "pretty-format": "^29.7.0", -+ "slash": "^3.0.0", -+ "stack-utils": "^2.0.3" ++ "wrappy": "1" ++ } ++ }, ++ "node_modules/onetime": { ++ "version": "5.1.2", ++ "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", ++ "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", ++ "dev": true, ++ "dependencies": { ++ "mimic-fn": "^2.1.0" + }, + "engines": { -+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" ++ "node": ">=6" ++ }, ++ "funding": { ++ "url": "https://github.com/sponsors/sindresorhus" ++ } ++ }, ++ "node_modules/p-limit": { ++ "version": "3.1.0", ++ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", ++ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", ++ "dev": true, ++ "dependencies": { ++ "yocto-queue": "^0.1.0" ++ }, ++ "engines": { ++ "node": ">=10" ++ }, ++ "funding": { ++ "url": "https://github.com/sponsors/sindresorhus" + } + }, -+ "node_modules/jest-message-util/node_modules/ansi-styles": { -+ "version": "4.3.0", -+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", -+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", ++ "node_modules/p-locate": { ++ "version": "4.1.0", ++ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", ++ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { -+ "color-convert": "^2.0.1" ++ "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" -+ }, -+ "funding": { -+ "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, -+ "node_modules/jest-message-util/node_modules/chalk": { -+ "version": "4.1.2", -+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", -+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", ++ "node_modules/p-locate/node_modules/p-limit": { ++ "version": "2.3.0", ++ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", ++ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { -+ "ansi-styles": "^4.1.0", -+ "supports-color": "^7.1.0" ++ "p-try": "^2.0.0" + }, + "engines": { -+ "node": ">=10" ++ "node": ">=6" + }, + "funding": { -+ "url": "https://github.com/chalk/chalk?sponsor=1" ++ "url": "https://github.com/sponsors/sindresorhus" + } + }, -+ "node_modules/jest-message-util/node_modules/color-convert": { -+ "version": "2.0.1", -+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", -+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", ++ "node_modules/p-try": { ++ "version": "2.2.0", ++ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", ++ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", ++ "dev": true, ++ "engines": { ++ "node": ">=6" ++ } ++ }, ++ "node_modules/parse-json": { ++ "version": "5.2.0", ++ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", ++ "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { -+ "color-name": "~1.1.4" ++ "@babel/code-frame": "^7.0.0", ++ "error-ex": "^1.3.1", ++ "json-parse-even-better-errors": "^2.3.0", ++ "lines-and-columns": "^1.1.6" + }, + "engines": { -+ "node": ">=7.0.0" ++ "node": ">=8" ++ }, ++ "funding": { ++ "url": "https://github.com/sponsors/sindresorhus" + } + }, -+ "node_modules/jest-message-util/node_modules/color-name": { -+ "version": "1.1.4", -+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", -+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", -+ "dev": true -+ }, -+ "node_modules/jest-message-util/node_modules/has-flag": { ++ "node_modules/path-exists": { + "version": "4.0.0", -+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", -+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", ++ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", ++ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, -+ "node_modules/jest-message-util/node_modules/supports-color": { -+ "version": "7.2.0", -+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", -+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", ++ "node_modules/path-is-absolute": { ++ "version": "1.0.1", ++ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", ++ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, -+ "dependencies": { -+ "has-flag": "^4.0.0" -+ }, + "engines": { -+ "node": ">=8" ++ "node": ">=0.10.0" + } + }, -+ "node_modules/jest-mock": { -+ "version": "29.7.0", -+ "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", -+ "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", ++ "node_modules/path-key": { ++ "version": "3.1.1", ++ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", ++ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, -+ "dependencies": { -+ "@jest/types": "^29.6.3", -+ "@types/node": "*", -+ "jest-util": "^29.7.0" -+ }, + "engines": { -+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" ++ "node": ">=8" + } + }, -+ "node_modules/jest-pnp-resolver": { -+ "version": "1.2.3", -+ "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", -+ "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", ++ "node_modules/path-parse": { ++ "version": "1.0.7", ++ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", ++ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", ++ "dev": true ++ }, ++ "node_modules/picocolors": { ++ "version": "1.0.1", ++ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", ++ "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", ++ "dev": true ++ }, ++ "node_modules/picomatch": { ++ "version": "2.3.1", ++ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", ++ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { -+ "node": ">=6" -+ }, -+ "peerDependencies": { -+ "jest-resolve": "*" ++ "node": ">=8.6" + }, -+ "peerDependenciesMeta": { -+ "jest-resolve": { -+ "optional": true -+ } ++ "funding": { ++ "url": "https://github.com/sponsors/jonschlinkert" + } + }, -+ "node_modules/jest-regex-util": { -+ "version": "29.6.3", -+ "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", -+ "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", ++ "node_modules/pirates": { ++ "version": "4.0.6", ++ "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", ++ "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true, + "engines": { -+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" ++ "node": ">= 6" + } + }, -+ "node_modules/jest-resolve": { -+ "version": "29.7.0", -+ "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", -+ "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", ++ "node_modules/pkg-dir": { ++ "version": "4.2.0", ++ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", ++ "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "dependencies": { -+ "chalk": "^4.0.0", -+ "graceful-fs": "^4.2.9", -+ "jest-haste-map": "^29.7.0", -+ "jest-pnp-resolver": "^1.2.2", -+ "jest-util": "^29.7.0", -+ "jest-validate": "^29.7.0", -+ "resolve": "^1.20.0", -+ "resolve.exports": "^2.0.0", -+ "slash": "^3.0.0" ++ "find-up": "^4.0.0" + }, + "engines": { -+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" ++ "node": ">=8" + } + }, -+ "node_modules/jest-resolve-dependencies": { ++ "node_modules/pretty-format": { + "version": "29.7.0", -+ "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", -+ "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", ++ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", ++ "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "dependencies": { -+ "jest-regex-util": "^29.6.3", -+ "jest-snapshot": "^29.7.0" ++ "@jest/schemas": "^29.6.3", ++ "ansi-styles": "^5.0.0", ++ "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, -+ "node_modules/jest-resolve/node_modules/ansi-styles": { -+ "version": "4.3.0", -+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", -+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", ++ "node_modules/pretty-format/node_modules/ansi-styles": { ++ "version": "5.2.0", ++ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", ++ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, -+ "dependencies": { -+ "color-convert": "^2.0.1" -+ }, + "engines": { -+ "node": ">=8" ++ "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, -+ "node_modules/jest-resolve/node_modules/chalk": { -+ "version": "4.1.2", -+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", -+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", ++ "node_modules/prompts": { ++ "version": "2.4.2", ++ "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", ++ "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "dependencies": { -+ "ansi-styles": "^4.1.0", -+ "supports-color": "^7.1.0" ++ "kleur": "^3.0.3", ++ "sisteransi": "^1.0.5" + }, + "engines": { -+ "node": ">=10" -+ }, -+ "funding": { -+ "url": "https://github.com/chalk/chalk?sponsor=1" ++ "node": ">= 6" + } + }, -+ "node_modules/jest-resolve/node_modules/color-convert": { -+ "version": "2.0.1", -+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", -+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", ++ "node_modules/pure-rand": { ++ "version": "6.1.0", ++ "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", ++ "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", ++ "dev": true, ++ "funding": [ ++ { ++ "type": "individual", ++ "url": "https://github.com/sponsors/dubzzz" ++ }, ++ { ++ "type": "opencollective", ++ "url": "https://opencollective.com/fast-check" ++ } ++ ] ++ }, ++ "node_modules/react-is": { ++ "version": "18.3.1", ++ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", ++ "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", ++ "dev": true ++ }, ++ "node_modules/regenerate": { ++ "version": "1.4.2", ++ "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", ++ "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", ++ "dev": true ++ }, ++ "node_modules/regenerate-unicode-properties": { ++ "version": "10.1.1", ++ "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz", ++ "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==", + "dev": true, + "dependencies": { -+ "color-name": "~1.1.4" ++ "regenerate": "^1.4.2" + }, + "engines": { -+ "node": ">=7.0.0" ++ "node": ">=4" + } + }, -+ "node_modules/jest-resolve/node_modules/color-name": { -+ "version": "1.1.4", -+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", -+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", ++ "node_modules/regenerator-runtime": { ++ "version": "0.14.1", ++ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", ++ "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", + "dev": true + }, -+ "node_modules/jest-resolve/node_modules/has-flag": { -+ "version": "4.0.0", -+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", -+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", ++ "node_modules/regenerator-transform": { ++ "version": "0.15.2", ++ "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", ++ "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "dev": true, -+ "engines": { -+ "node": ">=8" ++ "dependencies": { ++ "@babel/runtime": "^7.8.4" + } + }, -+ "node_modules/jest-resolve/node_modules/supports-color": { -+ "version": "7.2.0", -+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", -+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", ++ "node_modules/regexpu-core": { ++ "version": "5.3.2", ++ "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", ++ "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", + "dev": true, + "dependencies": { -+ "has-flag": "^4.0.0" ++ "@babel/regjsgen": "^0.8.0", ++ "regenerate": "^1.4.2", ++ "regenerate-unicode-properties": "^10.1.0", ++ "regjsparser": "^0.9.1", ++ "unicode-match-property-ecmascript": "^2.0.0", ++ "unicode-match-property-value-ecmascript": "^2.1.0" + }, + "engines": { -+ "node": ">=8" ++ "node": ">=4" + } + }, -+ "node_modules/jest-runner": { -+ "version": "29.7.0", -+ "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", -+ "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", ++ "node_modules/regjsparser": { ++ "version": "0.9.1", ++ "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", ++ "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "dev": true, + "dependencies": { -+ "@jest/console": "^29.7.0", -+ "@jest/environment": "^29.7.0", -+ "@jest/test-result": "^29.7.0", -+ "@jest/transform": "^29.7.0", -+ "@jest/types": "^29.6.3", -+ "@types/node": "*", -+ "chalk": "^4.0.0", -+ "emittery": "^0.13.1", -+ "graceful-fs": "^4.2.9", -+ "jest-docblock": "^29.7.0", -+ "jest-environment-node": "^29.7.0", -+ "jest-haste-map": "^29.7.0", -+ "jest-leak-detector": "^29.7.0", -+ "jest-message-util": "^29.7.0", -+ "jest-resolve": "^29.7.0", -+ "jest-runtime": "^29.7.0", -+ "jest-util": "^29.7.0", -+ "jest-watcher": "^29.7.0", -+ "jest-worker": "^29.7.0", -+ "p-limit": "^3.1.0", -+ "source-map-support": "0.5.13" ++ "jsesc": "~0.5.0" + }, -+ "engines": { -+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" ++ "bin": { ++ "regjsparser": "bin/parser" + } + }, -+ "node_modules/jest-runner/node_modules/ansi-styles": { -+ "version": "4.3.0", -+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", -+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", ++ "node_modules/regjsparser/node_modules/jsesc": { ++ "version": "0.5.0", ++ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", ++ "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", ++ "dev": true, ++ "bin": { ++ "jsesc": "bin/jsesc" ++ } ++ }, ++ "node_modules/require-directory": { ++ "version": "2.1.1", ++ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", ++ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, -+ "dependencies": { -+ "color-convert": "^2.0.1" -+ }, + "engines": { -+ "node": ">=8" -+ }, -+ "funding": { -+ "url": "https://github.com/chalk/ansi-styles?sponsor=1" ++ "node": ">=0.10.0" + } + }, -+ "node_modules/jest-runner/node_modules/chalk": { -+ "version": "4.1.2", -+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", -+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", ++ "node_modules/resolve": { ++ "version": "1.22.8", ++ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", ++ "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "dependencies": { -+ "ansi-styles": "^4.1.0", -+ "supports-color": "^7.1.0" ++ "is-core-module": "^2.13.0", ++ "path-parse": "^1.0.7", ++ "supports-preserve-symlinks-flag": "^1.0.0" + }, -+ "engines": { -+ "node": ">=10" ++ "bin": { ++ "resolve": "bin/resolve" + }, + "funding": { -+ "url": "https://github.com/chalk/chalk?sponsor=1" ++ "url": "https://github.com/sponsors/ljharb" + } + }, -+ "node_modules/jest-runner/node_modules/color-convert": { -+ "version": "2.0.1", -+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", -+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", ++ "node_modules/resolve-cwd": { ++ "version": "3.0.0", ++ "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", ++ "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "dependencies": { -+ "color-name": "~1.1.4" ++ "resolve-from": "^5.0.0" + }, + "engines": { -+ "node": ">=7.0.0" ++ "node": ">=8" + } + }, -+ "node_modules/jest-runner/node_modules/color-name": { -+ "version": "1.1.4", -+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", -+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", -+ "dev": true -+ }, -+ "node_modules/jest-runner/node_modules/has-flag": { -+ "version": "4.0.0", -+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", -+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", ++ "node_modules/resolve-from": { ++ "version": "5.0.0", ++ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", ++ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, -+ "node_modules/jest-runner/node_modules/supports-color": { -+ "version": "7.2.0", -+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", -+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", ++ "node_modules/resolve.exports": { ++ "version": "2.0.2", ++ "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", ++ "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", + "dev": true, -+ "dependencies": { -+ "has-flag": "^4.0.0" -+ }, + "engines": { -+ "node": ">=8" ++ "node": ">=10" + } + }, -+ "node_modules/jest-runtime": { -+ "version": "29.7.0", -+ "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", -+ "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", -+ "dev": true, -+ "dependencies": { -+ "@jest/environment": "^29.7.0", -+ "@jest/fake-timers": "^29.7.0", -+ "@jest/globals": "^29.7.0", -+ "@jest/source-map": "^29.6.3", -+ "@jest/test-result": "^29.7.0", -+ "@jest/transform": "^29.7.0", -+ "@jest/types": "^29.6.3", -+ "@types/node": "*", -+ "chalk": "^4.0.0", -+ "cjs-module-lexer": "^1.0.0", -+ "collect-v8-coverage": "^1.0.0", -+ "glob": "^7.1.3", -+ "graceful-fs": "^4.2.9", -+ "jest-haste-map": "^29.7.0", -+ "jest-message-util": "^29.7.0", -+ "jest-mock": "^29.7.0", -+ "jest-regex-util": "^29.6.3", -+ "jest-resolve": "^29.7.0", -+ "jest-snapshot": "^29.7.0", -+ "jest-util": "^29.7.0", -+ "slash": "^3.0.0", -+ "strip-bom": "^4.0.0" ++ "node_modules/reverse-mirage": { ++ "version": "1.1.0", ++ "resolved": "https://registry.npmjs.org/reverse-mirage/-/reverse-mirage-1.1.0.tgz", ++ "integrity": "sha512-cA1O7GR0pn4rMFoaiEG7Skms9GenuW91DtCxeR5hphyNhH90eowV4RmUVlVPVS11CPkezm/iUjnCfmxlHri05w==", ++ "peerDependencies": { ++ "typescript": ">=5.0.4", ++ "viem": ">=2" + }, -+ "engines": { -+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" ++ "peerDependenciesMeta": { ++ "typescript": { ++ "optional": true ++ } + } + }, -+ "node_modules/jest-runtime/node_modules/ansi-styles": { -+ "version": "4.3.0", -+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", -+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", ++ "node_modules/semver": { ++ "version": "6.3.1", ++ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", ++ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, -+ "dependencies": { -+ "color-convert": "^2.0.1" -+ }, -+ "engines": { -+ "node": ">=8" -+ }, -+ "funding": { -+ "url": "https://github.com/chalk/ansi-styles?sponsor=1" ++ "bin": { ++ "semver": "bin/semver.js" + } + }, -+ "node_modules/jest-runtime/node_modules/chalk": { -+ "version": "4.1.2", -+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", -+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", ++ "node_modules/shebang-command": { ++ "version": "2.0.0", ++ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", ++ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { -+ "ansi-styles": "^4.1.0", -+ "supports-color": "^7.1.0" ++ "shebang-regex": "^3.0.0" + }, + "engines": { -+ "node": ">=10" -+ }, -+ "funding": { -+ "url": "https://github.com/chalk/chalk?sponsor=1" ++ "node": ">=8" + } + }, -+ "node_modules/jest-runtime/node_modules/color-convert": { -+ "version": "2.0.1", -+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", -+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", ++ "node_modules/shebang-regex": { ++ "version": "3.0.0", ++ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", ++ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, -+ "dependencies": { -+ "color-name": "~1.1.4" -+ }, + "engines": { -+ "node": ">=7.0.0" ++ "node": ">=8" + } + }, -+ "node_modules/jest-runtime/node_modules/color-name": { -+ "version": "1.1.4", -+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", -+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", ++ "node_modules/signal-exit": { ++ "version": "3.0.7", ++ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", ++ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, -+ "node_modules/jest-runtime/node_modules/has-flag": { -+ "version": "4.0.0", -+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", -+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", ++ "node_modules/sisteransi": { ++ "version": "1.0.5", ++ "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", ++ "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", ++ "dev": true ++ }, ++ "node_modules/slash": { ++ "version": "3.0.0", ++ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", ++ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", ++ "dev": true, ++ "engines": { ++ "node": ">=8" ++ } ++ }, ++ "node_modules/source-map": { ++ "version": "0.6.1", ++ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", ++ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { -+ "node": ">=8" ++ "node": ">=0.10.0" + } + }, -+ "node_modules/jest-runtime/node_modules/supports-color": { -+ "version": "7.2.0", -+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", -+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", ++ "node_modules/source-map-support": { ++ "version": "0.5.13", ++ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", ++ "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "dependencies": { -+ "has-flag": "^4.0.0" -+ }, -+ "engines": { -+ "node": ">=8" ++ "buffer-from": "^1.0.0", ++ "source-map": "^0.6.0" + } + }, -+ "node_modules/jest-snapshot": { -+ "version": "29.7.0", -+ "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", -+ "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", ++ "node_modules/sprintf-js": { ++ "version": "1.0.3", ++ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", ++ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", ++ "dev": true ++ }, ++ "node_modules/stack-utils": { ++ "version": "2.0.6", ++ "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", ++ "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, + "dependencies": { -+ "@babel/core": "^7.11.6", -+ "@babel/generator": "^7.7.2", -+ "@babel/plugin-syntax-jsx": "^7.7.2", -+ "@babel/plugin-syntax-typescript": "^7.7.2", -+ "@babel/types": "^7.3.3", -+ "@jest/expect-utils": "^29.7.0", -+ "@jest/transform": "^29.7.0", -+ "@jest/types": "^29.6.3", -+ "babel-preset-current-node-syntax": "^1.0.0", -+ "chalk": "^4.0.0", -+ "expect": "^29.7.0", -+ "graceful-fs": "^4.2.9", -+ "jest-diff": "^29.7.0", -+ "jest-get-type": "^29.6.3", -+ "jest-matcher-utils": "^29.7.0", -+ "jest-message-util": "^29.7.0", -+ "jest-util": "^29.7.0", -+ "natural-compare": "^1.4.0", -+ "pretty-format": "^29.7.0", -+ "semver": "^7.5.3" ++ "escape-string-regexp": "^2.0.0" + }, + "engines": { -+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" ++ "node": ">=10" + } + }, -+ "node_modules/jest-snapshot/node_modules/ansi-styles": { -+ "version": "4.3.0", -+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", -+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", ++ "node_modules/stack-utils/node_modules/escape-string-regexp": { ++ "version": "2.0.0", ++ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", ++ "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, -+ "dependencies": { -+ "color-convert": "^2.0.1" -+ }, + "engines": { + "node": ">=8" -+ }, -+ "funding": { -+ "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, -+ "node_modules/jest-snapshot/node_modules/chalk": { -+ "version": "4.1.2", -+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", -+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", ++ "node_modules/string-length": { ++ "version": "4.0.2", ++ "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", ++ "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "dependencies": { -+ "ansi-styles": "^4.1.0", -+ "supports-color": "^7.1.0" ++ "char-regex": "^1.0.2", ++ "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" -+ }, -+ "funding": { -+ "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, -+ "node_modules/jest-snapshot/node_modules/color-convert": { -+ "version": "2.0.1", -+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", -+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", ++ "node_modules/string-width": { ++ "version": "4.2.3", ++ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", ++ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { -+ "color-name": "~1.1.4" ++ "emoji-regex": "^8.0.0", ++ "is-fullwidth-code-point": "^3.0.0", ++ "strip-ansi": "^6.0.1" + }, + "engines": { -+ "node": ">=7.0.0" -+ } -+ }, -+ "node_modules/jest-snapshot/node_modules/color-name": { -+ "version": "1.1.4", -+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", -+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", -+ "dev": true -+ }, -+ "node_modules/jest-snapshot/node_modules/has-flag": { -+ "version": "4.0.0", -+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", -+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", -+ "dev": true, -+ "engines": { + "node": ">=8" + } + }, -+ "node_modules/jest-snapshot/node_modules/semver": { -+ "version": "7.6.3", -+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", -+ "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", ++ "node_modules/strip-ansi": { ++ "version": "6.0.1", ++ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", ++ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, -+ "bin": { -+ "semver": "bin/semver.js" ++ "dependencies": { ++ "ansi-regex": "^5.0.1" + }, + "engines": { -+ "node": ">=10" ++ "node": ">=8" + } + }, -+ "node_modules/jest-snapshot/node_modules/supports-color": { -+ "version": "7.2.0", -+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", -+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", ++ "node_modules/strip-bom": { ++ "version": "4.0.0", ++ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", ++ "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, -+ "dependencies": { -+ "has-flag": "^4.0.0" -+ }, + "engines": { + "node": ">=8" + } + }, -+ "node_modules/jest-util": { -+ "version": "29.7.0", -+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", -+ "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", ++ "node_modules/strip-final-newline": { ++ "version": "2.0.0", ++ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", ++ "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, -+ "dependencies": { -+ "@jest/types": "^29.6.3", -+ "@types/node": "*", -+ "chalk": "^4.0.0", -+ "ci-info": "^3.2.0", -+ "graceful-fs": "^4.2.9", -+ "picomatch": "^2.2.3" -+ }, + "engines": { -+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" ++ "node": ">=6" + } + }, -+ "node_modules/jest-util/node_modules/ansi-styles": { -+ "version": "4.3.0", -+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", -+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", ++ "node_modules/strip-json-comments": { ++ "version": "3.1.1", ++ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", ++ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, -+ "dependencies": { -+ "color-convert": "^2.0.1" -+ }, + "engines": { + "node": ">=8" + }, + "funding": { -+ "url": "https://github.com/chalk/ansi-styles?sponsor=1" ++ "url": "https://github.com/sponsors/sindresorhus" + } + }, -+ "node_modules/jest-util/node_modules/chalk": { -+ "version": "4.1.2", -+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", -+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", ++ "node_modules/supports-color": { ++ "version": "5.5.0", ++ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", ++ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { -+ "ansi-styles": "^4.1.0", -+ "supports-color": "^7.1.0" ++ "has-flag": "^3.0.0" + }, + "engines": { -+ "node": ">=10" ++ "node": ">=4" ++ } ++ }, ++ "node_modules/supports-preserve-symlinks-flag": { ++ "version": "1.0.0", ++ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", ++ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", ++ "dev": true, ++ "engines": { ++ "node": ">= 0.4" + }, + "funding": { -+ "url": "https://github.com/chalk/chalk?sponsor=1" ++ "url": "https://github.com/sponsors/ljharb" + } + }, -+ "node_modules/jest-util/node_modules/color-convert": { -+ "version": "2.0.1", -+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", -+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", ++ "node_modules/test-exclude": { ++ "version": "6.0.0", ++ "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", ++ "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "dependencies": { -+ "color-name": "~1.1.4" ++ "@istanbuljs/schema": "^0.1.2", ++ "glob": "^7.1.4", ++ "minimatch": "^3.0.4" + }, + "engines": { -+ "node": ">=7.0.0" ++ "node": ">=8" + } + }, -+ "node_modules/jest-util/node_modules/color-name": { -+ "version": "1.1.4", -+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", -+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", ++ "node_modules/tmpl": { ++ "version": "1.0.5", ++ "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", ++ "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true + }, -+ "node_modules/jest-util/node_modules/has-flag": { -+ "version": "4.0.0", -+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", -+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", ++ "node_modules/to-fast-properties": { ++ "version": "2.0.0", ++ "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", ++ "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true, + "engines": { -+ "node": ">=8" ++ "node": ">=4" + } + }, -+ "node_modules/jest-util/node_modules/supports-color": { -+ "version": "7.2.0", -+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", -+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", ++ "node_modules/to-regex-range": { ++ "version": "5.0.1", ++ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", ++ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { -+ "has-flag": "^4.0.0" ++ "is-number": "^7.0.0" + }, + "engines": { -+ "node": ">=8" ++ "node": ">=8.0" + } + }, -+ "node_modules/jest-validate": { -+ "version": "29.7.0", -+ "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", -+ "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", ++ "node_modules/type-detect": { ++ "version": "4.0.8", ++ "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", ++ "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, -+ "dependencies": { -+ "@jest/types": "^29.6.3", -+ "camelcase": "^6.2.0", -+ "chalk": "^4.0.0", -+ "jest-get-type": "^29.6.3", -+ "leven": "^3.1.0", -+ "pretty-format": "^29.7.0" -+ }, + "engines": { -+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" ++ "node": ">=4" + } + }, -+ "node_modules/jest-validate/node_modules/ansi-styles": { -+ "version": "4.3.0", -+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", -+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", ++ "node_modules/type-fest": { ++ "version": "0.21.3", ++ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", ++ "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, -+ "dependencies": { -+ "color-convert": "^2.0.1" -+ }, + "engines": { -+ "node": ">=8" ++ "node": ">=10" + }, + "funding": { -+ "url": "https://github.com/chalk/ansi-styles?sponsor=1" ++ "url": "https://github.com/sponsors/sindresorhus" + } + }, -+ "node_modules/jest-validate/node_modules/camelcase": { -+ "version": "6.3.0", -+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", -+ "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", ++ "node_modules/undici-types": { ++ "version": "5.26.5", ++ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", ++ "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", ++ "dev": true ++ }, ++ "node_modules/unicode-canonical-property-names-ecmascript": { ++ "version": "2.0.0", ++ "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", ++ "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "dev": true, + "engines": { -+ "node": ">=10" -+ }, -+ "funding": { -+ "url": "https://github.com/sponsors/sindresorhus" ++ "node": ">=4" + } + }, -+ "node_modules/jest-validate/node_modules/chalk": { -+ "version": "4.1.2", -+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", -+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", ++ "node_modules/unicode-match-property-ecmascript": { ++ "version": "2.0.0", ++ "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", ++ "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dev": true, + "dependencies": { -+ "ansi-styles": "^4.1.0", -+ "supports-color": "^7.1.0" ++ "unicode-canonical-property-names-ecmascript": "^2.0.0", ++ "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { -+ "node": ">=10" ++ "node": ">=4" ++ } ++ }, ++ "node_modules/unicode-match-property-value-ecmascript": { ++ "version": "2.1.0", ++ "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", ++ "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", ++ "dev": true, ++ "engines": { ++ "node": ">=4" ++ } ++ }, ++ "node_modules/unicode-property-aliases-ecmascript": { ++ "version": "2.1.0", ++ "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", ++ "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", ++ "dev": true, ++ "engines": { ++ "node": ">=4" ++ } ++ }, ++ "node_modules/update-browserslist-db": { ++ "version": "1.1.0", ++ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", ++ "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", ++ "dev": true, ++ "funding": [ ++ { ++ "type": "opencollective", ++ "url": "https://opencollective.com/browserslist" ++ }, ++ { ++ "type": "tidelift", ++ "url": "https://tidelift.com/funding/github/npm/browserslist" ++ }, ++ { ++ "type": "github", ++ "url": "https://github.com/sponsors/ai" ++ } ++ ], ++ "dependencies": { ++ "escalade": "^3.1.2", ++ "picocolors": "^1.0.1" + }, -+ "funding": { -+ "url": "https://github.com/chalk/chalk?sponsor=1" ++ "bin": { ++ "update-browserslist-db": "cli.js" ++ }, ++ "peerDependencies": { ++ "browserslist": ">= 4.21.0" + } + }, -+ "node_modules/jest-validate/node_modules/color-convert": { -+ "version": "2.0.1", -+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", -+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", ++ "node_modules/v8-to-istanbul": { ++ "version": "9.3.0", ++ "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", ++ "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", + "dev": true, + "dependencies": { -+ "color-name": "~1.1.4" ++ "@jridgewell/trace-mapping": "^0.3.12", ++ "@types/istanbul-lib-coverage": "^2.0.1", ++ "convert-source-map": "^2.0.0" + }, + "engines": { -+ "node": ">=7.0.0" ++ "node": ">=10.12.0" + } + }, -+ "node_modules/jest-validate/node_modules/color-name": { -+ "version": "1.1.4", -+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", -+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", -+ "dev": true ++ "node_modules/viem": { ++ "version": "2.17.4", ++ "resolved": "https://registry.npmjs.org/viem/-/viem-2.17.4.tgz", ++ "integrity": "sha512-6gmBB85I7z1qt/+yPPS+i4L2jNPJqCs+SEb+26WnKVYez13svSzjYMsU9OYYlPFpQmpGSy9dV2bKW6VX68FTgg==", ++ "funding": [ ++ { ++ "type": "github", ++ "url": "https://github.com/sponsors/wevm" ++ } ++ ], ++ "dependencies": { ++ "@adraffy/ens-normalize": "1.10.0", ++ "@noble/curves": "1.4.0", ++ "@noble/hashes": "1.4.0", ++ "@scure/bip32": "1.4.0", ++ "@scure/bip39": "1.3.0", ++ "abitype": "1.0.5", ++ "isows": "1.0.4", ++ "ws": "8.17.1" ++ }, ++ "peerDependencies": { ++ "typescript": ">=5.0.4" ++ }, ++ "peerDependenciesMeta": { ++ "typescript": { ++ "optional": true ++ } ++ } + }, -+ "node_modules/jest-validate/node_modules/has-flag": { -+ "version": "4.0.0", -+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", -+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", ++ "node_modules/walker": { ++ "version": "1.0.8", ++ "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", ++ "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, -+ "engines": { -+ "node": ">=8" ++ "dependencies": { ++ "makeerror": "1.0.12" + } + }, -+ "node_modules/jest-validate/node_modules/supports-color": { -+ "version": "7.2.0", -+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", -+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", ++ "node_modules/which": { ++ "version": "2.0.2", ++ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", ++ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { -+ "has-flag": "^4.0.0" ++ "isexe": "^2.0.0" ++ }, ++ "bin": { ++ "node-which": "bin/node-which" + }, + "engines": { -+ "node": ">=8" ++ "node": ">= 8" + } + }, -+ "node_modules/jest-watcher": { -+ "version": "29.7.0", -+ "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", -+ "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", ++ "node_modules/wrap-ansi": { ++ "version": "7.0.0", ++ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", ++ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { -+ "@jest/test-result": "^29.7.0", -+ "@jest/types": "^29.6.3", -+ "@types/node": "*", -+ "ansi-escapes": "^4.2.1", -+ "chalk": "^4.0.0", -+ "emittery": "^0.13.1", -+ "jest-util": "^29.7.0", -+ "string-length": "^4.0.1" ++ "ansi-styles": "^4.0.0", ++ "string-width": "^4.1.0", ++ "strip-ansi": "^6.0.0" + }, + "engines": { -+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" ++ "node": ">=10" ++ }, ++ "funding": { ++ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, -+ "node_modules/jest-watcher/node_modules/ansi-styles": { ++ "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", @@ -22055,23 +74906,7 @@ + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, -+ "node_modules/jest-watcher/node_modules/chalk": { -+ "version": "4.1.2", -+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", -+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", -+ "dev": true, -+ "dependencies": { -+ "ansi-styles": "^4.1.0", -+ "supports-color": "^7.1.0" -+ }, -+ "engines": { -+ "node": ">=10" -+ }, -+ "funding": { -+ "url": "https://github.com/chalk/chalk?sponsor=1" -+ } -+ }, -+ "node_modules/jest-watcher/node_modules/color-convert": { ++ "node_modules/wrap-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", @@ -22083,1229 +74918,28685 @@ + "node": ">=7.0.0" + } + }, -+ "node_modules/jest-watcher/node_modules/color-name": { ++ "node_modules/wrap-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, -+ "node_modules/jest-watcher/node_modules/has-flag": { -+ "version": "4.0.0", -+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", -+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", -+ "dev": true, -+ "engines": { -+ "node": ">=8" -+ } -+ }, -+ "node_modules/jest-watcher/node_modules/supports-color": { -+ "version": "7.2.0", -+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", -+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", -+ "dev": true, -+ "dependencies": { -+ "has-flag": "^4.0.0" -+ }, -+ "engines": { -+ "node": ">=8" -+ } ++ "node_modules/wrappy": { ++ "version": "1.0.2", ++ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", ++ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", ++ "dev": true + }, -+ "node_modules/jest-worker": { -+ "version": "29.7.0", -+ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", -+ "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", ++ "node_modules/write-file-atomic": { ++ "version": "4.0.2", ++ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", ++ "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "dependencies": { -+ "@types/node": "*", -+ "jest-util": "^29.7.0", -+ "merge-stream": "^2.0.0", -+ "supports-color": "^8.0.0" ++ "imurmurhash": "^0.1.4", ++ "signal-exit": "^3.0.7" + }, + "engines": { -+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" ++ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, -+ "node_modules/jest-worker/node_modules/has-flag": { -+ "version": "4.0.0", -+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", -+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", -+ "dev": true, ++ "node_modules/ws": { ++ "version": "8.17.1", ++ "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", ++ "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "engines": { -+ "node": ">=8" ++ "node": ">=10.0.0" ++ }, ++ "peerDependencies": { ++ "bufferutil": "^4.0.1", ++ "utf-8-validate": ">=5.0.2" ++ }, ++ "peerDependenciesMeta": { ++ "bufferutil": { ++ "optional": true ++ }, ++ "utf-8-validate": { ++ "optional": true ++ } + } + }, -+ "node_modules/jest-worker/node_modules/supports-color": { -+ "version": "8.1.1", -+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", -+ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", ++ "node_modules/y18n": { ++ "version": "5.0.8", ++ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", ++ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, -+ "dependencies": { -+ "has-flag": "^4.0.0" -+ }, + "engines": { + "node": ">=10" -+ }, -+ "funding": { -+ "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, -+ "node_modules/js-tokens": { -+ "version": "4.0.0", -+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", -+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", ++ "node_modules/yallist": { ++ "version": "3.1.1", ++ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", ++ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, -+ "node_modules/js-yaml": { -+ "version": "3.14.1", -+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", -+ "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", ++ "node_modules/yargs": { ++ "version": "17.7.2", ++ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", ++ "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "dependencies": { -+ "argparse": "^1.0.7", -+ "esprima": "^4.0.0" ++ "cliui": "^8.0.1", ++ "escalade": "^3.1.1", ++ "get-caller-file": "^2.0.5", ++ "require-directory": "^2.1.1", ++ "string-width": "^4.2.3", ++ "y18n": "^5.0.5", ++ "yargs-parser": "^21.1.1" + }, -+ "bin": { -+ "js-yaml": "bin/js-yaml.js" ++ "engines": { ++ "node": ">=12" + } + }, -+ "node_modules/jsesc": { -+ "version": "2.5.2", -+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", -+ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", ++ "node_modules/yargs-parser": { ++ "version": "21.1.1", ++ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", ++ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, -+ "bin": { -+ "jsesc": "bin/jsesc" -+ }, + "engines": { -+ "node": ">=4" ++ "node": ">=12" + } + }, -+ "node_modules/json-parse-even-better-errors": { -+ "version": "2.3.1", -+ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", -+ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", -+ "dev": true -+ }, -+ "node_modules/json5": { -+ "version": "2.2.3", -+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", -+ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", ++ "node_modules/yocto-queue": { ++ "version": "0.1.0", ++ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", ++ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, -+ "bin": { -+ "json5": "lib/cli.js" ++ "engines": { ++ "node": ">=10" ++ }, ++ "funding": { ++ "url": "https://github.com/sponsors/sindresorhus" ++ } ++ } ++ } ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+22
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/celo/package.json CELO/op-e2e/celo/package.json +new file mode 100644 +index 0000000000000000000000000000000000000000..0026da775c4f3d242af7554e491c5831303b5303 +--- /dev/null ++++ CELO/op-e2e/celo/package.json +@@ -0,0 +1,22 @@ ++{ ++ "name": "testsuite", ++ "version": "1.0.0", ++ "description": "", ++ "type": "module", ++ "main": "dist/test.js", ++ "scripts": { ++ "test": "jest tests --detectOpenHandles" ++ }, ++ "author": "Celo Labs Inc.", ++ "license": "ISC", ++ "dependencies": { ++ "reverse-mirage": "^1.1.0", ++ "viem": "^2.13.1" ++ }, ++ "devDependencies": { ++ "@babel/core": "^7.24.7", ++ "@babel/preset-env": "^7.24.7", ++ "babel-jest": "^29.7.0", ++ "jest": "^29.7.0" ++ } ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+56
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/celo/run_all_tests.sh CELO/op-e2e/celo/run_all_tests.sh +new file mode 100755 +index 0000000000000000000000000000000000000000..ecafe64b51fc6603594bd0640d5a71afcdd422fa +--- /dev/null ++++ CELO/op-e2e/celo/run_all_tests.sh +@@ -0,0 +1,56 @@ ++#!/bin/bash ++#shellcheck disable=SC1091 ++set -eo pipefail ++ ++SCRIPT_DIR=$(readlink -f "$(dirname "$0")") ++TEST_GLOB=$1 ++spawn_devnet=${SPAWN_DEVNET:-true} ++ ++if [[ $spawn_devnet != false ]]; then ++ ## Start geth ++ cd "$SCRIPT_DIR/../.." || exit 1 ++ trap 'cd "$SCRIPT_DIR/../.." && make devnet-down' EXIT # kill bg job at exit ++ DEVNET_L2OO=true DEVNET_CELO=true make devnet-up ++fi ++ ++cd "$SCRIPT_DIR" || exit 1 ++source "$SCRIPT_DIR/shared.sh" ++ ++# Wait for geth to be ready ++for _ in {1..10}; do ++ if cast block &>/dev/null; then ++ echo geth ready ++ break ++ fi ++ sleep 0.2 ++done ++ ++## Run tests ++echo Start tests ++failures=0 ++tests=0 ++for f in test_*"$TEST_GLOB"*; do ++ echo -e "\nRun $f" ++ if "./$f"; then ++ tput setaf 2 || true ++ echo "PASS $f" ++ else ++ tput setaf 1 || true ++ echo "FAIL $f ❌" ++ ((failures++)) || true ++ fi ++ tput sgr0 || true ++ ((tests++)) || true ++done ++ ++## Final summary ++echo ++if [[ $failures -eq 0 ]]; then ++ tput setaf 2 || true ++ echo All tests succeeded! ++else ++ tput setaf 1 || true ++ echo "$failures/$tests" failed. ++fi ++tput sgr0 || true ++exit "$failures"
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+12
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/celo/shared.sh CELO/op-e2e/celo/shared.sh +new file mode 100644 +index 0000000000000000000000000000000000000000..92e9be7be28ec1d52cd4b29af0204a1a8fa6791e +--- /dev/null ++++ CELO/op-e2e/celo/shared.sh +@@ -0,0 +1,12 @@ ++#!/bin/bash ++#shellcheck disable=SC2034 # unused vars make sense in a shared file ++ ++export ETH_RPC_URL=http://localhost:9545 ++export ETH_RPC_URL_L1=http://localhost:8545 ++ ++export ACC_PRIVKEY=ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 ++ACC_ADDR=$(cast wallet address $ACC_PRIVKEY) ++export ACC_ADDR ++export REGISTRY_ADDR=0x000000000000000000000000000000000000ce10 ++export TOKEN_ADDR=0x471ece3750da237f93b8e339c536989b8978a438 ++export FEE_CURRENCY_DIRECTORY_ADDR=0x71FFbD48E34bdD5a87c3c683E866dc63b8B2a685
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+658
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/celo/src/OptimismPortal.js CELO/op-e2e/celo/src/OptimismPortal.js +new file mode 100644 +index 0000000000000000000000000000000000000000..80b02f38341420bc72c43c39150aaf591dfa09fa +--- /dev/null ++++ CELO/op-e2e/celo/src/OptimismPortal.js +@@ -0,0 +1,658 @@ ++export const OptimismPortalABI = [ ++ { ++ type: 'constructor', ++ inputs: [], ++ stateMutability: 'nonpayable', ++ }, ++ { ++ type: 'receive', ++ stateMutability: 'payable', ++ }, ++ { ++ type: 'function', ++ name: 'balance', ++ inputs: [], ++ outputs: [ ++ { ++ name: '', ++ type: 'uint256', ++ internalType: 'uint256', ++ }, ++ ], ++ stateMutability: 'view', ++ }, ++ { ++ type: 'function', ++ name: 'depositERC20Transaction', ++ inputs: [ ++ { ++ name: '_to', ++ type: 'address', ++ internalType: 'address', ++ }, ++ { ++ name: '_mint', ++ type: 'uint256', ++ internalType: 'uint256', ++ }, ++ { ++ name: '_value', ++ type: 'uint256', ++ internalType: 'uint256', ++ }, ++ { ++ name: '_gasLimit', ++ type: 'uint64', ++ internalType: 'uint64', ++ }, ++ { ++ name: '_isCreation', ++ type: 'bool', ++ internalType: 'bool', ++ }, ++ { ++ name: '_data', ++ type: 'bytes', ++ internalType: 'bytes', ++ }, ++ ], ++ outputs: [], ++ stateMutability: 'nonpayable', ++ }, ++ { ++ type: 'function', ++ name: 'depositTransaction', ++ inputs: [ ++ { ++ name: '_to', ++ type: 'address', ++ internalType: 'address', ++ }, ++ { ++ name: '_value', ++ type: 'uint256', ++ internalType: 'uint256', ++ }, ++ { ++ name: '_gasLimit', ++ type: 'uint64', ++ internalType: 'uint64', ++ }, ++ { ++ name: '_isCreation', ++ type: 'bool', ++ internalType: 'bool', ++ }, ++ { ++ name: '_data', ++ type: 'bytes', ++ internalType: 'bytes', ++ }, ++ ], ++ outputs: [], ++ stateMutability: 'payable', ++ }, ++ { ++ type: 'function', ++ name: 'donateETH', ++ inputs: [], ++ outputs: [], ++ stateMutability: 'payable', ++ }, ++ { ++ type: 'function', ++ name: 'finalizeWithdrawalTransaction', ++ inputs: [ ++ { ++ name: '_tx', ++ type: 'tuple', ++ internalType: 'struct Types.WithdrawalTransaction', ++ components: [ ++ { ++ name: 'nonce', ++ type: 'uint256', ++ internalType: 'uint256', ++ }, ++ { ++ name: 'sender', ++ type: 'address', ++ internalType: 'address', ++ }, ++ { ++ name: 'target', ++ type: 'address', ++ internalType: 'address', ++ }, ++ { ++ name: 'value', ++ type: 'uint256', ++ internalType: 'uint256', ++ }, ++ { ++ name: 'gasLimit', ++ type: 'uint256', ++ internalType: 'uint256', ++ }, ++ { ++ name: 'data', ++ type: 'bytes', ++ internalType: 'bytes', ++ }, ++ ], ++ }, ++ ], ++ outputs: [], ++ stateMutability: 'nonpayable', ++ }, ++ { ++ type: 'function', ++ name: 'finalizedWithdrawals', ++ inputs: [ ++ { ++ name: '', ++ type: 'bytes32', ++ internalType: 'bytes32', ++ }, ++ ], ++ outputs: [ ++ { ++ name: '', ++ type: 'bool', ++ internalType: 'bool', ++ }, ++ ], ++ stateMutability: 'view', ++ }, ++ { ++ type: 'function', ++ name: 'guardian', ++ inputs: [], ++ outputs: [ ++ { ++ name: '', ++ type: 'address', ++ internalType: 'address', + }, -+ "engines": { -+ "node": ">=6" -+ } -+ }, -+ "node_modules/kleur": { -+ "version": "3.0.3", -+ "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", -+ "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", -+ "dev": true, -+ "engines": { -+ "node": ">=6" -+ } -+ }, -+ "node_modules/leven": { -+ "version": "3.1.0", -+ "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", -+ "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", -+ "dev": true, -+ "engines": { -+ "node": ">=6" -+ } -+ }, -+ "node_modules/lines-and-columns": { -+ "version": "1.2.4", -+ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", -+ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", -+ "dev": true -+ }, -+ "node_modules/locate-path": { -+ "version": "5.0.0", -+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", -+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", -+ "dev": true, -+ "dependencies": { -+ "p-locate": "^4.1.0" ++ ], ++ stateMutability: 'view', ++ }, ++ { ++ type: 'function', ++ name: 'initialize', ++ inputs: [ ++ { ++ name: '_l2Oracle', ++ type: 'address', ++ internalType: 'contract L2OutputOracle', + }, -+ "engines": { -+ "node": ">=8" -+ } -+ }, -+ "node_modules/lodash.debounce": { -+ "version": "4.0.8", -+ "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", -+ "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", -+ "dev": true -+ }, -+ "node_modules/lru-cache": { -+ "version": "5.1.1", -+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", -+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", -+ "dev": true, -+ "dependencies": { -+ "yallist": "^3.0.2" -+ } -+ }, -+ "node_modules/make-dir": { -+ "version": "4.0.0", -+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", -+ "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", -+ "dev": true, -+ "dependencies": { -+ "semver": "^7.5.3" ++ { ++ name: '_systemConfig', ++ type: 'address', ++ internalType: 'contract SystemConfig', + }, -+ "engines": { -+ "node": ">=10" ++ { ++ name: '_superchainConfig', ++ type: 'address', ++ internalType: 'contract SuperchainConfig', + }, -+ "funding": { -+ "url": "https://github.com/sponsors/sindresorhus" -+ } -+ }, -+ "node_modules/make-dir/node_modules/semver": { -+ "version": "7.6.3", -+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", -+ "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", -+ "dev": true, -+ "bin": { -+ "semver": "bin/semver.js" ++ { ++ name: '_initialBalance', ++ type: 'uint256', ++ internalType: 'uint256', + }, -+ "engines": { -+ "node": ">=10" -+ } -+ }, -+ "node_modules/makeerror": { -+ "version": "1.0.12", -+ "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", -+ "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", -+ "dev": true, -+ "dependencies": { -+ "tmpl": "1.0.5" -+ } -+ }, -+ "node_modules/merge-stream": { -+ "version": "2.0.0", -+ "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", -+ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", -+ "dev": true -+ }, -+ "node_modules/micromatch": { -+ "version": "4.0.7", -+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", -+ "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", -+ "dev": true, -+ "dependencies": { -+ "braces": "^3.0.3", -+ "picomatch": "^2.3.1" ++ ], ++ outputs: [], ++ stateMutability: 'nonpayable', ++ }, ++ { ++ type: 'function', ++ name: 'isOutputFinalized', ++ inputs: [ ++ { ++ name: '_l2OutputIndex', ++ type: 'uint256', ++ internalType: 'uint256', + }, -+ "engines": { -+ "node": ">=8.6" -+ } -+ }, -+ "node_modules/mimic-fn": { -+ "version": "2.1.0", -+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", -+ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", -+ "dev": true, -+ "engines": { -+ "node": ">=6" -+ } -+ }, -+ "node_modules/minimatch": { -+ "version": "3.1.2", -+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", -+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", -+ "dev": true, -+ "dependencies": { -+ "brace-expansion": "^1.1.7" ++ ], ++ outputs: [ ++ { ++ name: '', ++ type: 'bool', ++ internalType: 'bool', + }, -+ "engines": { -+ "node": "*" -+ } -+ }, -+ "node_modules/ms": { -+ "version": "2.1.2", -+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", -+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", -+ "dev": true -+ }, -+ "node_modules/natural-compare": { -+ "version": "1.4.0", -+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", -+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", -+ "dev": true -+ }, -+ "node_modules/node-int64": { -+ "version": "0.4.0", -+ "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", -+ "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", -+ "dev": true -+ }, -+ "node_modules/node-releases": { -+ "version": "2.0.17", -+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.17.tgz", -+ "integrity": "sha512-Ww6ZlOiEQfPfXM45v17oabk77Z7mg5bOt7AjDyzy7RjK9OrLrLC8dyZQoAPEOtFX9SaNf1Tdvr5gRJWdTJj7GA==", -+ "dev": true -+ }, -+ "node_modules/normalize-path": { -+ "version": "3.0.0", -+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", -+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", -+ "dev": true, -+ "engines": { -+ "node": ">=0.10.0" -+ } -+ }, -+ "node_modules/npm-run-path": { -+ "version": "4.0.1", -+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", -+ "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", -+ "dev": true, -+ "dependencies": { -+ "path-key": "^3.0.0" ++ ], ++ stateMutability: 'view', ++ }, ++ { ++ type: 'function', ++ name: 'l2Oracle', ++ inputs: [], ++ outputs: [ ++ { ++ name: '', ++ type: 'address', ++ internalType: 'contract L2OutputOracle', + }, -+ "engines": { -+ "node": ">=8" -+ } -+ }, -+ "node_modules/once": { -+ "version": "1.4.0", -+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", -+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", -+ "dev": true, -+ "dependencies": { -+ "wrappy": "1" -+ } -+ }, -+ "node_modules/onetime": { -+ "version": "5.1.2", -+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", -+ "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", -+ "dev": true, -+ "dependencies": { -+ "mimic-fn": "^2.1.0" ++ ], ++ stateMutability: 'view', ++ }, ++ { ++ type: 'function', ++ name: 'l2Sender', ++ inputs: [], ++ outputs: [ ++ { ++ name: '', ++ type: 'address', ++ internalType: 'address', + }, -+ "engines": { -+ "node": ">=6" ++ ], ++ stateMutability: 'view', ++ }, ++ { ++ type: 'function', ++ name: 'minimumGasLimit', ++ inputs: [ ++ { ++ name: '_byteCount', ++ type: 'uint64', ++ internalType: 'uint64', + }, -+ "funding": { -+ "url": "https://github.com/sponsors/sindresorhus" -+ } -+ }, -+ "node_modules/p-limit": { -+ "version": "3.1.0", -+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", -+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", -+ "dev": true, -+ "dependencies": { -+ "yocto-queue": "^0.1.0" ++ ], ++ outputs: [ ++ { ++ name: '', ++ type: 'uint64', ++ internalType: 'uint64', + }, -+ "engines": { -+ "node": ">=10" ++ ], ++ stateMutability: 'pure', ++ }, ++ { ++ type: 'function', ++ name: 'params', ++ inputs: [], ++ outputs: [ ++ { ++ name: 'prevBaseFee', ++ type: 'uint128', ++ internalType: 'uint128', + }, -+ "funding": { -+ "url": "https://github.com/sponsors/sindresorhus" -+ } -+ }, -+ "node_modules/p-locate": { -+ "version": "4.1.0", -+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", -+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", -+ "dev": true, -+ "dependencies": { -+ "p-limit": "^2.2.0" ++ { ++ name: 'prevBoughtGas', ++ type: 'uint64', ++ internalType: 'uint64', + }, -+ "engines": { -+ "node": ">=8" -+ } -+ }, -+ "node_modules/p-locate/node_modules/p-limit": { -+ "version": "2.3.0", -+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", -+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", -+ "dev": true, -+ "dependencies": { -+ "p-try": "^2.0.0" ++ { ++ name: 'prevBlockNum', ++ type: 'uint64', ++ internalType: 'uint64', + }, -+ "engines": { -+ "node": ">=6" ++ ], ++ stateMutability: 'view', ++ }, ++ { ++ type: 'function', ++ name: 'paused', ++ inputs: [], ++ outputs: [ ++ { ++ name: 'paused_', ++ type: 'bool', ++ internalType: 'bool', + }, -+ "funding": { -+ "url": "https://github.com/sponsors/sindresorhus" -+ } -+ }, -+ "node_modules/p-try": { -+ "version": "2.2.0", -+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", -+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", -+ "dev": true, -+ "engines": { -+ "node": ">=6" -+ } -+ }, -+ "node_modules/parse-json": { -+ "version": "5.2.0", -+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", -+ "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", -+ "dev": true, -+ "dependencies": { -+ "@babel/code-frame": "^7.0.0", -+ "error-ex": "^1.3.1", -+ "json-parse-even-better-errors": "^2.3.0", -+ "lines-and-columns": "^1.1.6" ++ ], ++ stateMutability: 'view', ++ }, ++ { ++ type: 'function', ++ name: 'proveWithdrawalTransaction', ++ inputs: [ ++ { ++ name: '_tx', ++ type: 'tuple', ++ internalType: 'struct Types.WithdrawalTransaction', ++ components: [ ++ { ++ name: 'nonce', ++ type: 'uint256', ++ internalType: 'uint256', ++ }, ++ { ++ name: 'sender', ++ type: 'address', ++ internalType: 'address', ++ }, ++ { ++ name: 'target', ++ type: 'address', ++ internalType: 'address', ++ }, ++ { ++ name: 'value', ++ type: 'uint256', ++ internalType: 'uint256', ++ }, ++ { ++ name: 'gasLimit', ++ type: 'uint256', ++ internalType: 'uint256', ++ }, ++ { ++ name: 'data', ++ type: 'bytes', ++ internalType: 'bytes', ++ }, ++ ], + }, -+ "engines": { -+ "node": ">=8" ++ { ++ name: '_l2OutputIndex', ++ type: 'uint256', ++ internalType: 'uint256', + }, -+ "funding": { -+ "url": "https://github.com/sponsors/sindresorhus" -+ } -+ }, -+ "node_modules/path-exists": { -+ "version": "4.0.0", -+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", -+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", -+ "dev": true, -+ "engines": { -+ "node": ">=8" -+ } -+ }, -+ "node_modules/path-is-absolute": { -+ "version": "1.0.1", -+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", -+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", -+ "dev": true, -+ "engines": { -+ "node": ">=0.10.0" -+ } -+ }, -+ "node_modules/path-key": { -+ "version": "3.1.1", -+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", -+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", -+ "dev": true, -+ "engines": { -+ "node": ">=8" -+ } -+ }, -+ "node_modules/path-parse": { -+ "version": "1.0.7", -+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", -+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", -+ "dev": true -+ }, -+ "node_modules/picocolors": { -+ "version": "1.0.1", -+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", -+ "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", -+ "dev": true -+ }, -+ "node_modules/picomatch": { -+ "version": "2.3.1", -+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", -+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", -+ "dev": true, -+ "engines": { -+ "node": ">=8.6" ++ { ++ name: '_outputRootProof', ++ type: 'tuple', ++ internalType: 'struct Types.OutputRootProof', ++ components: [ ++ { ++ name: 'version', ++ type: 'bytes32', ++ internalType: 'bytes32', ++ }, ++ { ++ name: 'stateRoot', ++ type: 'bytes32', ++ internalType: 'bytes32', ++ }, ++ { ++ name: 'messagePasserStorageRoot', ++ type: 'bytes32', ++ internalType: 'bytes32', ++ }, ++ { ++ name: 'latestBlockhash', ++ type: 'bytes32', ++ internalType: 'bytes32', ++ }, ++ ], + }, -+ "funding": { -+ "url": "https://github.com/sponsors/jonschlinkert" -+ } -+ }, -+ "node_modules/pirates": { -+ "version": "4.0.6", -+ "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", -+ "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", -+ "dev": true, -+ "engines": { -+ "node": ">= 6" -+ } -+ }, -+ "node_modules/pkg-dir": { -+ "version": "4.2.0", -+ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", -+ "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", -+ "dev": true, -+ "dependencies": { -+ "find-up": "^4.0.0" ++ { ++ name: '_withdrawalProof', ++ type: 'bytes[]', ++ internalType: 'bytes[]', + }, -+ "engines": { -+ "node": ">=8" -+ } -+ }, -+ "node_modules/prettier": { -+ "version": "3.3.3", -+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", -+ "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", -+ "dev": true, -+ "bin": { -+ "prettier": "bin/prettier.cjs" ++ ], ++ outputs: [], ++ stateMutability: 'nonpayable', ++ }, ++ { ++ type: 'function', ++ name: 'provenWithdrawals', ++ inputs: [ ++ { ++ name: '', ++ type: 'bytes32', ++ internalType: 'bytes32', + }, -+ "engines": { -+ "node": ">=14" ++ ], ++ outputs: [ ++ { ++ name: 'outputRoot', ++ type: 'bytes32', ++ internalType: 'bytes32', + }, -+ "funding": { -+ "url": "https://github.com/prettier/prettier?sponsor=1" -+ } -+ }, -+ "node_modules/pretty-format": { -+ "version": "29.7.0", -+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", -+ "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", -+ "dev": true, -+ "dependencies": { -+ "@jest/schemas": "^29.6.3", -+ "ansi-styles": "^5.0.0", -+ "react-is": "^18.0.0" ++ { ++ name: 'timestamp', ++ type: 'uint128', ++ internalType: 'uint128', + }, -+ "engines": { -+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" -+ } -+ }, -+ "node_modules/pretty-format/node_modules/ansi-styles": { -+ "version": "5.2.0", -+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", -+ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", -+ "dev": true, -+ "engines": { -+ "node": ">=10" ++ { ++ name: 'l2OutputIndex', ++ type: 'uint128', ++ internalType: 'uint128', + }, -+ "funding": { -+ "url": "https://github.com/chalk/ansi-styles?sponsor=1" -+ } -+ }, -+ "node_modules/prompts": { -+ "version": "2.4.2", -+ "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", -+ "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", -+ "dev": true, -+ "dependencies": { -+ "kleur": "^3.0.3", -+ "sisteransi": "^1.0.5" ++ ], ++ stateMutability: 'view', ++ }, ++ { ++ type: 'function', ++ name: 'setGasPayingToken', ++ inputs: [ ++ { ++ name: '_token', ++ type: 'address', ++ internalType: 'address', + }, -+ "engines": { -+ "node": ">= 6" -+ } -+ }, -+ "node_modules/pure-rand": { -+ "version": "6.1.0", -+ "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", -+ "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", -+ "dev": true, -+ "funding": [ -+ { -+ "type": "individual", -+ "url": "https://github.com/sponsors/dubzzz" -+ }, -+ { -+ "type": "opencollective", -+ "url": "https://opencollective.com/fast-check" -+ } -+ ] -+ }, -+ "node_modules/react-is": { -+ "version": "18.3.1", -+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", -+ "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", -+ "dev": true -+ }, -+ "node_modules/regenerate": { -+ "version": "1.4.2", -+ "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", -+ "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", -+ "dev": true -+ }, -+ "node_modules/regenerate-unicode-properties": { -+ "version": "10.1.1", -+ "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz", -+ "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==", -+ "dev": true, -+ "dependencies": { -+ "regenerate": "^1.4.2" ++ { ++ name: '_decimals', ++ type: 'uint8', ++ internalType: 'uint8', + }, -+ "engines": { -+ "node": ">=4" -+ } -+ }, -+ "node_modules/regenerator-runtime": { -+ "version": "0.14.1", -+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", -+ "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", -+ "dev": true -+ }, -+ "node_modules/regenerator-transform": { -+ "version": "0.15.2", -+ "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", -+ "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", -+ "dev": true, -+ "dependencies": { -+ "@babel/runtime": "^7.8.4" -+ } -+ }, -+ "node_modules/regexpu-core": { -+ "version": "5.3.2", -+ "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", -+ "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", -+ "dev": true, -+ "dependencies": { -+ "@babel/regjsgen": "^0.8.0", -+ "regenerate": "^1.4.2", -+ "regenerate-unicode-properties": "^10.1.0", -+ "regjsparser": "^0.9.1", -+ "unicode-match-property-ecmascript": "^2.0.0", -+ "unicode-match-property-value-ecmascript": "^2.1.0" ++ { ++ name: '_name', ++ type: 'bytes32', ++ internalType: 'bytes32', + }, -+ "engines": { -+ "node": ">=4" -+ } -+ }, -+ "node_modules/regjsparser": { -+ "version": "0.9.1", -+ "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", -+ "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", -+ "dev": true, -+ "dependencies": { -+ "jsesc": "~0.5.0" ++ { ++ name: '_symbol', ++ type: 'bytes32', ++ internalType: 'bytes32', + }, -+ "bin": { -+ "regjsparser": "bin/parser" -+ } -+ }, -+ "node_modules/regjsparser/node_modules/jsesc": { -+ "version": "0.5.0", -+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", -+ "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", -+ "dev": true, -+ "bin": { -+ "jsesc": "bin/jsesc" -+ } -+ }, -+ "node_modules/require-directory": { -+ "version": "2.1.1", -+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", -+ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", -+ "dev": true, -+ "engines": { -+ "node": ">=0.10.0" -+ } -+ }, -+ "node_modules/resolve": { -+ "version": "1.22.8", -+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", -+ "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", -+ "dev": true, -+ "dependencies": { -+ "is-core-module": "^2.13.0", -+ "path-parse": "^1.0.7", -+ "supports-preserve-symlinks-flag": "^1.0.0" ++ ], ++ outputs: [], ++ stateMutability: 'nonpayable', ++ }, ++ { ++ type: 'function', ++ name: 'superchainConfig', ++ inputs: [], ++ outputs: [ ++ { ++ name: '', ++ type: 'address', ++ internalType: 'contract SuperchainConfig', + }, -+ "bin": { -+ "resolve": "bin/resolve" ++ ], ++ stateMutability: 'view', ++ }, ++ { ++ type: 'function', ++ name: 'systemConfig', ++ inputs: [], ++ outputs: [ ++ { ++ name: '', ++ type: 'address', ++ internalType: 'contract SystemConfig', + }, -+ "funding": { -+ "url": "https://github.com/sponsors/ljharb" -+ } -+ }, -+ "node_modules/resolve-cwd": { -+ "version": "3.0.0", -+ "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", -+ "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", -+ "dev": true, -+ "dependencies": { -+ "resolve-from": "^5.0.0" ++ ], ++ stateMutability: 'view', ++ }, ++ { ++ type: 'function', ++ name: 'version', ++ inputs: [], ++ outputs: [ ++ { ++ name: '', ++ type: 'string', ++ internalType: 'string', + }, -+ "engines": { -+ "node": ">=8" -+ } -+ }, -+ "node_modules/resolve-from": { -+ "version": "5.0.0", -+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", -+ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", -+ "dev": true, -+ "engines": { -+ "node": ">=8" -+ } -+ }, -+ "node_modules/resolve.exports": { -+ "version": "2.0.2", -+ "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", -+ "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", -+ "dev": true, -+ "engines": { -+ "node": ">=10" -+ } -+ }, -+ "node_modules/reverse-mirage": { -+ "version": "1.1.0", -+ "resolved": "https://registry.npmjs.org/reverse-mirage/-/reverse-mirage-1.1.0.tgz", -+ "integrity": "sha512-cA1O7GR0pn4rMFoaiEG7Skms9GenuW91DtCxeR5hphyNhH90eowV4RmUVlVPVS11CPkezm/iUjnCfmxlHri05w==", -+ "peerDependencies": { -+ "typescript": ">=5.0.4", -+ "viem": ">=2" ++ ], ++ stateMutability: 'view', ++ }, ++ { ++ type: 'event', ++ name: 'Initialized', ++ inputs: [ ++ { ++ name: 'version', ++ type: 'uint8', ++ indexed: false, ++ internalType: 'uint8', + }, -+ "peerDependenciesMeta": { -+ "typescript": { -+ "optional": true -+ } -+ } -+ }, -+ "node_modules/semver": { -+ "version": "6.3.1", -+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", -+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", -+ "dev": true, -+ "bin": { -+ "semver": "bin/semver.js" -+ } -+ }, -+ "node_modules/shebang-command": { -+ "version": "2.0.0", -+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", -+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", -+ "dev": true, -+ "dependencies": { -+ "shebang-regex": "^3.0.0" ++ ], ++ anonymous: false, ++ }, ++ { ++ type: 'event', ++ name: 'TransactionDeposited', ++ inputs: [ ++ { ++ name: 'from', ++ type: 'address', ++ indexed: true, ++ internalType: 'address', + }, -+ "engines": { -+ "node": ">=8" -+ } -+ }, -+ "node_modules/shebang-regex": { -+ "version": "3.0.0", -+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", -+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", -+ "dev": true, -+ "engines": { -+ "node": ">=8" -+ } -+ }, -+ "node_modules/signal-exit": { -+ "version": "3.0.7", -+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", -+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", -+ "dev": true -+ }, -+ "node_modules/sisteransi": { -+ "version": "1.0.5", -+ "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", -+ "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", -+ "dev": true -+ }, -+ "node_modules/slash": { -+ "version": "3.0.0", -+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", -+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", -+ "dev": true, -+ "engines": { -+ "node": ">=8" -+ } -+ }, -+ "node_modules/source-map": { -+ "version": "0.6.1", -+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", -+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", -+ "dev": true, -+ "engines": { -+ "node": ">=0.10.0" -+ } -+ }, -+ "node_modules/source-map-support": { -+ "version": "0.5.13", -+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", -+ "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", -+ "dev": true, -+ "dependencies": { -+ "buffer-from": "^1.0.0", -+ "source-map": "^0.6.0" -+ } -+ }, -+ "node_modules/sprintf-js": { -+ "version": "1.0.3", -+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", -+ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", -+ "dev": true -+ }, -+ "node_modules/stack-utils": { -+ "version": "2.0.6", -+ "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", -+ "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", -+ "dev": true, -+ "dependencies": { -+ "escape-string-regexp": "^2.0.0" ++ { ++ name: 'to', ++ type: 'address', ++ indexed: true, ++ internalType: 'address', + }, -+ "engines": { -+ "node": ">=10" -+ } -+ }, -+ "node_modules/stack-utils/node_modules/escape-string-regexp": { -+ "version": "2.0.0", -+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", -+ "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", -+ "dev": true, -+ "engines": { -+ "node": ">=8" -+ } -+ }, -+ "node_modules/string-length": { -+ "version": "4.0.2", -+ "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", -+ "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", -+ "dev": true, -+ "dependencies": { -+ "char-regex": "^1.0.2", -+ "strip-ansi": "^6.0.0" ++ { ++ name: 'version', ++ type: 'uint256', ++ indexed: true, ++ internalType: 'uint256', + }, -+ "engines": { -+ "node": ">=10" -+ } -+ }, -+ "node_modules/string-width": { -+ "version": "4.2.3", -+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", -+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", -+ "dev": true, -+ "dependencies": { -+ "emoji-regex": "^8.0.0", -+ "is-fullwidth-code-point": "^3.0.0", -+ "strip-ansi": "^6.0.1" ++ { ++ name: 'opaqueData', ++ type: 'bytes', ++ indexed: false, ++ internalType: 'bytes', + }, -+ "engines": { -+ "node": ">=8" -+ } -+ }, -+ "node_modules/strip-ansi": { -+ "version": "6.0.1", -+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", -+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", -+ "dev": true, -+ "dependencies": { -+ "ansi-regex": "^5.0.1" ++ ], ++ anonymous: false, ++ }, ++ { ++ type: 'event', ++ name: 'WithdrawalFinalized', ++ inputs: [ ++ { ++ name: 'withdrawalHash', ++ type: 'bytes32', ++ indexed: true, ++ internalType: 'bytes32', + }, -+ "engines": { -+ "node": ">=8" -+ } -+ }, -+ "node_modules/strip-bom": { -+ "version": "4.0.0", -+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", -+ "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", -+ "dev": true, -+ "engines": { -+ "node": ">=8" -+ } -+ }, -+ "node_modules/strip-final-newline": { -+ "version": "2.0.0", -+ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", -+ "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", -+ "dev": true, -+ "engines": { -+ "node": ">=6" -+ } -+ }, -+ "node_modules/strip-json-comments": { -+ "version": "3.1.1", -+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", -+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", -+ "dev": true, -+ "engines": { -+ "node": ">=8" ++ { ++ name: 'success', ++ type: 'bool', ++ indexed: false, ++ internalType: 'bool', ++ }, ++ ], ++ anonymous: false, ++ }, ++ { ++ type: 'event', ++ name: 'WithdrawalProven', ++ inputs: [ ++ { ++ name: 'withdrawalHash', ++ type: 'bytes32', ++ indexed: true, ++ internalType: 'bytes32', + }, -+ "funding": { -+ "url": "https://github.com/sponsors/sindresorhus" -+ } -+ }, -+ "node_modules/supports-color": { -+ "version": "5.5.0", -+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", -+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", -+ "dev": true, -+ "dependencies": { -+ "has-flag": "^3.0.0" ++ { ++ name: 'from', ++ type: 'address', ++ indexed: true, ++ internalType: 'address', + }, -+ "engines": { -+ "node": ">=4" -+ } -+ }, -+ "node_modules/supports-preserve-symlinks-flag": { -+ "version": "1.0.0", -+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", -+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", -+ "dev": true, -+ "engines": { -+ "node": ">= 0.4" ++ { ++ name: 'to', ++ type: 'address', ++ indexed: true, ++ internalType: 'address', + }, -+ "funding": { -+ "url": "https://github.com/sponsors/ljharb" -+ } -+ }, -+ "node_modules/test-exclude": { -+ "version": "6.0.0", -+ "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", -+ "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", -+ "dev": true, -+ "dependencies": { -+ "@istanbuljs/schema": "^0.1.2", -+ "glob": "^7.1.4", -+ "minimatch": "^3.0.4" ++ ], ++ anonymous: false, ++ }, ++ { ++ type: 'error', ++ name: 'BadTarget', ++ inputs: [], ++ }, ++ { ++ type: 'error', ++ name: 'CallPaused', ++ inputs: [], ++ }, ++ { ++ type: 'error', ++ name: 'ContentLengthMismatch', ++ inputs: [], ++ }, ++ { ++ type: 'error', ++ name: 'EmptyItem', ++ inputs: [], ++ }, ++ { ++ type: 'error', ++ name: 'GasEstimation', ++ inputs: [], ++ }, ++ { ++ type: 'error', ++ name: 'InvalidDataRemainder', ++ inputs: [], ++ }, ++ { ++ type: 'error', ++ name: 'InvalidHeader', ++ inputs: [], ++ }, ++ { ++ type: 'error', ++ name: 'LargeCalldata', ++ inputs: [], ++ }, ++ { ++ type: 'error', ++ name: 'NoValue', ++ inputs: [], ++ }, ++ { ++ type: 'error', ++ name: 'NonReentrant', ++ inputs: [], ++ }, ++ { ++ type: 'error', ++ name: 'OnlyCustomGasToken', ++ inputs: [], ++ }, ++ { ++ type: 'error', ++ name: 'OutOfGas', ++ inputs: [], ++ }, ++ { ++ type: 'error', ++ name: 'SmallGasLimit', ++ inputs: [], ++ }, ++ { ++ type: 'error', ++ name: 'TransferFailed', ++ inputs: [], ++ }, ++ { ++ type: 'error', ++ name: 'Unauthorized', ++ inputs: [], ++ }, ++ { ++ type: 'error', ++ name: 'UnexpectedList', ++ inputs: [], ++ }, ++ { ++ type: 'error', ++ name: 'UnexpectedString', ++ inputs: [], ++ }, ++]
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+66
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/celo/src/chain.js CELO/op-e2e/celo/src/chain.js +new file mode 100644 +index 0000000000000000000000000000000000000000..6d5ec9e73ea594fb39c1cd43a53705040db903f6 +--- /dev/null ++++ CELO/op-e2e/celo/src/chain.js +@@ -0,0 +1,66 @@ ++import { chainConfig } from 'viem/op-stack' ++import { defineChain } from 'viem' ++ ++export function makeChainConfigs(l1ChainID, l2ChainID, contractAddresses) { ++ console.log(process.env) ++ return { ++ l2: defineChain({ ++ formatters: { ++ ...chainConfig.formatters, + }, -+ "engines": { -+ "node": ">=8" -+ } -+ }, -+ "node_modules/tmpl": { -+ "version": "1.0.5", -+ "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", -+ "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", -+ "dev": true -+ }, -+ "node_modules/to-fast-properties": { -+ "version": "2.0.0", -+ "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", -+ "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", -+ "dev": true, -+ "engines": { -+ "node": ">=4" -+ } -+ }, -+ "node_modules/to-regex-range": { -+ "version": "5.0.1", -+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", -+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", -+ "dev": true, -+ "dependencies": { -+ "is-number": "^7.0.0" ++ serializers: { ++ ...chainConfig.serializers, + }, -+ "engines": { -+ "node": ">=8.0" -+ } -+ }, -+ "node_modules/type-detect": { -+ "version": "4.0.8", -+ "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", -+ "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", -+ "dev": true, -+ "engines": { -+ "node": ">=4" -+ } -+ }, -+ "node_modules/type-fest": { -+ "version": "0.21.3", -+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", -+ "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", -+ "dev": true, -+ "engines": { -+ "node": ">=10" ++ id: l2ChainID, ++ name: 'Celo', ++ nativeCurrency: { ++ decimals: 18, ++ name: 'Celo - native currency', ++ symbol: 'CELO', + }, -+ "funding": { -+ "url": "https://github.com/sponsors/sindresorhus" -+ } -+ }, -+ "node_modules/undici-types": { -+ "version": "5.26.5", -+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", -+ "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", -+ "dev": true -+ }, -+ "node_modules/unicode-canonical-property-names-ecmascript": { -+ "version": "2.0.0", -+ "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", -+ "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", -+ "dev": true, -+ "engines": { -+ "node": ">=4" -+ } -+ }, -+ "node_modules/unicode-match-property-ecmascript": { -+ "version": "2.0.0", -+ "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", -+ "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", -+ "dev": true, -+ "dependencies": { -+ "unicode-canonical-property-names-ecmascript": "^2.0.0", -+ "unicode-property-aliases-ecmascript": "^2.0.0" ++ rpcUrls: { ++ default: { ++ http: [process.env.ETH_RPC_URL], ++ }, + }, -+ "engines": { -+ "node": ">=4" -+ } -+ }, -+ "node_modules/unicode-match-property-value-ecmascript": { -+ "version": "2.1.0", -+ "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", -+ "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", -+ "dev": true, -+ "engines": { -+ "node": ">=4" -+ } -+ }, -+ "node_modules/unicode-property-aliases-ecmascript": { -+ "version": "2.1.0", -+ "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", -+ "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", -+ "dev": true, -+ "engines": { -+ "node": ">=4" -+ } -+ }, -+ "node_modules/update-browserslist-db": { -+ "version": "1.1.0", -+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", -+ "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", -+ "dev": true, -+ "funding": [ -+ { -+ "type": "opencollective", -+ "url": "https://opencollective.com/browserslist" ++ contracts: { ++ ...chainConfig.contracts, ++ l2OutputOracle: { ++ [l1ChainID]: { ++ address: contractAddresses.L2OutputOracleProxy, ++ }, + }, -+ { -+ "type": "tidelift", -+ "url": "https://tidelift.com/funding/github/npm/browserslist" ++ portal: { ++ [l1ChainID]: { ++ address: contractAddresses.OptimismPortalProxy, ++ }, ++ }, ++ l1StandardBridge: { ++ [l1ChainID]: { ++ address: contractAddresses.L1StandardBridgeProxy, ++ }, + }, -+ { -+ "type": "github", -+ "url": "https://github.com/sponsors/ai" -+ } -+ ], -+ "dependencies": { -+ "escalade": "^3.1.2", -+ "picocolors": "^1.0.1" -+ }, -+ "bin": { -+ "update-browserslist-db": "cli.js" + }, -+ "peerDependencies": { -+ "browserslist": ">= 4.21.0" -+ } -+ }, -+ "node_modules/v8-to-istanbul": { -+ "version": "9.3.0", -+ "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", -+ "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", -+ "dev": true, -+ "dependencies": { -+ "@jridgewell/trace-mapping": "^0.3.12", -+ "@types/istanbul-lib-coverage": "^2.0.1", -+ "convert-source-map": "^2.0.0" ++ }), ++ l1: defineChain({ ++ id: l1ChainID, ++ testnet: true, ++ name: 'Ethereum L1', ++ nativeCurrency: { ++ decimals: 18, ++ name: 'Ether', ++ symbol: 'ETH', + }, -+ "engines": { -+ "node": ">=10.12.0" -+ } -+ }, -+ "node_modules/viem": { -+ "version": "2.21.19", -+ "resolved": "https://registry.npmjs.org/viem/-/viem-2.21.19.tgz", -+ "integrity": "sha512-FdlkN+UI1IU5sYOmzvygkxsUNjDRD5YHht3gZFu2X9xFv6Z3h9pXq9ycrYQ3F17lNfb41O2Ot4/aqbUkwOv9dA==", -+ "funding": [ -+ { -+ "type": "github", -+ "url": "https://github.com/sponsors/wevm" -+ } -+ ], -+ "dependencies": { -+ "@adraffy/ens-normalize": "1.11.0", -+ "@noble/curves": "1.6.0", -+ "@noble/hashes": "1.5.0", -+ "@scure/bip32": "1.5.0", -+ "@scure/bip39": "1.4.0", -+ "abitype": "1.0.6", -+ "isows": "1.0.6", -+ "webauthn-p256": "0.0.10", -+ "ws": "8.18.0" ++ rpcUrls: { ++ default: { ++ http: [process.env.ETH_RPC_URL_L1], ++ }, + }, -+ "peerDependencies": { -+ "typescript": ">=5.0.4" ++ contracts: { ++ multicall3: { ++ address: contractAddresses.Multicall3, ++ }, + }, -+ "peerDependenciesMeta": { -+ "typescript": { -+ "optional": true -+ } -+ } -+ }, -+ "node_modules/walker": { -+ "version": "1.0.8", -+ "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", -+ "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", -+ "dev": true, -+ "dependencies": { -+ "makeerror": "1.0.12" -+ } -+ }, -+ "node_modules/webauthn-p256": { -+ "version": "0.0.10", -+ "resolved": "https://registry.npmjs.org/webauthn-p256/-/webauthn-p256-0.0.10.tgz", -+ "integrity": "sha512-EeYD+gmIT80YkSIDb2iWq0lq2zbHo1CxHlQTeJ+KkCILWpVy3zASH3ByD4bopzfk0uCwXxLqKGLqp2W4O28VFA==", -+ "funding": [ -+ { -+ "type": "github", -+ "url": "https://github.com/sponsors/wevm" ++ }), ++ } ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+98
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/celo/src/config.js CELO/op-e2e/celo/src/config.js +new file mode 100644 +index 0000000000000000000000000000000000000000..7e410dffbdd0de20f4dc8b781d6aabcd21f7448f +--- /dev/null ++++ CELO/op-e2e/celo/src/config.js +@@ -0,0 +1,98 @@ ++import { createPublicClient, createWalletClient, http } from 'viem' ++import { readContract } from 'viem/actions' ++import { constructDepositCustomGas } from './deposit.js' ++import { ++ getERC20, ++ simulateERC20Transfer, ++ getERC20BalanceOf, ++ getERC20Symbol, ++ getERC20Decimals, ++ simulateERC20Approve, ++} from 'reverse-mirage' ++import { ++ publicActionsL1, ++ publicActionsL2, ++ walletActionsL1, ++ walletActionsL2, ++} from 'viem/op-stack' ++ ++export function makeReadContract(contractAddress, contractABI) { ++ return (client) => { ++ return { ++ readContract: (args) => { ++ const rcArgs = { ++ address: contractAddress, ++ abi: contractABI, ++ functionName: args.functionName, ++ args: args.args, + } -+ ], -+ "dependencies": { -+ "@noble/curves": "^1.4.0", -+ "@noble/hashes": "^1.4.0" -+ } -+ }, -+ "node_modules/which": { -+ "version": "2.0.2", -+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", -+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", -+ "dev": true, -+ "dependencies": { -+ "isexe": "^2.0.0" -+ }, -+ "bin": { -+ "node-which": "bin/node-which" -+ }, -+ "engines": { -+ "node": ">= 8" -+ } -+ }, -+ "node_modules/wrap-ansi": { -+ "version": "7.0.0", -+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", -+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", -+ "dev": true, -+ "dependencies": { -+ "ansi-styles": "^4.0.0", -+ "string-width": "^4.1.0", -+ "strip-ansi": "^6.0.0" -+ }, -+ "engines": { -+ "node": ">=10" ++ return readContract(client, rcArgs) + }, -+ "funding": { -+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" -+ } ++ } ++ } ++} ++ ++export function erc20PublicActions(client) { ++ return { ++ getERC20: (args) => getERC20(client, args), ++ getERC20Symbol: (args) => getERC20Symbol(client, args), ++ getERC20BalanceOf: (args) => getERC20BalanceOf(client, args), ++ getERC20Decimals: (args) => getERC20Decimals(client, args), ++ } ++} ++export function erc20WalletActions(client) { ++ return { ++ simulateERC20Transfer: (args) => { ++ return simulateERC20Transfer(client, { args: args }) + }, -+ "node_modules/wrap-ansi/node_modules/ansi-styles": { -+ "version": "4.3.0", -+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", -+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", -+ "dev": true, -+ "dependencies": { -+ "color-convert": "^2.0.1" -+ }, -+ "engines": { -+ "node": ">=8" -+ }, -+ "funding": { -+ "url": "https://github.com/chalk/ansi-styles?sponsor=1" -+ } ++ simulateERC20Approve: (args) => { ++ return simulateERC20Approve(client, { args: args }) + }, -+ "node_modules/wrap-ansi/node_modules/color-convert": { -+ "version": "2.0.1", -+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", -+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", -+ "dev": true, -+ "dependencies": { -+ "color-name": "~1.1.4" -+ }, -+ "engines": { -+ "node": ">=7.0.0" -+ } ++ } ++} ++ ++export function celoL1PublicActions(client) { ++ return { ++ prepareDepositGasPayingTokenERC20: (args) => { ++ return constructDepositCustomGas(client, args) + }, -+ "node_modules/wrap-ansi/node_modules/color-name": { -+ "version": "1.1.4", -+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", -+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", -+ "dev": true ++ } ++} ++ ++export function setupClients(l1ChainConfig, l2ChainConfig, account) { ++ return { ++ l1: { ++ public: createPublicClient({ ++ account, ++ chain: l1ChainConfig, ++ transport: http(), ++ }) ++ .extend(publicActionsL1()) ++ .extend(celoL1PublicActions) ++ .extend(erc20PublicActions), ++ wallet: createWalletClient({ ++ account, ++ chain: l1ChainConfig, ++ transport: http(), ++ }) ++ .extend(erc20WalletActions) ++ .extend(walletActionsL1()), + }, -+ "node_modules/wrappy": { -+ "version": "1.0.2", -+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", -+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", -+ "dev": true ++ l2: { ++ public: createPublicClient({ ++ account, ++ chain: l2ChainConfig, ++ transport: http(), ++ }) ++ .extend(publicActionsL2()) ++ .extend(erc20PublicActions), ++ wallet: createWalletClient({ ++ account, ++ chain: l2ChainConfig, ++ transport: http(), ++ }) ++ .extend(erc20WalletActions) ++ .extend(walletActionsL2()), + }, -+ "node_modules/write-file-atomic": { -+ "version": "4.0.2", -+ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", -+ "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", -+ "dev": true, -+ "dependencies": { -+ "imurmurhash": "^0.1.4", -+ "signal-exit": "^3.0.7" -+ }, -+ "engines": { -+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" -+ } ++ } ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+127
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/celo/src/deposit.js CELO/op-e2e/celo/src/deposit.js +new file mode 100644 +index 0000000000000000000000000000000000000000..2e1f5ef17dbdf0eadd4fba293eba79712a1fd0b2 +--- /dev/null ++++ CELO/op-e2e/celo/src/deposit.js +@@ -0,0 +1,127 @@ ++import { getL2TransactionHashes } from 'viem/op-stack' ++import { OptimismPortalABI } from './OptimismPortal.js' ++ ++// public client functionality ++export async function constructDepositCustomGas(client, parameters) { ++ const { ++ account, ++ chain = client.chain, ++ gas, ++ maxFeePerGas, ++ maxPriorityFeePerGas, ++ nonce, ++ request: { ++ data = '0x', ++ gas: l2Gas, ++ isCreation = false, ++ mint, ++ to = '0x', ++ value, + }, -+ "node_modules/ws": { -+ "version": "8.18.0", -+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", -+ "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", -+ "engines": { -+ "node": ">=10.0.0" ++ targetChain, ++ } = parameters ++ ++ const portalAddress = (() => { ++ if (parameters.portalAddress) return parameters.portalAddress ++ if (chain) return targetChain.contracts.portal[chain.id].address ++ return Object.values(targetChain.contracts.portal)[0].address ++ })() ++ const callArgs = { ++ account: account, ++ abi: OptimismPortalABI, ++ address: portalAddress, ++ chain, ++ functionName: 'depositERC20Transaction', ++ /// @notice Entrypoint to depositing an ERC20 token as a custom gas token. ++ /// This function depends on a well formed ERC20 token. There are only ++ /// so many checks that can be done on chain for this so it is assumed ++ /// that chain operators will deploy chains with well formed ERC20 tokens. ++ /// @param _to Target address on L2. ++ /// @param _mint Units of ERC20 token to deposit into L2. ++ /// @param _value Units of ERC20 token to send on L2 to the recipient. ++ /// @param _gasLimit Amount of L2 gas to purchase by burning gas on L1. ++ /// @param _isCreation Whether or not the transaction is a contract creation. ++ /// @param _data Data to trigger the recipient with. ++ args: [ ++ isCreation ? zeroAddress : to, ++ mint ?? value ?? 0n, ++ value ?? mint ?? 0n, ++ l2Gas, ++ isCreation, ++ data, ++ ], ++ maxFeePerGas, ++ maxPriorityFeePerGas, ++ nonce, ++ } ++ const gas_ = ++ typeof gas !== 'number' && gas !== null ++ ? await client.estimateContractGas(callArgs) ++ : undefined ++ callArgs.gas = gas_ ++ const result = client.simulateContract(callArgs) ++ return { result: result, args: callArgs } ++} ++ ++export async function deposit(args, config) { ++ var spentGas = BigInt(0) ++ const depositArgs = await config.client.l2.public.buildDepositTransaction({ ++ mint: args.mint, ++ to: args.to, ++ }) ++ ++ const celoToken = await config.client.l1.public.getERC20({ ++ erc20: { ++ address: config.addresses.CustomGasTokenProxy, ++ chainID: config.client.l1.public.chain.id, ++ }, ++ }) ++ const portalAddress = ++ config.client.l2.public.chain.contracts.portal[ ++ config.client.l1.public.chain.id ++ ].address ++ const approve = await config.client.l1.wallet.simulateERC20Approve({ ++ amount: { amount: args.mint, token: celoToken }, ++ spender: portalAddress, ++ }) ++ if (!approve.result) { ++ return { ++ success: false, ++ l1GasPayment: spentGas, ++ } ++ } ++ ++ const approveHash = await config.client.l1.wallet.writeContract( ++ approve.request ++ ) ++ // Wait for the L1 transaction to be processed. ++ const approveReceipt = ++ await config.client.l1.public.waitForTransactionReceipt({ ++ hash: approveHash, ++ }) ++ ++ spentGas += approveReceipt.gasUsed * approveReceipt.effectiveGasPrice ++ const dep = ++ await config.client.l1.public.prepareDepositGasPayingTokenERC20(depositArgs) ++ const hash = await config.client.l1.wallet.writeContract(dep.args) ++ ++ // Wait for the L1 transaction to be processed. ++ const receipt = await config.client.l1.public.waitForTransactionReceipt({ ++ hash: hash, ++ }) ++ ++ spentGas += receipt.gasUsed * receipt.effectiveGasPrice ++ ++ // Get the L2 transaction hash from the L1 transaction receipt. ++ const [l2Hash] = getL2TransactionHashes(receipt) ++ ++ // Wait for the L2 transaction to be processed. ++ const l2Receipt = await config.client.l2.public.waitForTransactionReceipt({ ++ hash: l2Hash, ++ }) ++ ++ return { ++ success: l2Receipt.status == 'success', ++ l1GasPayment: spentGas, ++ } ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+63
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/celo/src/withdraw.js CELO/op-e2e/celo/src/withdraw.js +new file mode 100644 +index 0000000000000000000000000000000000000000..b52740e75761056942dfe40386334c40e3bd8123 +--- /dev/null ++++ CELO/op-e2e/celo/src/withdraw.js +@@ -0,0 +1,63 @@ ++export const withdraw = async function (args, config) { ++ const initiateHash = await config.client.l2.wallet.initiateWithdrawal({ ++ request: { ++ gas: args.gas, ++ to: args.to, ++ value: args.amount, ++ }, ++ }) ++ const receipt = await config.client.l2.public.waitForTransactionReceipt({ ++ hash: initiateHash, ++ }) ++ ++ const l2GasPayment = ++ receipt.gasUsed * receipt.effectiveGasPrice + receipt.l1Fee ++ ++ // FIXME: this blocks longer, the longer the devnet is running, see ++ // https://github.com/ethereum-optimism/optimism/issues/7668 ++ // NOTE: this function requires the mulitcall contract to be deployed ++ // on the L1 chain. ++ const { output, withdrawal } = await config.client.l1.public.waitToProve({ ++ receipt, ++ targetChain: config.client.l2.public.chain, ++ }) ++ // ++ ++ const proveWithdrawalArgs = ++ await config.client.l2.public.buildProveWithdrawal({ ++ output, ++ withdrawal, ++ }) ++ const proveHash = ++ await config.client.l1.wallet.proveWithdrawal(proveWithdrawalArgs) ++ ++ const proveReceipt = await config.client.l1.public.waitForTransactionReceipt({ ++ hash: proveHash, ++ }) ++ if (proveReceipt.status != 'success') { ++ return { ++ success: false, ++ l2GasPayment: l2GasPayment, ++ } ++ } ++ ++ await config.client.l1.public.waitToFinalize({ ++ withdrawalHash: withdrawal.withdrawalHash, ++ targetChain: config.client.l2.public.chain, ++ }) ++ ++ const finalizeHash = await config.client.l1.wallet.finalizeWithdrawal({ ++ targetChain: config.client.l2.public.chain, ++ withdrawal, ++ }) ++ ++ const finalizeReceipt = ++ await config.client.l1.public.waitForTransactionReceipt({ ++ hash: finalizeHash, ++ }) ++ ++ return { ++ success: finalizeReceipt.status == 'success', ++ l2GasPayment: l2GasPayment, ++ } ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+6
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/celo/test_npm.sh CELO/op-e2e/celo/test_npm.sh +new file mode 100755 +index 0000000000000000000000000000000000000000..89783597300cf124d3091a535f3e01473998ae61 +--- /dev/null ++++ CELO/op-e2e/celo/test_npm.sh +@@ -0,0 +1,6 @@ ++#!/bin/bash ++#shellcheck disable=SC1091 ++set -eo pipefail ++ ++source shared.sh ++npm test
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+42
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/celo/test_weth_bridge.sh CELO/op-e2e/celo/test_weth_bridge.sh +new file mode 100755 +index 0000000000000000000000000000000000000000..c6cc765ca6516cc156bc882efe4eb76c6c4328a4 +--- /dev/null ++++ CELO/op-e2e/celo/test_weth_bridge.sh +@@ -0,0 +1,42 @@ ++#!/bin/bash ++#shellcheck disable=SC2086,SC1091 ++set -eo pipefail ++set -x ++ ++source shared.sh ++SCRIPT_DIR=$(readlink -f "$(dirname "$0")") ++CONTRACTS_DIR=$SCRIPT_DIR/../../packages/contracts-bedrock ++ ++# Deploy WETH ++L1_WETH=$( ++ ETH_RPC_URL=$ETH_RPC_URL_L1 forge create --private-key=$ACC_PRIVKEY --root $CONTRACTS_DIR $CONTRACTS_DIR/src/universal/WETH98.sol:WETH98 --json | jq .deployedTo -r ++) ++ ++# create ERC20 token on L2 ++L2_TOKEN=$( ++ cast send --private-key $ACC_PRIVKEY 0x4200000000000000000000000000000000000012 "createOptimismMintableERC20(address,string,string)" $L1_WETH "Wrapped Ether" "WETH" --json \ ++ | jq -r '.logs[0].topics[2]' | cast parse-bytes32-address ++) ++ ++# Wrap some ETH ++ETH_RPC_URL=$ETH_RPC_URL_L1 cast send --private-key $ACC_PRIVKEY $L1_WETH --value 1ether ++# Approve transfer to bridge ++L1_BRIDGE_ADDR=$(cast call 0x4200000000000000000000000000000000000010 'otherBridge() returns (address)') ++ETH_RPC_URL=$ETH_RPC_URL_L1 cast send --private-key $ACC_PRIVKEY $L1_WETH 'approve(address, uint256) returns (bool)' $L1_BRIDGE_ADDR 1ether ++# Bridge to L2 ++ETH_RPC_URL=$ETH_RPC_URL_L1 cast send --private-key $ACC_PRIVKEY $L1_BRIDGE_ADDR 'bridgeERC20(address _localToken, address _remoteToken, uint256 _amount, uint32 _minGasLimit, bytes calldata _extraData)' $L1_WETH $L2_TOKEN 0.3ether 50000 0x --gas-limit 6000000 ++ ++# Setup up oracle and FeeCurrencyDirectory ++ORACLE=$(forge create --private-key=$ACC_PRIVKEY --root $CONTRACTS_DIR $CONTRACTS_DIR/src/celo/testing/MockSortedOracles.sol:MockSortedOracles --json | jq .deployedTo -r) ++cast send --private-key $ACC_PRIVKEY $ORACLE 'setMedianRate(address, uint256)' $L2_TOKEN 100000000000000000 ++cast send --private-key $ACC_PRIVKEY $FEE_CURRENCY_DIRECTORY_ADDR 'setCurrencyConfig(address, address, uint256)' $L2_TOKEN $ORACLE 60000 ++ ++# Check balance from bridging (we intentionally don't do this right after bridging, since it takes a bit) ++L2_BALANCE=$(cast call $L2_TOKEN 'balanceOf(address) returns (uint256)' $ACC_ADDR) ++echo L2 balance: $L2_BALANCE ++[[ $(echo $L2_BALANCE | awk '{print $1}') -gt 0 ]] || (echo "Bridging to L2 failed!"; exit 1) ++ ++# Send fee currency tx! ++#TXHASH=$(~/op-geth/e2e_test/js-tests/send_tx.mjs 901 $ACC_PRIVKEY $L2_TOKEN) ++#cast receipt $TXHASH ++echo You can use privkey $ACC_PRIVKEY to pay for txs with $L2_TOKEN, now.
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+64
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/celo/tests/setup.js CELO/op-e2e/celo/tests/setup.js +new file mode 100644 +index 0000000000000000000000000000000000000000..585c9ccdbed1a3b673968e484ba44dd82abd6507 +--- /dev/null ++++ CELO/op-e2e/celo/tests/setup.js +@@ -0,0 +1,64 @@ ++import { setupClients } from '../src/config.js' ++import { makeChainConfigs } from '../src/chain.js' ++import { privateKeyToAccount } from 'viem/accounts' ++import { readFileSync } from 'fs' ++ ++// Default Anvil dev account that has a pre-allocation on the op-devnet: ++// "test test test test test test test test test test test junk" mnemonic account, ++// on path "m/44'/60'/0'/0/6". ++// Address: 0x976EA74026E726554dB657fA54763abd0C3a0aa9. ++const privKey = ++ '0x92db14e403b83dfe3df233f83dfa3a0d7096f21ca9b0d6d6b8d88b2b4ec1564e' ++ ++async function waitForNoError(func, timeout) { ++ const start = Date.now() ++ while (Date.now() - start < timeout) { ++ try { ++ await func() ++ return true ++ } catch (error) { } ++ await new Promise((r) => setTimeout(r, 1000)) ++ } ++ return false ++} ++ ++async function waitReachable(client, timeout) { ++ const f = async () => client.getChainId() ++ return waitForNoError(f, timeout) ++} ++ ++async function waitForNextL2Output(client, l2ChainConfig, timeout) { ++ const f = async () => ++ client.waitForNextL2Output({ ++ pollingInterval: 500, ++ l2BlockNumber: 0, ++ targetChain: l2ChainConfig, ++ }) ++ return waitForNoError(f, timeout) ++} ++ ++export async function setup() { ++ const contractAddrs = JSON.parse( ++ readFileSync('../../.devnet/addresses.json', 'utf8') ++ ) ++ const config = { account: privateKeyToAccount(privKey) } ++ const chainConfig = makeChainConfigs(900, 901, contractAddrs) ++ ++ config.client = setupClients( ++ chainConfig.l1, ++ chainConfig.l2, ++ config.account, ++ contractAddrs ++ ) ++ config.addresses = contractAddrs ++ ++ const success = await Promise.all([ ++ waitReachable(config.client.l1.public, 10_000), ++ waitReachable(config.client.l2.public, 10_000), ++ waitForNextL2Output(config.client.l1.public, chainConfig.l2, 60_000), ++ ]) ++ if (success.every((v) => v == true)) { ++ return config ++ } ++ throw new Error('l1 and l2 clients not reachable within the deadline') ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+42
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/celo/tests/tokenduality.test.js CELO/op-e2e/celo/tests/tokenduality.test.js +new file mode 100644 +index 0000000000000000000000000000000000000000..9980c81fece42a92f061e53be6cec62627a944f2 +--- /dev/null ++++ CELO/op-e2e/celo/tests/tokenduality.test.js +@@ -0,0 +1,42 @@ ++import { createAmountFromString } from 'reverse-mirage' ++import { setup } from './setup.js' ++ ++const minute = 60 * 1000 ++let config = {} ++ ++beforeAll(async () => { ++ config = await setup() ++}, 30_000) ++ ++test( ++ 'test token duality', ++ async () => { ++ const receiverAddr = '0x000000000000000000000000000000000000dEaD' ++ const dualityToken = await config.client.l2.public.getERC20({ ++ erc20: { ++ address: '0x471ece3750da237f93b8e339c536989b8978a438', ++ chainID: config.client.l2.public.chain.id, + }, -+ "peerDependencies": { -+ "bufferutil": "^4.0.1", -+ "utf-8-validate": ">=5.0.2" ++ }) ++ const balanceBefore = await config.client.l2.public.getBalance({ ++ address: receiverAddr, ++ }) ++ ++ const sendAmount = createAmountFromString(dualityToken, '100') ++ const { request } = await config.client.l2.wallet.simulateERC20Transfer({ ++ to: receiverAddr, ++ amount: sendAmount, ++ }) ++ const transferHash = await config.client.l2.wallet.writeContract(request) ++ const receipt = await config.client.l2.public.waitForTransactionReceipt({ ++ hash: transferHash, ++ }) ++ expect(receipt.status).toBe('success') ++ const balanceAfter = await config.client.l2.public.getBalance({ ++ address: receiverAddr, ++ }) ++ ++ expect(balanceAfter).toBe(balanceBefore + sendAmount.amount) ++ }, ++ 1 * minute ++)
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+77
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/celo/tests/withdraw_deposit.test.js CELO/op-e2e/celo/tests/withdraw_deposit.test.js +new file mode 100644 +index 0000000000000000000000000000000000000000..b7235239f4d1ff2653420f7406c322cbd4ceb83e +--- /dev/null ++++ CELO/op-e2e/celo/tests/withdraw_deposit.test.js +@@ -0,0 +1,77 @@ ++import { withdraw } from '../src/withdraw.js' ++import { deposit } from '../src/deposit.js' ++import { parseEther } from 'viem' ++import { setup } from './setup.js' ++ ++const minute = 60 * 1000 ++var config = {} ++ ++beforeAll(async () => { ++ config = await setup() ++}, minute) ++ ++test( ++ 'execute a withdraw and a deposit in succession', ++ async () => { ++ const celoToken = await config.client.l1.public.getERC20({ ++ erc20: { ++ address: config.addresses.CustomGasTokenProxy, ++ chainID: config.client.l1.public.chain.id, + }, -+ "peerDependenciesMeta": { -+ "bufferutil": { -+ "optional": true -+ }, -+ "utf-8-validate": { -+ "optional": true -+ } -+ } -+ }, -+ "node_modules/y18n": { -+ "version": "5.0.8", -+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", -+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", -+ "dev": true, -+ "engines": { -+ "node": ">=10" -+ } -+ }, -+ "node_modules/yallist": { -+ "version": "3.1.1", -+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", -+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", -+ "dev": true -+ }, -+ "node_modules/yargs": { -+ "version": "17.7.2", -+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", -+ "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", -+ "dev": true, -+ "dependencies": { -+ "cliui": "^8.0.1", -+ "escalade": "^3.1.1", -+ "get-caller-file": "^2.0.5", -+ "require-directory": "^2.1.1", -+ "string-width": "^4.2.3", -+ "y18n": "^5.0.5", -+ "yargs-parser": "^21.1.1" ++ }) ++ const balanceL1Before = await config.client.l1.public.getERC20BalanceOf({ ++ erc20: celoToken, ++ address: config.account.address, ++ }) ++ const balanceL2Before = await config.client.l2.public.getBalance({ ++ address: config.account.address, ++ }) ++ const withdrawAmount = parseEther('1') ++ const withdrawResult = await withdraw( ++ { ++ amount: withdrawAmount, ++ to: config.account.address, ++ gas: 21_000n, + }, -+ "engines": { -+ "node": ">=12" -+ } -+ }, -+ "node_modules/yargs-parser": { -+ "version": "21.1.1", -+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", -+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", -+ "dev": true, -+ "engines": { -+ "node": ">=12" -+ } -+ }, -+ "node_modules/yocto-queue": { -+ "version": "0.1.0", -+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", -+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", -+ "dev": true, -+ "engines": { -+ "node": ">=10" ++ config ++ ) ++ expect(withdrawResult.success).toBe(true) ++ const balanceL1AfterWithdraw = ++ await config.client.l1.public.getERC20BalanceOf({ ++ erc20: celoToken, ++ address: config.account.address, ++ }) ++ const balanceL2AfterWithdraw = await config.client.l2.public.getBalance({ ++ address: config.account.address, ++ }) ++ expect(balanceL1AfterWithdraw.amount).toBe( ++ balanceL1Before.amount + BigInt(withdrawAmount) ++ ) ++ expect(balanceL2AfterWithdraw).toBe( ++ balanceL2Before - BigInt(withdrawAmount) - withdrawResult.l2GasPayment ++ ) ++ const depositResult = await deposit( ++ { ++ mint: withdrawAmount, ++ to: config.account.address, + }, -+ "funding": { -+ "url": "https://github.com/sponsors/sindresorhus" -+ } ++ config ++ ) ++ expect(depositResult.success).toBe(true) ++ ++ const balanceL1AfterDeposit = ++ await config.client.l1.public.getERC20BalanceOf({ ++ erc20: celoToken, ++ address: config.account.address, ++ }) ++ const balanceL2AfterDeposit = await config.client.l2.public.getBalance({ ++ address: config.account.address, ++ }) ++ ++ expect(balanceL1AfterDeposit.amount).toBe(balanceL1Before.amount) ++ expect(balanceL2AfterDeposit).toBe( ++ balanceL2Before - withdrawResult.l2GasPayment ++ ) ++ }, ++ 15 * minute ++)
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+4
+
-4
+ +
+ +
+
+
diff --git OP/op-e2e/devnet/devnet_test.go CELO/op-e2e/devnet/devnet_test.go +index 2a9b4be8aa5d9a04a16a7874384ca96b6369f4c8..8bf7bd7665dab5da774b6a296852a965079c460c 100644 +--- OP/op-e2e/devnet/devnet_test.go ++++ CELO/op-e2e/devnet/devnet_test.go +@@ -6,11 +6,11 @@ "log/slog" + "testing" + "time" +  +- e2e "github.com/ethereum-optimism/optimism/op-e2e" +- "github.com/ethereum-optimism/optimism/op-service/testlog" +- + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ++ ++ "github.com/ethereum-optimism/optimism/op-e2e/system/bridge" ++ "github.com/ethereum-optimism/optimism/op-service/testlog" + ) +  + func TestDevnet(t *testing.T) { +@@ -29,7 +29,7 @@ testSyncFinalized(t, sys) + }) + t.Run("Withdrawal", func(t *testing.T) { + t.Parallel() +- e2e.RunWithdrawalsTest(t, sys) ++ bridge.RunWithdrawalsTest(t, sys) + }) + } +
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+7
+
-6
+ +
+ +
+
+
diff --git OP/op-e2e/devnet/setup.go CELO/op-e2e/devnet/setup.go +index 8724fcfc4e1f9d7ea4507d9832305e6c52524605..557caed0388b239070dc15ce9fda2619cd9757cd 100644 +--- OP/op-e2e/devnet/setup.go ++++ CELO/op-e2e/devnet/setup.go +@@ -6,8 +6,9 @@ "crypto/ecdsa" + "os" + "path/filepath" +  ++ "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" ++ + "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" +- e2e "github.com/ethereum-optimism/optimism/op-e2e" + "github.com/ethereum-optimism/optimism/op-e2e/config" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" + op_service "github.com/ethereum-optimism/optimism/op-service" +@@ -29,7 +30,7 @@ type System struct { + L1 *ethclient.Client + L2 *ethclient.Client + Rollup *sources.RollupClient +- Cfg e2e.SystemConfig ++ Cfg e2esys.SystemConfig + } +  + func NewSystem(ctx context.Context, lgr log.Logger) (sys *System, err error) { +@@ -69,7 +70,7 @@ return nil, err + } +  + // Incomplete SystemConfig suffices for withdrawal test (only consumer right now) +- sys.Cfg = e2e.SystemConfig{ ++ sys.Cfg = e2esys.SystemConfig{ + DeployConfig: deployConfig, + L1Deployments: config.L1Deployments.Copy(), + Secrets: secrets, +@@ -79,9 +80,9 @@ } +  + func (s System) NodeClient(role string) *ethclient.Client { + switch role { +- case e2e.RoleL1: ++ case e2esys.RoleL1: + return s.L1 +- case e2e.RoleSeq, e2e.RoleVerif: ++ case e2esys.RoleSeq, e2esys.RoleVerif: + // we have only one L2 node + return s.L2 + default: +@@ -94,7 +95,7 @@ // we ignore role, have only one L2 rollup + return s.Rollup + } +  +-func (s System) Config() e2e.SystemConfig { ++func (s System) Config() e2esys.SystemConfig { + return s.Cfg + } +
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+20
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/helper.go CELO/op-e2e/e2e.go +rename from op-e2e/helper.go +rename to op-e2e/e2e.go +index 441bc3d9275c19738feec7351ee50ea73c6378af..ebcf5750e381812cf4a15d00e36706d32147c79b 100644 +--- OP/op-e2e/helper.go ++++ CELO/op-e2e/e2e.go +@@ -2,12 +2,32 @@ package op_e2e +  + import ( + "crypto/md5" ++ "fmt" + "os" ++ "runtime" + "strconv" + "strings" ++ "testing" +  ++ "github.com/ethereum-optimism/optimism/op-e2e/config" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" + ) ++ ++func RunMain(m *testing.M) { ++ if config.ExternalL2Shim != "" { ++ fmt.Println("Running tests with external L2 process adapter at ", config.ExternalL2Shim) ++ // As these are integration tests which launch many other processes, the ++ // default parallelism makes the tests flaky. This change aims to ++ // reduce the flakiness of these tests. ++ maxProcs := runtime.NumCPU() / 4 ++ if maxProcs == 0 { ++ maxProcs = 1 ++ } ++ runtime.GOMAXPROCS(maxProcs) ++ } ++ ++ os.Exit(m.Run()) ++} +  + var enableParallelTesting bool = os.Getenv("OP_E2E_DISABLE_PARALLEL") != "true" +
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+73
+
-11
+ +
+ +
+
+
diff --git OP/op-e2e/e2eutils/blobs.go CELO/op-e2e/e2eutils/blobs.go +index 730aae1d94c5ebab3c7068cad06a0acbda90dec3..791130470eda57f23f785f22074ea08ff32a7949 100644 +--- OP/op-e2e/e2eutils/blobs.go ++++ CELO/op-e2e/e2eutils/blobs.go +@@ -5,7 +5,7 @@ "context" + "fmt" +  + "github.com/ethereum/go-ethereum" +- "github.com/ethereum/go-ethereum/common" ++ "github.com/ethereum/go-ethereum/crypto/kzg4844" +  + "github.com/ethereum-optimism/optimism/op-node/rollup/derive" + "github.com/ethereum-optimism/optimism/op-service/eth" +@@ -13,35 +13,97 @@ ) +  + // BlobsStore is a simple in-memory store of blobs, for testing purposes + type BlobsStore struct { +- // blockhash -> blob versioned hash -> blob +- blobs map[common.Hash]map[common.Hash]*eth.Blob ++ // block timestamp -> blob versioned hash -> blob ++ blobs map[uint64]map[eth.IndexedBlobHash]*eth.Blob + } +  + func NewBlobStore() *BlobsStore { +- return &BlobsStore{blobs: make(map[common.Hash]map[common.Hash]*eth.Blob)} ++ return &BlobsStore{blobs: make(map[uint64]map[eth.IndexedBlobHash]*eth.Blob)} + } +  +-func (store *BlobsStore) StoreBlob(blockHash common.Hash, versionedHash common.Hash, blob *eth.Blob) { +- m, ok := store.blobs[blockHash] ++func (store *BlobsStore) StoreBlob(blockTime uint64, indexedHash eth.IndexedBlobHash, blob *eth.Blob) { ++ m, ok := store.blobs[blockTime] + if !ok { +- m = make(map[common.Hash]*eth.Blob) +- store.blobs[blockHash] = m ++ m = make(map[eth.IndexedBlobHash]*eth.Blob) ++ store.blobs[blockTime] = m + } +- m[versionedHash] = blob ++ m[indexedHash] = blob + } +  + func (store *BlobsStore) GetBlobs(ctx context.Context, ref eth.L1BlockRef, hashes []eth.IndexedBlobHash) ([]*eth.Blob, error) { + out := make([]*eth.Blob, 0, len(hashes)) +- m, ok := store.blobs[ref.Hash] ++ m, ok := store.blobs[ref.Time] + if !ok { + return nil, fmt.Errorf("no blobs known with given time: %w", ethereum.NotFound) + } + for _, h := range hashes { +- b, ok := m[h.Hash] ++ b, ok := m[h] + if !ok { + return nil, fmt.Errorf("blob %d %s is not in store: %w", h.Index, h.Hash, ethereum.NotFound) + } + out = append(out, b) ++ } ++ return out, nil ++} ++ ++func (store *BlobsStore) GetBlobSidecars(ctx context.Context, ref eth.L1BlockRef, hashes []eth.IndexedBlobHash) ([]*eth.BlobSidecar, error) { ++ out := make([]*eth.BlobSidecar, 0, len(hashes)) ++ m, ok := store.blobs[ref.Time] ++ if !ok { ++ return nil, fmt.Errorf("no blobs known with given time: %w", ethereum.NotFound) ++ } ++ for _, h := range hashes { ++ b, ok := m[h] ++ if !ok { ++ return nil, fmt.Errorf("blob %d %s is not in store: %w", h.Index, h.Hash, ethereum.NotFound) ++ } ++ if b == nil { ++ return nil, fmt.Errorf("blob %d %s is nil, cannot copy: %w", h.Index, h.Hash, ethereum.NotFound) ++ } ++ ++ commitment, err := kzg4844.BlobToCommitment(b.KZGBlob()) ++ if err != nil { ++ return nil, fmt.Errorf("failed to convert blob to commitment: %w", err) ++ } ++ proof, err := kzg4844.ComputeBlobProof(b.KZGBlob(), commitment) ++ if err != nil { ++ return nil, fmt.Errorf("failed to compute blob proof: %w", err) ++ } ++ out = append(out, &eth.BlobSidecar{ ++ Index: eth.Uint64String(h.Index), ++ Blob: *b, ++ KZGCommitment: eth.Bytes48(commitment), ++ KZGProof: eth.Bytes48(proof), ++ }) ++ } ++ return out, nil ++} ++ ++func (store *BlobsStore) GetAllSidecars(ctx context.Context, l1Timestamp uint64) ([]*eth.BlobSidecar, error) { ++ m, ok := store.blobs[l1Timestamp] ++ if !ok { ++ return nil, fmt.Errorf("no blobs known with given time: %w", ethereum.NotFound) ++ } ++ out := make([]*eth.BlobSidecar, len(m)) ++ for h, b := range m { ++ if b == nil { ++ return nil, fmt.Errorf("blob %d %s is nil, cannot copy: %w", h.Index, h.Hash, ethereum.NotFound) ++ } ++ ++ commitment, err := kzg4844.BlobToCommitment(b.KZGBlob()) ++ if err != nil { ++ return nil, fmt.Errorf("failed to convert blob to commitment: %w", err) ++ } ++ proof, err := kzg4844.ComputeBlobProof(b.KZGBlob(), commitment) ++ if err != nil { ++ return nil, fmt.Errorf("failed to compute blob proof: %w", err) ++ } ++ out[h.Index] = &eth.BlobSidecar{ ++ Index: eth.Uint64String(h.Index), ++ Blob: *b, ++ KZGCommitment: eth.Bytes48(commitment), ++ KZGProof: eth.Bytes48(proof), ++ } + } + return out, nil + }
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+9
+
-2
+ +
+ +
+
+
diff --git OP/op-e2e/e2eutils/challenger/helper.go CELO/op-e2e/e2eutils/challenger/helper.go +index e79bb56b3304bf8b85c5489d983676976dc3e664..87a51d96a5f0f731fd644d3df6d44919ddc917de 100644 +--- OP/op-e2e/e2eutils/challenger/helper.go ++++ CELO/op-e2e/e2eutils/challenger/helper.go +@@ -11,6 +11,8 @@ "path/filepath" + "testing" + "time" +  ++ "github.com/ethereum-optimism/optimism/op-service/crypto" ++ + "github.com/ethereum/go-ethereum/ethclient" + "github.com/stretchr/testify/require" +  +@@ -72,7 +74,7 @@ } +  + func WithPrivKey(key *ecdsa.PrivateKey) Option { + return func(c *config.Config) { +- c.TxMgrConfig.PrivateKey = e2eutils.EncodePrivKeyToString(key) ++ c.TxMgrConfig.PrivateKey = crypto.EncodePrivKeyToString(key) + } + } +  +@@ -106,7 +108,12 @@ require := require.New(t) + root := FindMonorepoRoot(t) + c.Cannon.VmBin = root + "cannon/bin/cannon" + c.Cannon.Server = root + "op-program/bin/op-program" +- c.CannonAbsolutePreState = root + "op-program/bin/prestate.json" ++ if e2eutils.UseMTCannon() { ++ t.Log("Using MT-Cannon absolute prestate") ++ c.CannonAbsolutePreState = root + "op-program/bin/prestate-mt.bin.gz" ++ } else { ++ c.CannonAbsolutePreState = root + "op-program/bin/prestate.json" ++ } + c.Cannon.SnapshotFreq = 10_000_000 +  + genesisBytes, err := json.Marshal(l2Genesis)
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+1
+
-1
+ +
+ +
+
+
diff --git OP/op-e2e/e2eutils/disputegame/output_cannon_helper.go CELO/op-e2e/e2eutils/disputegame/output_cannon_helper.go +index fdb8fd6b3195b4619461e806f4b228f58edbd4ba..a4e017f9c9806873f5d6cee20b3dac8a5cf0c66a 100644 +--- OP/op-e2e/e2eutils/disputegame/output_cannon_helper.go ++++ CELO/op-e2e/e2eutils/disputegame/output_cannon_helper.go +@@ -316,7 +316,7 @@ g.Require.NoError(err, "Failed to fetch local inputs") + localContext = outputs.CreateLocalContext(pre, post) + dir := filepath.Join(cfg.Datadir, "cannon-trace") + subdir := filepath.Join(dir, localContext.Hex()) +- return cannon.NewTraceProviderForTest(logger, metrics.NoopMetrics, cfg, localInputs, subdir, g.MaxDepth(ctx)-splitDepth-1), nil ++ return cannon.NewTraceProviderForTest(logger, metrics.NoopMetrics.VmMetrics(types.TraceTypeCannon.String()), cfg, localInputs, subdir, g.MaxDepth(ctx)-splitDepth-1), nil + }) +  + claims, err := g.Game.GetAllClaims(ctx, rpcblock.Latest)
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+44
+
-29
+ +
+ +
+
+
diff --git OP/op-e2e/e2eutils/fakebeacon/blobs.go CELO/op-e2e/e2eutils/fakebeacon/blobs.go +index 6be65bbb3521e3565d5e633827d76a51ba6b2f29..a96042bc7add4e849f6bd56a3da313e9beb7d886 100644 +--- OP/op-e2e/e2eutils/fakebeacon/blobs.go ++++ CELO/op-e2e/e2eutils/fakebeacon/blobs.go +@@ -1,23 +1,24 @@ + package fakebeacon +  + import ( ++ "context" + "encoding/binary" + "encoding/json" + "errors" + "fmt" +- "io/fs" + "net" + "net/http" +- "os" +- "path/filepath" + "strconv" + "strings" + "sync" + "time" +  ++ "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" + "github.com/ethereum-optimism/optimism/op-service/eth" + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/beacon/engine" ++ "github.com/ethereum/go-ethereum/common/hexutil" ++ "github.com/ethereum/go-ethereum/crypto/kzg4844" + "github.com/ethereum/go-ethereum/log" + ) +  +@@ -27,8 +28,8 @@ // to complement the actual block-building to happen in testing (e.g. through the fake consensus geth module). + type FakeBeacon struct { + log log.Logger +  +- // directory to store blob contents in after the blobs are persisted in a block +- blobsDir string ++ // in-memory blob store ++ blobStore *e2eutils.BlobsStore + blobsLock sync.Mutex +  + beaconSrv *http.Server +@@ -38,10 +39,10 @@ genesisTime uint64 + blockTime uint64 + } +  +-func NewBeacon(log log.Logger, blobsDir string, genesisTime uint64, blockTime uint64) *FakeBeacon { ++func NewBeacon(log log.Logger, blobStore *e2eutils.BlobsStore, genesisTime uint64, blockTime uint64) *FakeBeacon { + return &FakeBeacon{ + log: log, +- blobsDir: blobsDir, ++ blobStore: blobStore, + genesisTime: genesisTime, + blockTime: blockTime, + } +@@ -158,20 +159,23 @@ return nil + } +  + func (f *FakeBeacon) StoreBlobsBundle(slot uint64, bundle *engine.BlobsBundleV1) error { +- data, err := json.Marshal(bundle) +- if err != nil { +- return fmt.Errorf("failed to encode blobs bundle of slot %d: %w", slot, err) +- } +- + f.blobsLock.Lock() + defer f.blobsLock.Unlock() +- bundlePath := fmt.Sprintf("blobs_bundle_%d.json", slot) +- if err := os.MkdirAll(f.blobsDir, 0755); err != nil { +- return fmt.Errorf("failed to create dir for blob storage: %w", err) +- } +- err = os.WriteFile(filepath.Join(f.blobsDir, bundlePath), data, 0755) +- if err != nil { +- return fmt.Errorf("failed to write blobs bundle of slot %d: %w", slot, err) ++ ++ // Solve for the slot timestamp. ++ // slot = (timestamp - genesis) / slot_time ++ // timestamp = slot * slot_time + genesis ++ slotTimestamp := slot*f.blockTime + f.genesisTime ++ ++ for i, b := range bundle.Blobs { ++ f.blobStore.StoreBlob( ++ slotTimestamp, ++ eth.IndexedBlobHash{ ++ Index: uint64(i), ++ Hash: eth.KZGToVersionedHash(kzg4844.Commitment(bundle.Commitments[i])), ++ }, ++ (*eth.Blob)(b[:]), ++ ) + } + return nil + } +@@ -179,19 +183,30 @@ + func (f *FakeBeacon) LoadBlobsBundle(slot uint64) (*engine.BlobsBundleV1, error) { + f.blobsLock.Lock() + defer f.blobsLock.Unlock() +- bundlePath := fmt.Sprintf("blobs_bundle_%d.json", slot) +- data, err := os.ReadFile(filepath.Join(f.blobsDir, bundlePath)) ++ ++ // Solve for the slot timestamp. ++ // slot = (timestamp - genesis) / slot_time ++ // timestamp = slot * slot_time + genesis ++ slotTimestamp := slot*f.blockTime + f.genesisTime ++ ++ // Load blobs from the store ++ blobs, err := f.blobStore.GetAllSidecars(context.Background(), slotTimestamp) + if err != nil { +- if errors.Is(err, fs.ErrNotExist) { +- return nil, fmt.Errorf("no blobs bundle found for slot %d (%q): %w", slot, bundlePath, ethereum.NotFound) +- } else { +- return nil, fmt.Errorf("failed to read blobs bundle of slot %d (%q): %w", slot, bundlePath, err) +- } ++ return nil, fmt.Errorf("failed to load blobs from store: %w", err) ++ } ++ ++ // Convert blobs to the bundle ++ out := engine.BlobsBundleV1{ ++ Commitments: make([]hexutil.Bytes, len(blobs)), ++ Proofs: make([]hexutil.Bytes, len(blobs)), ++ Blobs: make([]hexutil.Bytes, len(blobs)), + } +- var out engine.BlobsBundleV1 +- if err := json.Unmarshal(data, &out); err != nil { +- return nil, fmt.Errorf("failed to decode blobs bundle of slot %d (%q): %w", slot, bundlePath, err) ++ for _, b := range blobs { ++ out.Commitments[b.Index] = hexutil.Bytes(b.KZGCommitment[:]) ++ out.Proofs[b.Index] = hexutil.Bytes(b.KZGProof[:]) ++ out.Blobs[b.Index] = hexutil.Bytes(b.Blob[:]) + } ++ + return &out, nil + } +
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+1
+
-1
+ +
+ +
+
+
diff --git OP/op-e2e/tracer.go CELO/op-e2e/e2eutils/opnode/tracer.go +rename from op-e2e/tracer.go +rename to op-e2e/e2eutils/opnode/tracer.go +index 217c1762082ac5481248119acf00fa2594b4efa9..33a23b775ce5fa5c67693def032b04a7cbef55f5 100644 +--- OP/op-e2e/tracer.go ++++ CELO/op-e2e/e2eutils/opnode/tracer.go +@@ -1,4 +1,4 @@ +-package op_e2e ++package opnode +  + import ( + "context"
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+0
+
-13
+ +
+ +
+
+
diff --git OP/op-e2e/e2eutils/secrets.go CELO/op-e2e/e2eutils/secrets.go +index 7c934cc65f5a5f00c0e4cd22859c83e0762f5b3d..cd4c91e1e09e5d55e20adacf99ce715433c5c03a 100644 +--- OP/op-e2e/e2eutils/secrets.go ++++ CELO/op-e2e/e2eutils/secrets.go +@@ -8,7 +8,6 @@ + hdwallet "github.com/ethereum-optimism/go-ethereum-hdwallet" + "github.com/ethereum/go-ethereum/accounts" + "github.com/ethereum/go-ethereum/common" +- "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/crypto" + ) +  +@@ -132,18 +131,6 @@ Mallory *ecdsa.PrivateKey +  + // Share the wallet to be able to generate more accounts + Wallet *hdwallet.Wallet +-} +- +-// EncodePrivKey encodes the given private key in 32 bytes +-func EncodePrivKey(priv *ecdsa.PrivateKey) hexutil.Bytes { +- privkey := make([]byte, 32) +- blob := priv.D.Bytes() +- copy(privkey[32-len(blob):], blob) +- return privkey +-} +- +-func EncodePrivKeyToString(priv *ecdsa.PrivateKey) string { +- return hexutil.Encode(EncodePrivKey(priv)) + } +  + // Addresses computes the ethereum address of each account,
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+6
+
-1
+ +
+ +
+
+
diff --git OP/op-e2e/e2eutils/setup.go CELO/op-e2e/e2eutils/setup.go +index e226b3da80959c4e2cb8930be5e59c2f98742e79..52dd6ec2d3aef8d047565f3898c197cb7edd6473 100644 +--- OP/op-e2e/e2eutils/setup.go ++++ CELO/op-e2e/e2eutils/setup.go +@@ -134,7 +134,7 @@ if ecotoneTime := deployConf.EcotoneTime(l1Block.Time()); ecotoneTime != nil && *ecotoneTime == 0 { + allocsMode = genesis.L2AllocsEcotone + } + l2Allocs := config.L2Allocs(allocsMode) +- l2Genesis, err := genesis.BuildL2Genesis(deployConf, l2Allocs, l1Block) ++ l2Genesis, err := genesis.BuildL2Genesis(deployConf, l2Allocs, l1Block.Header()) + require.NoError(t, err, "failed to create l2 genesis") + if alloc.PrefundTestUsers { + for _, addr := range deployParams.Addresses.All() { +@@ -249,3 +249,8 @@ func UseAltDA() bool { + return (os.Getenv("OP_E2E_USE_ALTDA") == "true" || + os.Getenv("DEVNET_ALTDA") == "true") + } ++ ++func UseMTCannon() bool { ++ return (os.Getenv("OP_E2E_USE_MT_CANNON") == "true" || ++ os.Getenv("USE_MT_CANNON") == "true") ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+32
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/e2eutils/setuputils/utils.go CELO/op-e2e/e2eutils/setuputils/utils.go +new file mode 100644 +index 0000000000000000000000000000000000000000..12f6bca83f42495be13692445fb0cb5aba533b58 +--- /dev/null ++++ CELO/op-e2e/e2eutils/setuputils/utils.go +@@ -0,0 +1,32 @@ ++package setuputils ++ ++import ( ++ "crypto/ecdsa" ++ "time" ++ ++ "github.com/ethereum-optimism/optimism/op-service/crypto" ++ ++ "github.com/ethereum/go-ethereum/common/hexutil" ++ ++ "github.com/ethereum-optimism/optimism/op-service/endpoint" ++ "github.com/ethereum-optimism/optimism/op-service/txmgr" ++) ++ ++func hexPriv(in *ecdsa.PrivateKey) string { ++ b := crypto.EncodePrivKey(in) ++ return hexutil.Encode(b) ++} ++ ++func NewTxMgrConfig(l1Addr endpoint.RPC, privKey *ecdsa.PrivateKey) txmgr.CLIConfig { ++ return txmgr.CLIConfig{ ++ L1RPCURL: l1Addr.RPC(), ++ PrivateKey: hexPriv(privKey), ++ NumConfirmations: 1, ++ SafeAbortNonceTooLowCount: 3, ++ FeeLimitMultiplier: 5, ++ ResubmissionTimeout: 3 * time.Second, ++ ReceiptQueryInterval: 50 * time.Millisecond, ++ NetworkTimeout: 2 * time.Second, ++ TxNotInMempoolTimeout: 2 * time.Minute, ++ } ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+21
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/e2eutils/transactions/count.go CELO/op-e2e/e2eutils/transactions/count.go +new file mode 100644 +index 0000000000000000000000000000000000000000..0f4d41fe04786da83030e0f3465f48f7c4fd812c +--- /dev/null ++++ CELO/op-e2e/e2eutils/transactions/count.go +@@ -0,0 +1,21 @@ ++package transactions ++ ++import ( ++ "github.com/ethereum/go-ethereum/common" ++ "github.com/ethereum/go-ethereum/core/types" ++) ++ ++func TransactionsBySender(block *types.Block, sender common.Address) (int64, error) { ++ txCount := int64(0) ++ for _, tx := range block.Transactions() { ++ signer := types.NewCancunSigner(tx.ChainId()) ++ txSender, err := types.Sender(signer, tx) ++ if err != nil { ++ return 0, err ++ } ++ if txSender == sender { ++ txCount++ ++ } ++ } ++ return txCount, nil ++}
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+3
+
-2
+ +
+ +
+
+
diff --git OP/op-e2e/external_geth/main_test.go CELO/op-e2e/external_geth/main_test.go +index 8cea0ec81fdb13f2d9b701872ae29b4f85cab7cc..b971057e0cc29c657cf7b1918bf549461deb77e5 100644 +--- OP/op-e2e/external_geth/main_test.go ++++ CELO/op-e2e/external_geth/main_test.go +@@ -9,9 +9,10 @@ "path/filepath" + "testing" + "time" +  ++ "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" ++ + "github.com/stretchr/testify/require" +  +- e2e "github.com/ethereum-optimism/optimism/op-e2e" + "github.com/ethereum-optimism/optimism/op-e2e/config" + "github.com/ethereum-optimism/optimism/op-service/endpoint" + ) +@@ -37,7 +38,7 @@ require.FileExists(t, "op-geth") +  + config.EthNodeVerbosity = config.LegacyLevelDebug +  +- ec := (&e2e.ExternalRunner{ ++ ec := (&e2esys.ExternalRunner{ + Name: "TestShim", + BinPath: shimPath, + }).Run(t)
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+7
+
-5
+ +
+ +
+
+
diff --git OP/op-e2e/faultproofs/cannon_benchmark_test.go CELO/op-e2e/faultproofs/cannon_benchmark_test.go +index a4e1674810873c104091d940f0525fe4a74c9b85..7171d1211764e7330e04d600bb47181eeae91f69 100644 +--- OP/op-e2e/faultproofs/cannon_benchmark_test.go ++++ CELO/op-e2e/faultproofs/cannon_benchmark_test.go +@@ -11,6 +11,9 @@ "sync" + "testing" + "time" +  ++ op_e2e "github.com/ethereum-optimism/optimism/op-e2e" ++ "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" ++ + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" +@@ -23,7 +26,6 @@ "github.com/stretchr/testify/require" +  + "github.com/ethereum-optimism/optimism/cannon/mipsevm" + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/utils" +- op_e2e "github.com/ethereum-optimism/optimism/op-e2e" + "github.com/ethereum-optimism/optimism/op-e2e/bindings" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" + "github.com/ethereum-optimism/optimism/op-service/predeploys" +@@ -35,7 +37,7 @@ t.Skip("TODO(client-pod#906): Compare total witness size for assertions against pages allocated by the VM") +  + op_e2e.InitParallel(t, op_e2e.UsesCannon) + ctx := context.Background() +- cfg := op_e2e.DefaultSystemConfig(t) ++ cfg := e2esys.DefaultSystemConfig(t) + // We don't need a verifier - just the sequencer is enough + delete(cfg.Nodes, "verifier") + // Use a small sequencer window size to avoid test timeout while waiting for empty blocks +@@ -93,7 +95,7 @@ L2OutputRoot: common.Hash(l2OutputRoot), + L2BlockNumber: l2ClaimBlockNumber, + } + debugfile := path.Join(t.TempDir(), "debug.json") +- runCannon(t, ctx, sys, inputs, "sequencer", "--debug-info", debugfile) ++ runCannon(t, ctx, sys, inputs, "--debug-info", debugfile) + data, err := os.ReadFile(debugfile) + require.NoError(t, err) + var debuginfo mipsevm.DebugInfo +@@ -102,7 +104,7 @@ t.Logf("Debug info: %#v", debuginfo) + // TODO(client-pod#906): Use maximum witness size for assertions against pages allocated by the VM + } +  +-func createBigContracts(ctx context.Context, t *testing.T, cfg op_e2e.SystemConfig, client *ethclient.Client, key *ecdsa.PrivateKey, numContracts int) []common.Address { ++func createBigContracts(ctx context.Context, t *testing.T, cfg e2esys.SystemConfig, client *ethclient.Client, key *ecdsa.PrivateKey, numContracts int) []common.Address { + /* + contract Big { + bytes constant foo = hex"<24.4 KB of random data>"; +@@ -162,7 +164,7 @@ } + return addrs + } +  +-func callBigContracts(ctx context.Context, t *testing.T, cfg op_e2e.SystemConfig, client *ethclient.Client, key *ecdsa.PrivateKey, addrs []common.Address) *types.Receipt { ++func callBigContracts(ctx context.Context, t *testing.T, cfg e2esys.SystemConfig, client *ethclient.Client, key *ecdsa.PrivateKey, addrs []common.Address) *types.Receipt { + multicall3, err := bindings.NewMultiCall3(predeploys.MultiCall3Addr, client) + require.NoError(t, err) +
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+1
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/faultproofs/challenge_preimage_test.go CELO/op-e2e/faultproofs/challenge_preimage_test.go +index 226f85c825c154fe753dcbcc8512aaba11b4cfc0..3bed79ad068ec3792f3a9a5162fd415171167e85 100644 +--- OP/op-e2e/faultproofs/challenge_preimage_test.go ++++ CELO/op-e2e/faultproofs/challenge_preimage_test.go +@@ -5,6 +5,7 @@ "context" + "testing" +  + op_e2e "github.com/ethereum-optimism/optimism/op-e2e" ++ + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/challenger" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/disputegame" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/disputegame/preimage"
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+1
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/faultproofs/multi_test.go CELO/op-e2e/faultproofs/multi_test.go +index 8073c3e7596b22db88d4dad4a2c2cad948988e84..83b475d60e0d5f38bfd3a4e6d517274649efd5dc 100644 +--- OP/op-e2e/faultproofs/multi_test.go ++++ CELO/op-e2e/faultproofs/multi_test.go +@@ -5,6 +5,7 @@ "context" + "testing" +  + op_e2e "github.com/ethereum-optimism/optimism/op-e2e" ++ + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/challenger" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/disputegame" + "github.com/ethereum/go-ethereum/common"
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+2
+
-1
+ +
+ +
+
+
diff --git OP/op-e2e/faultproofs/output_alphabet_test.go CELO/op-e2e/faultproofs/output_alphabet_test.go +index 3e46c732edb3a932c2488112b9db74704a4378f4..9255214ff39b76f5e89d3bb7b3e3185a35a001fa 100644 +--- OP/op-e2e/faultproofs/output_alphabet_test.go ++++ CELO/op-e2e/faultproofs/output_alphabet_test.go +@@ -6,8 +6,9 @@ "math/big" + "testing" + "time" +  ++ op_e2e "github.com/ethereum-optimism/optimism/op-e2e" ++ + "github.com/ethereum-optimism/optimism/op-challenger/game/types" +- op_e2e "github.com/ethereum-optimism/optimism/op-e2e" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/challenger" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/disputegame" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait"
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+2
+
-1
+ +
+ +
+
+
diff --git OP/op-e2e/faultproofs/output_cannon_test.go CELO/op-e2e/faultproofs/output_cannon_test.go +index c5ac078df93206fa663e348f90954d4c9a55949e..d0abbac7338c9b2c33e1b6a51fba550a2e1a330e 100644 +--- OP/op-e2e/faultproofs/output_cannon_test.go ++++ CELO/op-e2e/faultproofs/output_cannon_test.go +@@ -5,10 +5,11 @@ "context" + "fmt" + "testing" +  ++ op_e2e "github.com/ethereum-optimism/optimism/op-e2e" ++ + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/utils" + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" + gameTypes "github.com/ethereum-optimism/optimism/op-challenger/game/types" +- op_e2e "github.com/ethereum-optimism/optimism/op-e2e" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/challenger" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/disputegame" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/disputegame/preimage"
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+17
+
-31
+ +
+ +
+
+
diff --git OP/op-e2e/faultproofs/precompile_test.go CELO/op-e2e/faultproofs/precompile_test.go +index ba60d45802e9afd1c9544cdefdf4f20351138b43..aebe6a8fd1a9978504d7040e0f73521c72c5d9d1 100644 +--- OP/op-e2e/faultproofs/precompile_test.go ++++ CELO/op-e2e/faultproofs/precompile_test.go +@@ -2,13 +2,16 @@ package faultproofs +  + import ( + "context" +- "encoding/json" +- "fmt" + "math" + "math/big" + "path/filepath" + "testing" +  ++ op_e2e "github.com/ethereum-optimism/optimism/op-e2e" ++ "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" ++ "github.com/ethereum-optimism/optimism/op-e2e/system/helpers" ++ ++ "github.com/ethereum-optimism/optimism/cannon/mipsevm/versions" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core/types" +@@ -16,16 +19,13 @@ "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/params" + "github.com/stretchr/testify/require" +  +- "github.com/ethereum-optimism/optimism/cannon/mipsevm/singlethreaded" + "github.com/ethereum-optimism/optimism/op-challenger/config" + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/utils" + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/vm" + "github.com/ethereum-optimism/optimism/op-challenger/metrics" +- op_e2e "github.com/ethereum-optimism/optimism/op-e2e" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/challenger" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/disputegame" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" +- "github.com/ethereum-optimism/optimism/op-service/ioutil" + "github.com/ethereum-optimism/optimism/op-service/testlog" + ) +  +@@ -78,7 +78,7 @@ t.Run(test.name, func(t *testing.T) { + op_e2e.InitParallel(t, op_e2e.UsesCannon) + ctx := context.Background() + genesisTime := hexutil.Uint64(0) +- cfg := op_e2e.EcotoneSystemConfig(t, &genesisTime) ++ cfg := e2esys.EcotoneSystemConfig(t, &genesisTime) + // We don't need a verifier - just the sequencer is enough + delete(cfg.Nodes, "verifier") + // Use a small sequencer window size to avoid test timeout while waiting for empty blocks +@@ -104,7 +104,7 @@ require.NoError(t, err, "could not retrieve l2 agreed block") + l2Head := agreedL2Output.BlockRef.Hash + l2OutputRoot := agreedL2Output.OutputRoot +  +- receipt := op_e2e.SendL2Tx(t, cfg, l2Seq, aliceKey, func(opts *op_e2e.TxOpts) { ++ receipt := helpers.SendL2Tx(t, cfg, l2Seq, aliceKey, func(opts *helpers.TxOpts) { + opts.Gas = 1_000_000 + opts.ToAddr = &test.address + opts.Nonce = 0 +@@ -130,7 +130,7 @@ L2Claim: common.Hash(l2Claim), + L2OutputRoot: common.Hash(l2OutputRoot), + L2BlockNumber: l2ClaimBlockNumber, + } +- runCannon(t, ctx, sys, inputs, "sequencer") ++ runCannon(t, ctx, sys, inputs) + }) +  + t.Run("DisputePrecompile-"+test.name, func(t *testing.T) { +@@ -143,7 +143,7 @@ sys, _ := StartFaultDisputeSystem(t, WithBlobBatches()) +  + l2Seq := sys.NodeClient("sequencer") + aliceKey := sys.Cfg.Secrets.Alice +- receipt := op_e2e.SendL2Tx(t, sys.Cfg, l2Seq, aliceKey, func(opts *op_e2e.TxOpts) { ++ receipt := helpers.SendL2Tx(t, sys.Cfg, l2Seq, aliceKey, func(opts *helpers.TxOpts) { + opts.Gas = 1_000_000 + opts.ToAddr = &test.address + opts.Nonce = 0 +@@ -177,7 +177,7 @@ func TestGranitePrecompiles(t *testing.T) { + op_e2e.InitParallel(t, op_e2e.UsesCannon) + ctx := context.Background() + genesisTime := hexutil.Uint64(0) +- cfg := op_e2e.GraniteSystemConfig(t, &genesisTime) ++ cfg := e2esys.GraniteSystemConfig(t, &genesisTime) + // We don't need a verifier - just the sequencer is enough + delete(cfg.Nodes, "verifier") + // Use a small sequencer window size to avoid test timeout while waiting for empty blocks +@@ -242,10 +242,10 @@ L2Claim: common.Hash(l2Claim), + L2OutputRoot: common.Hash(l2OutputRoot), + L2BlockNumber: l2ClaimBlockNumber, + } +- runCannon(t, ctx, sys, inputs, "sequencer") ++ runCannon(t, ctx, sys, inputs) + } +  +-func runCannon(t *testing.T, ctx context.Context, sys *op_e2e.System, inputs utils.LocalGameInputs, l2Node string, extraVmArgs ...string) { ++func runCannon(t *testing.T, ctx context.Context, sys *e2esys.System, inputs utils.LocalGameInputs, extraVmArgs ...string) { + l1Endpoint := sys.NodeEndpoint("l1").RPC() + l1Beacon := sys.L1BeaconEndpoint().RestHTTP() + rollupEndpoint := sys.RollupEndpoint("sequencer").RPC() +@@ -257,29 +257,15 @@ cfg := config.NewConfig(common.Address{}, l1Endpoint, l1Beacon, rollupEndpoint, l2Endpoint, dir) + cannonOpts(&cfg) +  + logger := testlog.Logger(t, log.LevelInfo).New("role", "cannon") +- executor := vm.NewExecutor(logger, metrics.NoopMetrics, cfg.Cannon, vm.NewOpProgramServerExecutor(), cfg.CannonAbsolutePreState, inputs) ++ executor := vm.NewExecutor(logger, metrics.NoopMetrics.VmMetrics("cannon"), cfg.Cannon, vm.NewOpProgramServerExecutor(), cfg.CannonAbsolutePreState, inputs) +  + t.Log("Running cannon") + err := executor.DoGenerateProof(ctx, proofsDir, math.MaxUint, math.MaxUint, extraVmArgs...) + require.NoError(t, err, "failed to generate proof") +  +- state, err := parseState(filepath.Join(proofsDir, "final.json.gz")) ++ state, err := versions.LoadStateFromFile(vm.FinalStatePath(proofsDir, cfg.Cannon.BinarySnapshots)) + require.NoError(t, err, "failed to parse state") +- require.True(t, state.Exited, "cannon did not exit") +- require.Zero(t, state.ExitCode, "cannon failed with exit code %d", state.ExitCode) +- t.Logf("Completed in %d steps", state.Step) +-} +- +-func parseState(path string) (*singlethreaded.State, error) { +- file, err := ioutil.OpenDecompressed(path) +- if err != nil { +- return nil, fmt.Errorf("cannot open state file (%v): %w", path, err) +- } +- defer file.Close() +- var state singlethreaded.State +- err = json.NewDecoder(file).Decode(&state) +- if err != nil { +- return nil, fmt.Errorf("invalid mipsevm state (%v): %w", path, err) +- } +- return &state, nil ++ require.True(t, state.GetExited(), "cannon did not exit") ++ require.Zero(t, state.GetExitCode(), "cannon failed with exit code %d", state.GetExitCode()) ++ t.Logf("Completed in %d steps", state.GetStep()) + }
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+1
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/faultproofs/preimages_test.go CELO/op-e2e/faultproofs/preimages_test.go +index 03acf824daf368d076b4cae89fd0cd9f234848b3..8536fe578a5f53878cfd5d27038627dc0c3b37e8 100644 +--- OP/op-e2e/faultproofs/preimages_test.go ++++ CELO/op-e2e/faultproofs/preimages_test.go +@@ -6,6 +6,7 @@ "fmt" + "testing" +  + op_e2e "github.com/ethereum-optimism/optimism/op-e2e" ++ + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/disputegame" + preimage "github.com/ethereum-optimism/optimism/op-preimage" + "github.com/ethereum-optimism/optimism/op-program/client"
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+12
+
-10
+ +
+ +
+
+
diff --git OP/op-e2e/faultproofs/util.go CELO/op-e2e/faultproofs/util.go +index c3457b299d5ab804c77da1e4872e8e93a25e3872..5beebafd88a6ade16d8f12e065028aa471813911 100644 +--- OP/op-e2e/faultproofs/util.go ++++ CELO/op-e2e/faultproofs/util.go +@@ -4,8 +4,10 @@ import ( + "crypto/ecdsa" + "testing" +  ++ "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" ++ "github.com/ethereum-optimism/optimism/op-e2e/system/helpers" ++ + batcherFlags "github.com/ethereum-optimism/optimism/op-batcher/flags" +- op_e2e "github.com/ethereum-optimism/optimism/op-e2e" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core/types" +@@ -13,16 +15,16 @@ "github.com/ethereum/go-ethereum/ethclient" + "github.com/stretchr/testify/require" + ) +  +-type faultDisputeConfigOpts func(cfg *op_e2e.SystemConfig) ++type faultDisputeConfigOpts func(cfg *e2esys.SystemConfig) +  + func WithBatcherStopped() faultDisputeConfigOpts { +- return func(cfg *op_e2e.SystemConfig) { ++ return func(cfg *e2esys.SystemConfig) { + cfg.DisableBatcher = true + } + } +  + func WithBlobBatches() faultDisputeConfigOpts { +- return func(cfg *op_e2e.SystemConfig) { ++ return func(cfg *e2esys.SystemConfig) { + cfg.DataAvailabilityType = batcherFlags.BlobsType +  + genesisActivation := hexutil.Uint64(0) +@@ -33,7 +35,7 @@ } + } +  + func WithEcotone() faultDisputeConfigOpts { +- return func(cfg *op_e2e.SystemConfig) { ++ return func(cfg *e2esys.SystemConfig) { + genesisActivation := hexutil.Uint64(0) + cfg.DeployConfig.L1CancunTimeOffset = &genesisActivation + cfg.DeployConfig.L2GenesisDeltaTimeOffset = &genesisActivation +@@ -42,13 +44,13 @@ } + } +  + func WithSequencerWindowSize(size uint64) faultDisputeConfigOpts { +- return func(cfg *op_e2e.SystemConfig) { ++ return func(cfg *e2esys.SystemConfig) { + cfg.DeployConfig.SequencerWindowSize = size + } + } +  +-func StartFaultDisputeSystem(t *testing.T, opts ...faultDisputeConfigOpts) (*op_e2e.System, *ethclient.Client) { +- cfg := op_e2e.DefaultSystemConfig(t) ++func StartFaultDisputeSystem(t *testing.T, opts ...faultDisputeConfigOpts) (*e2esys.System, *ethclient.Client) { ++ cfg := e2esys.DefaultSystemConfig(t) + delete(cfg.Nodes, "verifier") + cfg.Nodes["sequencer"].SafeDBPath = t.TempDir() + cfg.DeployConfig.SequencerWindowSize = 4 +@@ -64,8 +66,8 @@ require.Nil(t, err, "Error starting up system") + return sys, sys.NodeClient("l1") + } +  +-func SendKZGPointEvaluationTx(t *testing.T, sys *op_e2e.System, l2Node string, privateKey *ecdsa.PrivateKey) *types.Receipt { +- return op_e2e.SendL2Tx(t, sys.Cfg, sys.NodeClient(l2Node), privateKey, func(opts *op_e2e.TxOpts) { ++func SendKZGPointEvaluationTx(t *testing.T, sys *e2esys.System, l2Node string, privateKey *ecdsa.PrivateKey) *types.Receipt { ++ return helpers.SendL2Tx(t, sys.Cfg, sys.NodeClient(l2Node), privateKey, func(opts *helpers.TxOpts) { + precompile := common.BytesToAddress([]byte{0x0a}) + opts.Gas = 100_000 + opts.ToAddr = &precompile
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+368
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/interop/contracts/emit.go CELO/op-e2e/interop/contracts/emit.go +new file mode 100644 +index 0000000000000000000000000000000000000000..ceae2412659bc48ae22773f6f27a5ca0e8688116 +--- /dev/null ++++ CELO/op-e2e/interop/contracts/emit.go +@@ -0,0 +1,368 @@ ++// Code generated - DO NOT EDIT. ++// This file is a generated binding and any manual changes will be lost. ++ ++package emit ++ ++import ( ++ "errors" ++ "math/big" ++ "strings" ++ ++ ethereum "github.com/ethereum/go-ethereum" ++ "github.com/ethereum/go-ethereum/accounts/abi" ++ "github.com/ethereum/go-ethereum/accounts/abi/bind" ++ "github.com/ethereum/go-ethereum/common" ++ "github.com/ethereum/go-ethereum/core/types" ++ "github.com/ethereum/go-ethereum/event" ++) ++ ++// Reference imports to suppress errors if they are not otherwise used. ++var ( ++ _ = errors.New ++ _ = big.NewInt ++ _ = strings.NewReader ++ _ = ethereum.NotFound ++ _ = bind.Bind ++ _ = common.Big1 ++ _ = types.BloomLookup ++ _ = event.NewSubscription ++ _ = abi.ConvertType ++) ++ ++// EmitMetaData contains all meta data concerning the Emit contract. ++var EmitMetaData = &bind.MetaData{ ++ ABI: "[{\"type\":\"function\",\"name\":\"emitData\",\"inputs\":[{\"name\":\"_data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"DataEmitted\",\"inputs\":[{\"name\":\"_data\",\"type\":\"bytes\",\"indexed\":true,\"internalType\":\"bytes\"}],\"anonymous\":false}]", ++ Bin: "0x6080604052348015600e575f80fd5b5060ff8061001b5f395ff3fe6080604052348015600e575f80fd5b50600436106026575f3560e01c8063d836083e14602a575b5f80fd5b60396035366004607c565b603b565b005b8181604051604992919060e3565b604051908190038120907fe00bbfe6f6f8f1bbed2da38e3f5a139c6f9da594ab248a3cf8b44fc73627772c905f90a25050565b5f8060208385031215608c575f80fd5b823567ffffffffffffffff8082111560a2575f80fd5b818501915085601f83011260b4575f80fd5b81358181111560c1575f80fd5b86602082850101111560d1575f80fd5b60209290920196919550909350505050565b818382375f910190815291905056fea164736f6c6343000819000a", ++} ++ ++// EmitABI is the input ABI used to generate the binding from. ++// Deprecated: Use EmitMetaData.ABI instead. ++var EmitABI = EmitMetaData.ABI ++ ++// EmitBin is the compiled bytecode used for deploying new contracts. ++// Deprecated: Use EmitMetaData.Bin instead. ++var EmitBin = EmitMetaData.Bin ++ ++// DeployEmit deploys a new Ethereum contract, binding an instance of Emit to it. ++func DeployEmit(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *Emit, error) { ++ parsed, err := EmitMetaData.GetAbi() ++ if err != nil { ++ return common.Address{}, nil, nil, err ++ } ++ if parsed == nil { ++ return common.Address{}, nil, nil, errors.New("GetABI returned nil") ++ } ++ ++ address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(EmitBin), backend) ++ if err != nil { ++ return common.Address{}, nil, nil, err ++ } ++ return address, tx, &Emit{EmitCaller: EmitCaller{contract: contract}, EmitTransactor: EmitTransactor{contract: contract}, EmitFilterer: EmitFilterer{contract: contract}}, nil ++} ++ ++// Emit is an auto generated Go binding around an Ethereum contract. ++type Emit struct { ++ EmitCaller // Read-only binding to the contract ++ EmitTransactor // Write-only binding to the contract ++ EmitFilterer // Log filterer for contract events ++} ++ ++// EmitCaller is an auto generated read-only Go binding around an Ethereum contract. ++type EmitCaller struct { ++ contract *bind.BoundContract // Generic contract wrapper for the low level calls ++} ++ ++// EmitTransactor is an auto generated write-only Go binding around an Ethereum contract. ++type EmitTransactor struct { ++ contract *bind.BoundContract // Generic contract wrapper for the low level calls ++} ++ ++// EmitFilterer is an auto generated log filtering Go binding around an Ethereum contract events. ++type EmitFilterer struct { ++ contract *bind.BoundContract // Generic contract wrapper for the low level calls ++} ++ ++// EmitSession is an auto generated Go binding around an Ethereum contract, ++// with pre-set call and transact options. ++type EmitSession struct { ++ Contract *Emit // Generic contract binding to set the session for ++ CallOpts bind.CallOpts // Call options to use throughout this session ++ TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session ++} ++ ++// EmitCallerSession is an auto generated read-only Go binding around an Ethereum contract, ++// with pre-set call options. ++type EmitCallerSession struct { ++ Contract *EmitCaller // Generic contract caller binding to set the session for ++ CallOpts bind.CallOpts // Call options to use throughout this session ++} ++ ++// EmitTransactorSession is an auto generated write-only Go binding around an Ethereum contract, ++// with pre-set transact options. ++type EmitTransactorSession struct { ++ Contract *EmitTransactor // Generic contract transactor binding to set the session for ++ TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session ++} ++ ++// EmitRaw is an auto generated low-level Go binding around an Ethereum contract. ++type EmitRaw struct { ++ Contract *Emit // Generic contract binding to access the raw methods on ++} ++ ++// EmitCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. ++type EmitCallerRaw struct { ++ Contract *EmitCaller // Generic read-only contract binding to access the raw methods on ++} ++ ++// EmitTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. ++type EmitTransactorRaw struct { ++ Contract *EmitTransactor // Generic write-only contract binding to access the raw methods on ++} ++ ++// NewEmit creates a new instance of Emit, bound to a specific deployed contract. ++func NewEmit(address common.Address, backend bind.ContractBackend) (*Emit, error) { ++ contract, err := bindEmit(address, backend, backend, backend) ++ if err != nil { ++ return nil, err ++ } ++ return &Emit{EmitCaller: EmitCaller{contract: contract}, EmitTransactor: EmitTransactor{contract: contract}, EmitFilterer: EmitFilterer{contract: contract}}, nil ++} ++ ++// NewEmitCaller creates a new read-only instance of Emit, bound to a specific deployed contract. ++func NewEmitCaller(address common.Address, caller bind.ContractCaller) (*EmitCaller, error) { ++ contract, err := bindEmit(address, caller, nil, nil) ++ if err != nil { ++ return nil, err ++ } ++ return &EmitCaller{contract: contract}, nil ++} ++ ++// NewEmitTransactor creates a new write-only instance of Emit, bound to a specific deployed contract. ++func NewEmitTransactor(address common.Address, transactor bind.ContractTransactor) (*EmitTransactor, error) { ++ contract, err := bindEmit(address, nil, transactor, nil) ++ if err != nil { ++ return nil, err ++ } ++ return &EmitTransactor{contract: contract}, nil ++} ++ ++// NewEmitFilterer creates a new log filterer instance of Emit, bound to a specific deployed contract. ++func NewEmitFilterer(address common.Address, filterer bind.ContractFilterer) (*EmitFilterer, error) { ++ contract, err := bindEmit(address, nil, nil, filterer) ++ if err != nil { ++ return nil, err ++ } ++ return &EmitFilterer{contract: contract}, nil ++} ++ ++// bindEmit binds a generic wrapper to an already deployed contract. ++func bindEmit(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { ++ parsed, err := EmitMetaData.GetAbi() ++ if err != nil { ++ return nil, err ++ } ++ return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil ++} ++ ++// Call invokes the (constant) contract method with params as input values and ++// sets the output to result. The result type might be a single field for simple ++// returns, a slice of interfaces for anonymous returns and a struct for named ++// returns. ++func (_Emit *EmitRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { ++ return _Emit.Contract.EmitCaller.contract.Call(opts, result, method, params...) ++} ++ ++// Transfer initiates a plain transaction to move funds to the contract, calling ++// its default method if one is available. ++func (_Emit *EmitRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { ++ return _Emit.Contract.EmitTransactor.contract.Transfer(opts) ++} ++ ++// Transact invokes the (paid) contract method with params as input values. ++func (_Emit *EmitRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { ++ return _Emit.Contract.EmitTransactor.contract.Transact(opts, method, params...) ++} ++ ++// Call invokes the (constant) contract method with params as input values and ++// sets the output to result. The result type might be a single field for simple ++// returns, a slice of interfaces for anonymous returns and a struct for named ++// returns. ++func (_Emit *EmitCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { ++ return _Emit.Contract.contract.Call(opts, result, method, params...) ++} ++ ++// Transfer initiates a plain transaction to move funds to the contract, calling ++// its default method if one is available. ++func (_Emit *EmitTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { ++ return _Emit.Contract.contract.Transfer(opts) ++} ++ ++// Transact invokes the (paid) contract method with params as input values. ++func (_Emit *EmitTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { ++ return _Emit.Contract.contract.Transact(opts, method, params...) ++} ++ ++// EmitData is a paid mutator transaction binding the contract method 0xd836083e. ++// ++// Solidity: function emitData(bytes _data) returns() ++func (_Emit *EmitTransactor) EmitData(opts *bind.TransactOpts, _data []byte) (*types.Transaction, error) { ++ return _Emit.contract.Transact(opts, "emitData", _data) ++} ++ ++// EmitData is a paid mutator transaction binding the contract method 0xd836083e. ++// ++// Solidity: function emitData(bytes _data) returns() ++func (_Emit *EmitSession) EmitData(_data []byte) (*types.Transaction, error) { ++ return _Emit.Contract.EmitData(&_Emit.TransactOpts, _data) ++} ++ ++// EmitData is a paid mutator transaction binding the contract method 0xd836083e. ++// ++// Solidity: function emitData(bytes _data) returns() ++func (_Emit *EmitTransactorSession) EmitData(_data []byte) (*types.Transaction, error) { ++ return _Emit.Contract.EmitData(&_Emit.TransactOpts, _data) ++} ++ ++// EmitDataEmittedIterator is returned from FilterDataEmitted and is used to iterate over the raw logs and unpacked data for DataEmitted events raised by the Emit contract. ++type EmitDataEmittedIterator struct { ++ Event *EmitDataEmitted // Event containing the contract specifics and raw log ++ ++ contract *bind.BoundContract // Generic contract to use for unpacking event data ++ event string // Event name to use for unpacking event data ++ ++ logs chan types.Log // Log channel receiving the found contract events ++ sub ethereum.Subscription // Subscription for errors, completion and termination ++ done bool // Whether the subscription completed delivering logs ++ fail error // Occurred error to stop iteration ++} ++ ++// Next advances the iterator to the subsequent event, returning whether there ++// are any more events found. In case of a retrieval or parsing error, false is ++// returned and Error() can be queried for the exact failure. ++func (it *EmitDataEmittedIterator) Next() bool { ++ // If the iterator failed, stop iterating ++ if it.fail != nil { ++ return false ++ } ++ // If the iterator completed, deliver directly whatever's available ++ if it.done { ++ select { ++ case log := <-it.logs: ++ it.Event = new(EmitDataEmitted) ++ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { ++ it.fail = err ++ return false ++ } ++ it.Event.Raw = log ++ return true ++ ++ default: ++ return false ++ } ++ } ++ // Iterator still in progress, wait for either a data or an error event ++ select { ++ case log := <-it.logs: ++ it.Event = new(EmitDataEmitted) ++ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { ++ it.fail = err ++ return false ++ } ++ it.Event.Raw = log ++ return true ++ ++ case err := <-it.sub.Err(): ++ it.done = true ++ it.fail = err ++ return it.Next() ++ } ++} ++ ++// Error returns any retrieval or parsing error occurred during filtering. ++func (it *EmitDataEmittedIterator) Error() error { ++ return it.fail ++} ++ ++// Close terminates the iteration process, releasing any pending underlying ++// resources. ++func (it *EmitDataEmittedIterator) Close() error { ++ it.sub.Unsubscribe() ++ return nil ++} ++ ++// EmitDataEmitted represents a DataEmitted event raised by the Emit contract. ++type EmitDataEmitted struct { ++ Data common.Hash ++ Raw types.Log // Blockchain specific contextual infos ++} ++ ++// FilterDataEmitted is a free log retrieval operation binding the contract event 0xe00bbfe6f6f8f1bbed2da38e3f5a139c6f9da594ab248a3cf8b44fc73627772c. ++// ++// Solidity: event DataEmitted(bytes indexed _data) ++func (_Emit *EmitFilterer) FilterDataEmitted(opts *bind.FilterOpts, _data [][]byte) (*EmitDataEmittedIterator, error) { ++ ++ var _dataRule []interface{} ++ for _, _dataItem := range _data { ++ _dataRule = append(_dataRule, _dataItem) ++ } ++ ++ logs, sub, err := _Emit.contract.FilterLogs(opts, "DataEmitted", _dataRule) ++ if err != nil { ++ return nil, err ++ } ++ return &EmitDataEmittedIterator{contract: _Emit.contract, event: "DataEmitted", logs: logs, sub: sub}, nil ++} ++ ++// WatchDataEmitted is a free log subscription operation binding the contract event 0xe00bbfe6f6f8f1bbed2da38e3f5a139c6f9da594ab248a3cf8b44fc73627772c. ++// ++// Solidity: event DataEmitted(bytes indexed _data) ++func (_Emit *EmitFilterer) WatchDataEmitted(opts *bind.WatchOpts, sink chan<- *EmitDataEmitted, _data [][]byte) (event.Subscription, error) { ++ ++ var _dataRule []interface{} ++ for _, _dataItem := range _data { ++ _dataRule = append(_dataRule, _dataItem) ++ } ++ ++ logs, sub, err := _Emit.contract.WatchLogs(opts, "DataEmitted", _dataRule) ++ if err != nil { ++ return nil, err ++ } ++ return event.NewSubscription(func(quit <-chan struct{}) error { ++ defer sub.Unsubscribe() ++ for { ++ select { ++ case log := <-logs: ++ // New log arrived, parse the event and forward to the user ++ event := new(EmitDataEmitted) ++ if err := _Emit.contract.UnpackLog(event, "DataEmitted", log); err != nil { ++ return err ++ } ++ event.Raw = log ++ ++ select { ++ case sink <- event: ++ case err := <-sub.Err(): ++ return err ++ case <-quit: ++ return nil ++ } ++ case err := <-sub.Err(): ++ return err ++ case <-quit: ++ return nil ++ } ++ } ++ }), nil ++} ++ ++// ParseDataEmitted is a log parse operation binding the contract event 0xe00bbfe6f6f8f1bbed2da38e3f5a139c6f9da594ab248a3cf8b44fc73627772c. ++// ++// Solidity: event DataEmitted(bytes indexed _data) ++func (_Emit *EmitFilterer) ParseDataEmitted(log types.Log) (*EmitDataEmitted, error) { ++ event := new(EmitDataEmitted) ++ if err := _Emit.contract.UnpackLog(event, "DataEmitted", log); err != nil { ++ return nil, err ++ } ++ event.Raw = log ++ return event, nil ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+31
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/interop/contracts/foundry.toml CELO/op-e2e/interop/contracts/foundry.toml +new file mode 100644 +index 0000000000000000000000000000000000000000..587dba436380c3a040693308253e083d7f7b086d +--- /dev/null ++++ CELO/op-e2e/interop/contracts/foundry.toml +@@ -0,0 +1,31 @@ ++################################################################ ++# PROFILE: DEFAULT (Local) # ++################################################################ ++ ++[profile.default] ++ ++# Compilation settings ++src = 'src' ++out = 'build' ++script = 'scripts' ++optimizer = true ++optimizer_runs = 999999 ++remappings = [] ++extra_output = ['devdoc', 'userdoc', 'metadata', 'storageLayout'] ++bytecode_hash = 'none' ++build_info_path = 'artifacts/build-info' ++ast = true ++evm_version = "cancun" ++# 5159 error code is selfdestruct error code ++ignored_error_codes = ["transient-storage", "code-size", "init-code-size", 5159] ++ ++# We set the gas limit to max int64 to avoid running out of gas during testing, since the default ++# gas limit is 1B and some of our tests require more gas than that, such as `test_callWithMinGas_noLeakageLow_succeeds`. ++# We use this gas limit since it was the default gas limit prior to https://github.com/foundry-rs/foundry/pull/8274. ++# Due to toml-rs limitations, if you increase the gas limit above this value it must be a string. ++gas_limit = 9223372036854775807 ++ ++# Test / Script Runner Settings ++ffi = false ++fs_permissions = [] ++libs = ["node_modules", "lib"]
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+12
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/interop/contracts/generate.sh CELO/op-e2e/interop/contracts/generate.sh +new file mode 100755 +index 0000000000000000000000000000000000000000..bba960153ec62f7fe54b96f1f8cca29cd6f157a8 +--- /dev/null ++++ CELO/op-e2e/interop/contracts/generate.sh +@@ -0,0 +1,12 @@ ++#!/bin/sh ++ ++set -euo ++ ++forge build ++ ++cd build/emit.sol ++cat EmitEvent.json | jq -r '.bytecode.object' > EmitEvent.bin ++cat EmitEvent.json | jq '.abi' > EmitEvent.abi ++cd ../.. ++ ++abigen --abi ./build/emit.sol/EmitEvent.abi --bin ./build/emit.sol/EmitEvent.bin --pkg emit --out ./emit.go
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+12
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/interop/contracts/src/emit.sol CELO/op-e2e/interop/contracts/src/emit.sol +new file mode 100644 +index 0000000000000000000000000000000000000000..5464bb7bbe6e68c960ea7abf1dd5f55558e32b92 +--- /dev/null ++++ CELO/op-e2e/interop/contracts/src/emit.sol +@@ -0,0 +1,12 @@ ++// SPDX-License-Identifier: MIT ++pragma solidity ^0.8.15; ++ ++contract EmitEvent { ++ // Define an event that logs the emitted data ++ event DataEmitted(bytes indexed _data); ++ ++ // Function that takes calldata and emits the data as an event ++ function emitData(bytes calldata _data) external { ++ emit DataEmitted(_data); + } ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+46
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/interop/interop_recipe_test.go CELO/op-e2e/interop/interop_recipe_test.go +new file mode 100644 +index 0000000000000000000000000000000000000000..16c846950d50f52ac3615c3ef3934655a132444b +--- /dev/null ++++ CELO/op-e2e/interop/interop_recipe_test.go +@@ -0,0 +1,46 @@ ++package interop ++ ++import ( ++ "encoding/json" ++ "os" ++ "testing" ++ ++ "github.com/stretchr/testify/require" ++ ++ "github.com/ethereum/go-ethereum/log" ++ ++ "github.com/ethereum-optimism/optimism/op-chain-ops/devkeys" ++ "github.com/ethereum-optimism/optimism/op-chain-ops/foundry" ++ "github.com/ethereum-optimism/optimism/op-chain-ops/interopgen" ++ "github.com/ethereum-optimism/optimism/op-service/testlog" ++) ++ ++func TestInteropDevRecipe(t *testing.T) { ++ t.Skipf("Skipping interop tests for now. Celo doesn't use interop, so we can fix these tests at a later time") ++ ++ rec := interopgen.InteropDevRecipe{ ++ L1ChainID: 900100, ++ L2ChainIDs: []uint64{900200, 900201}, ++ GenesisTimestamp: uint64(1234567), ++ } ++ hd, err := devkeys.NewMnemonicDevKeys(devkeys.TestMnemonic) ++ require.NoError(t, err) ++ worldCfg, err := rec.Build(hd) ++ require.NoError(t, err) ++ ++ logger := testlog.Logger(t, log.LevelDebug) ++ require.NoError(t, worldCfg.Check(logger)) ++ ++ fa := foundry.OpenArtifactsDir("../../packages/contracts-bedrock/forge-artifacts") ++ srcFS := foundry.NewSourceMapFS(os.DirFS("../../packages/contracts-bedrock")) ++ ++ worldDeployment, worldOutput, err := interopgen.Deploy(logger, fa, srcFS, worldCfg) ++ require.NoError(t, err) ++ enc := json.NewEncoder(os.Stdout) ++ enc.SetIndent(" ", " ") ++ require.NoError(t, enc.Encode(worldDeployment)) ++ logger.Info("L1 output", "accounts", len(worldOutput.L1.Genesis.Alloc)) ++ for id, l2Output := range worldOutput.L2s { ++ logger.Info("L2 output", "chain", &id, "accounts", len(l2Output.Genesis.Alloc)) ++ } ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+102
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/interop/interop_test.go CELO/op-e2e/interop/interop_test.go +new file mode 100644 +index 0000000000000000000000000000000000000000..1a8afae71aa240fc9c40788e64d6d30181ef6f9b +--- /dev/null ++++ CELO/op-e2e/interop/interop_test.go +@@ -0,0 +1,102 @@ ++package interop ++ ++import ( ++ "context" ++ "fmt" ++ "math/big" ++ "testing" ++ "time" ++ ++ "github.com/stretchr/testify/require" ++ ++ "github.com/ethereum-optimism/optimism/op-chain-ops/interopgen" ++ "github.com/ethereum-optimism/optimism/op-e2e/system/helpers" ++) ++ ++// TestInteropTrivial tests a simple interop scenario ++// Chains A and B exist, but no messages are sent between them ++// and in fact no event-logs are emitted by either chain at all. ++// A transaction is sent from Alice to Bob on Chain A. ++// The balance of Bob on Chain A is checked before and after the tx. ++// The balance of Bob on Chain B is checked after the tx. ++func TestInteropTrivial(t *testing.T) { ++ t.Skipf("Skipping interop tests for now. Celo doesn't use interop, so we can fix these tests at a later time") ++ ++ recipe := interopgen.InteropDevRecipe{ ++ L1ChainID: 900100, ++ L2ChainIDs: []uint64{900200, 900201}, ++ GenesisTimestamp: uint64(time.Now().Unix() + 3), // start chain 3 seconds from now ++ } ++ worldResources := worldResourcePaths{ ++ foundryArtifacts: "../../packages/contracts-bedrock/forge-artifacts", ++ sourceMap: "../../packages/contracts-bedrock", ++ } ++ ++ // create a super system from the recipe ++ // and get the L2 IDs for use in the test ++ s2 := NewSuperSystem(t, &recipe, worldResources) ++ ids := s2.L2IDs() ++ ++ // chainA is the first L2 chain ++ chainA := ids[0] ++ // chainB is the second L2 chain ++ chainB := ids[1] ++ ++ // create two users on all L2 chains ++ s2.AddUser("Alice") ++ s2.AddUser("Bob") ++ ++ bobAddr := s2.Address(chainA, "Bob") ++ ++ // check the balance of Bob ++ clientA := s2.L2GethClient(chainA) ++ ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) ++ defer cancel() ++ bobBalance, err := clientA.BalanceAt(ctx, bobAddr, nil) ++ require.NoError(t, err) ++ expectedBalance, _ := big.NewInt(0).SetString("10000000000000000000000000", 10) ++ require.Equal(t, expectedBalance, bobBalance) ++ ++ // send a tx from Alice to Bob ++ s2.SendL2Tx( ++ chainA, ++ "Alice", ++ func(l2Opts *helpers.TxOpts) { ++ l2Opts.ToAddr = &bobAddr ++ l2Opts.Value = big.NewInt(1000000) ++ l2Opts.GasFeeCap = big.NewInt(1_000_000_000) ++ l2Opts.GasTipCap = big.NewInt(1_000_000_000) ++ }, ++ ) ++ ++ // check the balance of Bob after the tx ++ ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second) ++ defer cancel() ++ bobBalance, err = clientA.BalanceAt(ctx, bobAddr, nil) ++ require.NoError(t, err) ++ expectedBalance, _ = big.NewInt(0).SetString("10000000000000000001000000", 10) ++ require.Equal(t, expectedBalance, bobBalance) ++ ++ // check that the balance of Bob on ChainB hasn't changed ++ bobAddrB := s2.Address(chainB, "Bob") ++ clientB := s2.L2GethClient(chainB) ++ ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second) ++ defer cancel() ++ bobBalance, err = clientB.BalanceAt(ctx, bobAddrB, nil) ++ require.NoError(t, err) ++ expectedBalance, _ = big.NewInt(0).SetString("10000000000000000000000000", 10) ++ require.Equal(t, expectedBalance, bobBalance) ++ ++ s2.DeployEmitterContract(chainA, "Alice") ++ rec := s2.EmitData(chainA, "Alice", "0x1234567890abcdef") ++ ++ fmt.Println("Result of emitting event:", rec) ++ ++ s2.DeployEmitterContract(chainB, "Alice") ++ rec = s2.EmitData(chainB, "Alice", "0x1234567890abcdef") ++ ++ fmt.Println("Result of emitting event:", rec) ++ ++ time.Sleep(10 * time.Second) ++ ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+678
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/interop/supersystem.go CELO/op-e2e/interop/supersystem.go +new file mode 100644 +index 0000000000000000000000000000000000000000..ffa91bef97f306e7de42fe329ee2aafd6c5fb8fd +--- /dev/null ++++ CELO/op-e2e/interop/supersystem.go +@@ -0,0 +1,678 @@ ++package interop ++ ++import ( ++ "context" ++ "crypto/ecdsa" ++ "math/big" ++ "os" ++ "path" ++ "path/filepath" ++ "testing" ++ "time" ++ ++ emit "github.com/ethereum-optimism/optimism/op-e2e/interop/contracts" ++ "github.com/ethereum-optimism/optimism/op-e2e/system/helpers" ++ ++ "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" ++ "github.com/stretchr/testify/require" ++ ++ "github.com/ethereum/go-ethereum/accounts/abi/bind" ++ "github.com/ethereum/go-ethereum/common" ++ "github.com/ethereum/go-ethereum/common/hexutil" ++ "github.com/ethereum/go-ethereum/core/types" ++ "github.com/ethereum/go-ethereum/crypto" ++ "github.com/ethereum/go-ethereum/ethclient" ++ "github.com/ethereum/go-ethereum/log" ++ "github.com/ethereum/go-ethereum/rpc" ++ ++ bss "github.com/ethereum-optimism/optimism/op-batcher/batcher" ++ batcherFlags "github.com/ethereum-optimism/optimism/op-batcher/flags" ++ "github.com/ethereum-optimism/optimism/op-chain-ops/devkeys" ++ "github.com/ethereum-optimism/optimism/op-chain-ops/foundry" ++ "github.com/ethereum-optimism/optimism/op-chain-ops/interopgen" ++ "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/fakebeacon" ++ "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" ++ "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/opnode" ++ "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/services" ++ "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/setuputils" ++ "github.com/ethereum-optimism/optimism/op-node/node" ++ "github.com/ethereum-optimism/optimism/op-node/p2p" ++ "github.com/ethereum-optimism/optimism/op-node/rollup/derive" ++ "github.com/ethereum-optimism/optimism/op-node/rollup/driver" ++ "github.com/ethereum-optimism/optimism/op-node/rollup/sync" ++ l2os "github.com/ethereum-optimism/optimism/op-proposer/proposer" ++ "github.com/ethereum-optimism/optimism/op-service/client" ++ "github.com/ethereum-optimism/optimism/op-service/clock" ++ "github.com/ethereum-optimism/optimism/op-service/dial" ++ "github.com/ethereum-optimism/optimism/op-service/endpoint" ++ oplog "github.com/ethereum-optimism/optimism/op-service/log" ++ "github.com/ethereum-optimism/optimism/op-service/metrics" ++ "github.com/ethereum-optimism/optimism/op-service/oppprof" ++ oprpc "github.com/ethereum-optimism/optimism/op-service/rpc" ++ "github.com/ethereum-optimism/optimism/op-service/sources" ++ "github.com/ethereum-optimism/optimism/op-service/testlog" ++ supervisorConfig "github.com/ethereum-optimism/optimism/op-supervisor/config" ++ "github.com/ethereum-optimism/optimism/op-supervisor/supervisor" ++) ++ ++// SuperSystem is an interface for the system (collection of connected resources) ++// it provides a way to get the resources for a network by network ID ++// and provides a way to get the list of network IDs ++// this is useful for testing multiple network backends, ++// for example, interopE2ESystem is the default implementation, but a shim to ++// kurtosis or another testing framework could be implemented ++type SuperSystem interface { ++ // get the supervisor ++ Supervisor() *supervisor.SupervisorService ++ // get the supervisor client ++ SupervisorClient() *sources.SupervisorClient ++ // get the batcher for a network ++ Batcher(network string) *bss.BatcherService ++ // get the proposer for a network ++ Proposer(network string) *l2os.ProposerService ++ // get the opnode for a network ++ OpNode(network string) *opnode.Opnode ++ // get the geth instance for a network ++ L2Geth(network string) *geth.GethInstance ++ // get the L2 geth client for a network ++ L2GethClient(network string) *ethclient.Client ++ // get the secret for a network and role ++ L2OperatorKey(network string, role devkeys.ChainOperatorRole) ecdsa.PrivateKey ++ // get the list of network IDs ++ L2IDs() []string ++ // register a username to an account on all L2s ++ AddUser(username string) ++ // get the user key for a user on an L2 ++ UserKey(id, username string) ecdsa.PrivateKey ++ // send a transaction on an L2 on the given network, from the given user ++ SendL2Tx(network string, username string, applyTxOpts helpers.TxOptsFn) *types.Receipt ++ // get the address for a user on an L2 ++ Address(network string, username string) common.Address ++ // Deploy the Emitter Contract, which emits Event Logs ++ DeployEmitterContract(network string, username string) common.Address ++ // Use the Emitter Contract to emit an Event Log ++ EmitData(network string, username string, data string) *types.Receipt ++ // Access a contract on a network by name ++ Contract(network string, contractName string) interface{} ++} ++ ++// NewSuperSystem creates a new SuperSystem from a recipe. It creates an interopE2ESystem. ++func NewSuperSystem(t *testing.T, recipe *interopgen.InteropDevRecipe, w worldResourcePaths) SuperSystem { ++ s2 := &interopE2ESystem{recipe: recipe} ++ s2.prepare(t, w) ++ return s2 ++} ++ ++// interopE2ESystem implements the SuperSystem interface ++// it prepares network resources and provides access to them ++// the functionality is broken down into smaller functions so that ++// the system can be prepared iteratively if desired ++type interopE2ESystem struct { ++ t *testing.T ++ recipe *interopgen.InteropDevRecipe ++ logger log.Logger ++ hdWallet *devkeys.MnemonicDevKeys ++ worldDeployment *interopgen.WorldDeployment ++ worldOutput *interopgen.WorldOutput ++ beacon *fakebeacon.FakeBeacon ++ l1 *geth.GethInstance ++ l2s map[string]l2Set ++ l2GethClients map[string]*ethclient.Client ++ supervisor *supervisor.SupervisorService ++ superClient *sources.SupervisorClient ++} ++ ++// l2Set is a set of resources for an L2 chain ++type l2Set struct { ++ chainID *big.Int ++ opNode *opnode.Opnode ++ l2Geth *geth.GethInstance ++ proposer *l2os.ProposerService ++ batcher *bss.BatcherService ++ operatorKeys map[devkeys.ChainOperatorRole]ecdsa.PrivateKey ++ userKeys map[string]ecdsa.PrivateKey ++ contracts map[string]interface{} ++} ++ ++// prepareHDWallet creates a new HD wallet to derive keys from ++func (s *interopE2ESystem) prepareHDWallet() *devkeys.MnemonicDevKeys { ++ hdWallet, err := devkeys.NewMnemonicDevKeys(devkeys.TestMnemonic) ++ require.NoError(s.t, err) ++ return hdWallet ++} ++ ++type worldResourcePaths struct { ++ foundryArtifacts string ++ sourceMap string ++} ++ ++// prepareWorld creates the world configuration from the recipe and deploys it ++func (s *interopE2ESystem) prepareWorld(w worldResourcePaths) (*interopgen.WorldDeployment, *interopgen.WorldOutput) { ++ // Build the world configuration from the recipe and the HD wallet ++ worldCfg, err := s.recipe.Build(s.hdWallet) ++ require.NoError(s.t, err) ++ ++ // create a logger for the world configuration ++ logger := s.logger.New("role", "world") ++ require.NoError(s.t, worldCfg.Check(logger)) ++ ++ // create the foundry artifacts and source map ++ foundryArtifacts := foundry.OpenArtifactsDir(w.foundryArtifacts) ++ sourceMap := foundry.NewSourceMapFS(os.DirFS(w.sourceMap)) ++ ++ // deploy the world, using the logger, foundry artifacts, source map, and world configuration ++ worldDeployment, worldOutput, err := interopgen.Deploy(logger, foundryArtifacts, sourceMap, worldCfg) ++ require.NoError(s.t, err) ++ ++ return worldDeployment, worldOutput ++} ++ ++// prepareL1 creates the L1 chain resources ++func (s *interopE2ESystem) prepareL1() (*fakebeacon.FakeBeacon, *geth.GethInstance) { ++ // Create a fake Beacon node to hold on to blobs created by the L1 miner, and to serve them to L2 ++ genesisTimestampL1 := s.worldOutput.L1.Genesis.Timestamp ++ blockTimeL1 := uint64(6) ++ blobPath := s.t.TempDir() ++ bcn := fakebeacon.NewBeacon(s.logger.New("role", "l1_cl"), ++ e2eutils.NewBlobStore(), genesisTimestampL1, blockTimeL1) ++ s.t.Cleanup(func() { ++ _ = bcn.Close() ++ }) ++ require.NoError(s.t, bcn.Start("127.0.0.1:0")) ++ beaconApiAddr := bcn.BeaconAddr() ++ require.NotEmpty(s.t, beaconApiAddr, "beacon API listener must be up") ++ ++ l1FinalizedDistance := uint64(3) ++ l1Clock := clock.SystemClock ++ // Start the L1 chain ++ l1Geth, err := geth.InitL1( ++ blockTimeL1, ++ l1FinalizedDistance, ++ s.worldOutput.L1.Genesis, ++ l1Clock, ++ filepath.Join(blobPath, "l1_el"), ++ bcn) ++ ++ require.NoError(s.t, err) ++ require.NoError(s.t, l1Geth.Node.Start()) ++ s.t.Cleanup(func() { ++ _ = l1Geth.Close() ++ }) ++ return bcn, l1Geth ++} ++ ++// newOperatorKeysForL2 creates the operator keys for an L2 chain ++// it uses an L2Output to determine the chain ID and configuration, ++// and then makes a key for each operator role [SequencerP2PRole, ProposerRole, BatcherRole] ++func (s *interopE2ESystem) newOperatorKeysForL2(l2Out *interopgen.L2Output) map[devkeys.ChainOperatorRole]ecdsa.PrivateKey { ++ // Create operatorKeys for the L2 chain actors ++ operatorKeys := map[devkeys.ChainOperatorRole]ecdsa.PrivateKey{} ++ // create the sequencer P2P secret ++ seqP2PSecret, err := s.hdWallet.Secret(devkeys.ChainOperatorKey{ ++ ChainID: l2Out.Genesis.Config.ChainID, ++ Role: devkeys.SequencerP2PRole, ++ }) ++ require.NoError(s.t, err) ++ operatorKeys[devkeys.SequencerP2PRole] = *seqP2PSecret ++ // create the proposer secret ++ proposerSecret, err := s.hdWallet.Secret(devkeys.ChainOperatorKey{ ++ ChainID: l2Out.Genesis.Config.ChainID, ++ Role: devkeys.ProposerRole, ++ }) ++ require.NoError(s.t, err) ++ operatorKeys[devkeys.ProposerRole] = *proposerSecret ++ // create the batcher secret ++ batcherSecret, err := s.hdWallet.Secret(devkeys.ChainOperatorKey{ ++ ChainID: l2Out.Genesis.Config.ChainID, ++ Role: devkeys.BatcherRole, ++ }) ++ require.NoError(s.t, err) ++ operatorKeys[devkeys.BatcherRole] = *batcherSecret ++ return operatorKeys ++} ++ ++// newGethForL2 creates a new Geth instance for an L2 chain ++func (s *interopE2ESystem) newGethForL2(id string, l2Out *interopgen.L2Output) *geth.GethInstance { ++ jwtPath := writeDefaultJWT(s.t) ++ name := "l2-" + id ++ l2Geth, err := geth.InitL2(name, l2Out.Genesis, jwtPath) ++ require.NoError(s.t, err) ++ require.NoError(s.t, l2Geth.Node.Start()) ++ s.t.Cleanup(func() { ++ _ = l2Geth.Close() ++ }) ++ return l2Geth ++} ++ ++// newNodeForL2 creates a new Opnode for an L2 chain ++func (s *interopE2ESystem) newNodeForL2( ++ id string, ++ l2Out *interopgen.L2Output, ++ operatorKeys map[devkeys.ChainOperatorRole]ecdsa.PrivateKey, ++ l2Geth *geth.GethInstance, ++) *opnode.Opnode { ++ logger := s.logger.New("role", "op-node-"+id) ++ p2pKey := operatorKeys[devkeys.SequencerP2PRole] ++ nodeCfg := &node.Config{ ++ L1: &node.PreparedL1Endpoint{ ++ Client: client.NewBaseRPCClient(endpoint.DialRPC( ++ endpoint.PreferAnyRPC, ++ s.l1.UserRPC(), ++ mustDial(s.t, logger))), ++ TrustRPC: false, ++ RPCProviderKind: sources.RPCKindDebugGeth, ++ }, ++ L2: &node.L2EndpointConfig{ ++ L2EngineAddr: l2Geth.AuthRPC().RPC(), ++ L2EngineJWTSecret: testingJWTSecret, ++ }, ++ Beacon: &node.L1BeaconEndpointConfig{ ++ BeaconAddr: s.beacon.BeaconAddr(), ++ }, ++ Driver: driver.Config{ ++ SequencerEnabled: true, ++ }, ++ Rollup: *l2Out.RollupCfg, ++ P2PSigner: &p2p.PreparedSigner{ ++ Signer: p2p.NewLocalSigner(&p2pKey)}, ++ RPC: node.RPCConfig{ ++ ListenAddr: "127.0.0.1", ++ ListenPort: 0, ++ EnableAdmin: true, ++ }, ++ Supervisor: &node.SupervisorEndpointConfig{ ++ SupervisorAddr: s.supervisor.RPC(), ++ }, ++ P2P: nil, // disabled P2P setup for now ++ L1EpochPollInterval: time.Second * 2, ++ RuntimeConfigReloadInterval: 0, ++ Tracer: nil, ++ Sync: sync.Config{ ++ SyncMode: sync.CLSync, ++ SkipSyncStartCheck: false, ++ SupportsPostFinalizationELSync: false, ++ }, ++ ConfigPersistence: node.DisabledConfigPersistence{}, ++ } ++ opNode, err := opnode.NewOpnode(logger.New("service", "op-node"), ++ nodeCfg, func(err error) { ++ s.t.Error(err) ++ }) ++ require.NoError(s.t, err) ++ s.t.Cleanup(func() { ++ ctx, cancel := context.WithCancel(context.Background()) ++ cancel() // force-quit ++ _ = opNode.Stop(ctx) ++ }) ++ return opNode ++} ++ ++// newProposerForL2 creates a new Proposer for an L2 chain ++// it is currently unused, as the generated world does not have a DisputeGameFactoryProxy ++// TODO(#11888): name this function "newProposerForL2" and use it in the prepareL2s function when the DisputeGameFactoryProxy is available ++func (s *interopE2ESystem) _( ++ id string, ++ operatorKeys map[devkeys.ChainOperatorRole]ecdsa.PrivateKey, ++ opNode *opnode.Opnode, ++) *l2os.ProposerService { ++ proposerSecret := operatorKeys[devkeys.ProposerRole] ++ logger := s.logger.New("role", "proposer"+id) ++ proposerCLIConfig := &l2os.CLIConfig{ ++ L1EthRpc: s.l1.UserRPC().RPC(), ++ RollupRpc: opNode.UserRPC().RPC(), ++ DGFAddress: s.worldDeployment.L2s[id].DisputeGameFactoryProxy.Hex(), ++ ProposalInterval: 6 * time.Second, ++ DisputeGameType: 254, // Fast game type ++ PollInterval: 500 * time.Millisecond, ++ TxMgrConfig: setuputils.NewTxMgrConfig(s.l1.UserRPC(), &proposerSecret), ++ AllowNonFinalized: false, ++ LogConfig: oplog.CLIConfig{ ++ Level: log.LvlInfo, ++ Format: oplog.FormatText, ++ }, ++ } ++ proposer, err := l2os.ProposerServiceFromCLIConfig( ++ context.Background(), ++ "0.0.1", ++ proposerCLIConfig, ++ logger.New("service", "proposer")) ++ require.NoError(s.t, err, "must start proposer") ++ require.NoError(s.t, proposer.Start(context.Background())) ++ s.t.Cleanup(func() { ++ ctx, cancel := context.WithCancel(context.Background()) ++ cancel() // force-quit ++ _ = proposer.Stop(ctx) ++ }) ++ return proposer ++} ++ ++// newBatcherForL2 creates a new Batcher for an L2 chain ++func (s *interopE2ESystem) newBatcherForL2( ++ id string, ++ operatorKeys map[devkeys.ChainOperatorRole]ecdsa.PrivateKey, ++ l2Geth *geth.GethInstance, ++ opNode *opnode.Opnode, ++) *bss.BatcherService { ++ batcherSecret := operatorKeys[devkeys.BatcherRole] ++ logger := s.logger.New("role", "batcher"+id) ++ batcherCLIConfig := &bss.CLIConfig{ ++ L1EthRpc: s.l1.UserRPC().RPC(), ++ L2EthRpc: l2Geth.UserRPC().RPC(), ++ RollupRpc: opNode.UserRPC().RPC(), ++ MaxPendingTransactions: 1, ++ MaxChannelDuration: 1, ++ MaxL1TxSize: 120_000, ++ TestUseMaxTxSizeForBlobs: false, ++ TargetNumFrames: 1, ++ ApproxComprRatio: 0.4, ++ SubSafetyMargin: 4, ++ PollInterval: 50 * time.Millisecond, ++ TxMgrConfig: setuputils.NewTxMgrConfig(s.l1.UserRPC(), &batcherSecret), ++ LogConfig: oplog.CLIConfig{ ++ Level: log.LevelInfo, ++ Format: oplog.FormatText, ++ }, ++ Stopped: false, ++ BatchType: derive.SpanBatchType, ++ MaxBlocksPerSpanBatch: 10, ++ DataAvailabilityType: batcherFlags.CalldataType, ++ CompressionAlgo: derive.Brotli, ++ } ++ batcher, err := bss.BatcherServiceFromCLIConfig( ++ context.Background(), "0.0.1", batcherCLIConfig, ++ logger.New("service", "batcher")) ++ require.NoError(s.t, err) ++ require.NoError(s.t, batcher.Start(context.Background())) ++ s.t.Cleanup(func() { ++ ctx, cancel := context.WithCancel(context.Background()) ++ cancel() // force-quit ++ _ = batcher.Stop(ctx) ++ }) ++ return batcher ++} ++ ++// newL2 creates a new L2, starting with the L2Output from the world configuration ++// and iterating through the resources needed for the L2. ++// it returns a l2Set with the resources for the L2 ++func (s *interopE2ESystem) newL2(id string, l2Out *interopgen.L2Output) l2Set { ++ operatorKeys := s.newOperatorKeysForL2(l2Out) ++ l2Geth := s.newGethForL2(id, l2Out) ++ opNode := s.newNodeForL2(id, l2Out, operatorKeys, l2Geth) ++ // TODO(#11886): proposer does not work with the generated world as there is no DisputeGameFactoryProxy ++ //proposer := s.newProposerForL2(id, operatorKeys, opNode) ++ batcher := s.newBatcherForL2(id, operatorKeys, l2Geth, opNode) ++ ++ return l2Set{ ++ chainID: l2Out.Genesis.Config.ChainID, ++ opNode: opNode, ++ l2Geth: l2Geth, ++ proposer: nil, ++ batcher: batcher, ++ operatorKeys: operatorKeys, ++ userKeys: make(map[string]ecdsa.PrivateKey), ++ contracts: make(map[string]interface{}), ++ } ++} ++ ++// prepareSupervisor creates a new supervisor for the system ++func (s *interopE2ESystem) prepareSupervisor() *supervisor.SupervisorService { ++ // Be verbose with op-supervisor, it's in early test phase ++ logger := testlog.Logger(s.t, log.LevelDebug).New("role", "supervisor") ++ cfg := supervisorConfig.Config{ ++ MetricsConfig: metrics.CLIConfig{ ++ Enabled: false, ++ }, ++ PprofConfig: oppprof.CLIConfig{ ++ ListenEnabled: false, ++ }, ++ LogConfig: oplog.CLIConfig{ ++ Level: log.LevelDebug, ++ Format: oplog.FormatText, ++ }, ++ RPC: oprpc.CLIConfig{ ++ ListenAddr: "127.0.0.1", ++ ListenPort: 0, ++ EnableAdmin: true, ++ }, ++ L2RPCs: []string{}, ++ Datadir: path.Join(s.t.TempDir(), "supervisor"), ++ } ++ for id := range s.l2s { ++ cfg.L2RPCs = append(cfg.L2RPCs, s.l2s[id].l2Geth.UserRPC().RPC()) ++ } ++ // Create the supervisor with the configuration ++ super, err := supervisor.SupervisorFromConfig(context.Background(), &cfg, logger) ++ require.NoError(s.t, err) ++ // Start the supervisor ++ err = super.Start(context.Background()) ++ require.NoError(s.t, err) ++ s.t.Cleanup(func() { ++ ctx, cancel := context.WithCancel(context.Background()) ++ cancel() // force-quit ++ _ = super.Stop(ctx) ++ }) ++ return super ++} ++ ++// SupervisorClient returns the supervisor client for the system, creating it if it doesn't exist ++func (s *interopE2ESystem) SupervisorClient() *sources.SupervisorClient { ++ if s.superClient != nil { ++ return s.superClient ++ } ++ cl, err := client.NewRPC(context.Background(), s.logger, s.supervisor.RPC()) ++ require.NoError(s.t, err, "failed to dial supervisor RPC") ++ superClient := sources.NewSupervisorClient(cl) ++ s.superClient = superClient ++ return superClient ++} ++ ++// prepare sets up the system for testing ++// components are built iteratively, so that they can be reused or modified ++// their creation can't be safely skipped or reordered at this time ++func (s *interopE2ESystem) prepare(t *testing.T, w worldResourcePaths) { ++ s.t = t ++ s.logger = testlog.Logger(s.t, log.LevelInfo) ++ s.hdWallet = s.prepareHDWallet() ++ s.worldDeployment, s.worldOutput = s.prepareWorld(w) ++ ++ // the supervisor and client are created first so that the L2s can use the supervisor ++ s.supervisor = s.prepareSupervisor() ++ ++ s.beacon, s.l1 = s.prepareL1() ++ s.l2s = s.prepareL2s() ++ ++ // add the L2 RPCs to the supervisor now that the L2s are created ++ ctx := context.Background() ++ for _, l2 := range s.l2s { ++ err := s.SupervisorClient().AddL2RPC(ctx, l2.l2Geth.UserRPC().RPC()) ++ require.NoError(s.t, err, "failed to add L2 RPC to supervisor", "error", err) ++ } ++} ++ ++// AddUser adds a user to the system by creating a user key for each L2. ++// each user key is stored in the L2's userKeys map. ++// because all user maps start empty, a users index should be the same for all L2s, ++// but if in the future these maps can diverge, the indexes for username would also diverge ++// NOTE: The first 20 accounts are implicitly funded by the Recipe's World Deployment ++// see: op-chain-ops/interopgen/recipe.go ++// TODO(#11887): make the funded account quantity specified in the recipe so SuperSystems can know which accounts are funded ++func (s *interopE2ESystem) AddUser(username string) { ++ for id, l2 := range s.l2s { ++ bigID, _ := big.NewInt(0).SetString(id, 10) ++ userSecret, _ := s.hdWallet.Secret( ++ devkeys.ChainUserKey{ ++ ChainID: bigID, ++ Index: uint64(len(l2.userKeys)), ++ }, ++ ) ++ l2.userKeys[username] = *userSecret ++ } ++} ++ ++// UserKey returns the user key for a user on an L2 ++func (s *interopE2ESystem) UserKey(id, username string) ecdsa.PrivateKey { ++ return s.l2s[id].userKeys[username] ++} ++ ++// Address returns the address for a user on an L2 ++func (s *interopE2ESystem) Address(id, username string) common.Address { ++ secret := s.UserKey(id, username) ++ require.NotNil(s.t, secret, "no secret found for user %s", username) ++ return crypto.PubkeyToAddress(secret.PublicKey) ++} ++ ++// prepareL2s creates the L2s for the system, returning a map of L2s ++func (s *interopE2ESystem) prepareL2s() map[string]l2Set { ++ l2s := make(map[string]l2Set) ++ for id, l2Out := range s.worldOutput.L2s { ++ l2s[id] = s.newL2(id, l2Out) ++ } ++ return l2s ++} ++ ++func (s *interopE2ESystem) L2GethClient(id string) *ethclient.Client { ++ // guard: check if the client already exists and return it in that case ++ nodeClient, ok := s.l2GethClients[id] ++ if ok { ++ return nodeClient ++ } ++ // create a new client for the L2 from the L2's geth instance ++ var ethClient services.EthInstance = s.L2Geth(id) ++ rpcEndpoint := ethClient.UserRPC() ++ rpcCl := endpoint.DialRPC( ++ endpoint.PreferAnyRPC, ++ rpcEndpoint, ++ func(v string) *rpc.Client { ++ logger := testlog.Logger(s.t, log.LevelInfo).New("node", id) ++ cl, err := dial.DialRPCClientWithTimeout(context.Background(), 30*time.Second, logger, v) ++ require.NoError(s.t, err, "failed to dial eth node instance %s", id) ++ return cl ++ }) ++ nodeClient = ethclient.NewClient(rpcCl) ++ // register the client so it can be reused ++ s.addL2GethClient(id, nodeClient) ++ return nodeClient ++} ++ ++func (sys *interopE2ESystem) addL2GethClient(name string, client *ethclient.Client) { ++ if sys.l2GethClients == nil { ++ sys.l2GethClients = make(map[string]*ethclient.Client) ++ } ++ sys.l2GethClients[name] = client ++} ++ ++// getter functions for L1 entities ++func (s *interopE2ESystem) Supervisor() *supervisor.SupervisorService { ++ return s.supervisor ++} ++ ++// gettter functions for the individual L2s ++func (s *interopE2ESystem) Batcher(id string) *bss.BatcherService { ++ return s.l2s[id].batcher ++} ++func (s *interopE2ESystem) Proposer(id string) *l2os.ProposerService { ++ return s.l2s[id].proposer ++} ++func (s *interopE2ESystem) OpNode(id string) *opnode.Opnode { ++ return s.l2s[id].opNode ++} ++func (s *interopE2ESystem) L2Geth(id string) *geth.GethInstance { ++ return s.l2s[id].l2Geth ++} ++func (s *interopE2ESystem) L2OperatorKey(id string, role devkeys.ChainOperatorRole) ecdsa.PrivateKey { ++ return s.l2s[id].operatorKeys[role] ++} ++ ++// L2IDs returns the list of L2 IDs, which are the keys of the L2s map ++func (s *interopE2ESystem) L2IDs() []string { ++ ids := make([]string, 0, len(s.l2s)) ++ for id := range s.l2s { ++ ids = append(ids, id) ++ } ++ return ids ++} ++ ++// SendL2Tx sends an L2 transaction to the L2 with the given ID. ++// it acts as a wrapper around op-e2e.SendL2TxWithID ++// and uses the L2's chain ID, username key, and geth client. ++func (s *interopE2ESystem) SendL2Tx( ++ id string, ++ sender string, ++ applyTxOpts helpers.TxOptsFn, ++) *types.Receipt { ++ senderSecret := s.UserKey(id, sender) ++ require.NotNil(s.t, senderSecret, "no secret found for sender %s", sender) ++ nonce, err := s.L2GethClient(id).PendingNonceAt(context.Background(), crypto.PubkeyToAddress(senderSecret.PublicKey)) ++ require.NoError(s.t, err, "failed to get nonce") ++ newApply := func(opts *helpers.TxOpts) { ++ applyTxOpts(opts) ++ opts.Nonce = nonce ++ } ++ return helpers.SendL2TxWithID( ++ s.t, ++ s.l2s[id].chainID, ++ s.L2GethClient(id), ++ &senderSecret, ++ newApply) ++} ++ ++func (s *interopE2ESystem) DeployEmitterContract( ++ id string, ++ sender string, ++) common.Address { ++ secret := s.UserKey(id, sender) ++ auth, err := bind.NewKeyedTransactorWithChainID(&secret, s.l2s[id].chainID) ++ require.NoError(s.t, err) ++ auth.GasLimit = uint64(3000000) ++ auth.GasPrice = big.NewInt(20000000000) ++ address, _, _, err := emit.DeployEmit(auth, s.L2GethClient(id)) ++ require.NoError(s.t, err) ++ contract, err := emit.NewEmit(address, s.L2GethClient(id)) ++ require.NoError(s.t, err) ++ s.l2s[id].contracts["emitter"] = contract ++ return address ++} ++ ++func (s *interopE2ESystem) EmitData( ++ id string, ++ sender string, ++ data string, ++) *types.Receipt { ++ secret := s.UserKey(id, sender) ++ auth, err := bind.NewKeyedTransactorWithChainID(&secret, s.l2s[id].chainID) ++ ++ require.NoError(s.t, err) ++ ++ auth.GasLimit = uint64(3000000) ++ auth.GasPrice = big.NewInt(20000000000) ++ ++ contract := s.Contract(id, "emitter").(*emit.Emit) ++ tx, err := contract.EmitTransactor.EmitData(auth, []byte(data)) ++ require.NoError(s.t, err) ++ receipt, err := bind.WaitMined(context.Background(), s.L2GethClient(id), tx) ++ require.NoError(s.t, err) ++ return receipt ++} ++ ++func (s *interopE2ESystem) Contract(id string, name string) interface{} { ++ return s.l2s[id].contracts[name] ++} ++ ++func mustDial(t *testing.T, logger log.Logger) func(v string) *rpc.Client { ++ return func(v string) *rpc.Client { ++ cl, err := dial.DialRPCClientWithTimeout(context.Background(), 30*time.Second, logger, v) ++ require.NoError(t, err, "failed to dial") ++ return cl ++ } ++} ++ ++var testingJWTSecret = [32]byte{123} ++ ++func writeDefaultJWT(t testing.TB) string { ++ // Sadly the geth node config cannot load JWT secret from memory, it has to be a file ++ jwtPath := path.Join(t.TempDir(), "jwt_secret") ++ if err := os.WriteFile(jwtPath, []byte(hexutil.Encode(testingJWTSecret[:])), 0o600); err != nil { ++ t.Fatalf("failed to prepare jwt file for geth: %v", err) ++ } ++ return jwtPath ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+3
+
-2
+ +
+ +
+
+
diff --git OP/op-e2e/fastlz_test.go CELO/op-e2e/opgeth/fastlz_test.go +rename from op-e2e/fastlz_test.go +rename to op-e2e/opgeth/fastlz_test.go +index 2323764e4678db3e48414f1d0c3ea15cf7311365..5b03ca38eca3c1fa3356e12d5213ff5c185bcc82 100644 +--- OP/op-e2e/fastlz_test.go ++++ CELO/op-e2e/opgeth/fastlz_test.go +@@ -1,7 +1,7 @@ + //go:build cgo_test + // +build cgo_test +  +-package op_e2e ++package opgeth +  + import ( + "context" +@@ -13,6 +13,7 @@ "time" +  + "github.com/ethereum-optimism/optimism/op-e2e/bindings" + "github.com/ethereum-optimism/optimism/op-e2e/fastlz" ++ "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" + "github.com/ethereum-optimism/optimism/op-service/predeploys" + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi/bind" +@@ -79,7 +80,7 @@ for _, seed := range seeds { + f.Add(seed) + } +  +- cfg := DefaultSystemConfig(f) ++ cfg := e2esys.DefaultSystemConfig(f) + s := hexutil.Uint64(0) + cfg.DeployConfig.L2GenesisCanyonTimeOffset = &s + cfg.DeployConfig.L2GenesisDeltaTimeOffset = &s
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+7
+
-5
+ +
+ +
+
+
diff --git OP/op-e2e/op_geth.go CELO/op-e2e/opgeth/op_geth.go +rename from op-e2e/op_geth.go +rename to op-e2e/opgeth/op_geth.go +index e13f42d8e885144ba2462610bb63390f075d7107..1e15eecbd08aebeae6c3212d7a64c855a6a4d2c4 100644 +--- OP/op-e2e/op_geth.go ++++ CELO/op-e2e/opgeth/op_geth.go +@@ -1,4 +1,4 @@ +-package op_e2e ++package opgeth +  + import ( + "context" +@@ -6,6 +6,8 @@ "errors" + "fmt" + "reflect" + "testing" ++ ++ "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" +  + "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" + "github.com/ethereum-optimism/optimism/op-e2e/config" +@@ -51,7 +53,7 @@ sequenceNum uint64 + lgr log.Logger + } +  +-func NewOpGeth(t testing.TB, ctx context.Context, cfg *SystemConfig) (*OpGeth, error) { ++func NewOpGeth(t testing.TB, ctx context.Context, cfg *e2esys.SystemConfig) (*OpGeth, error) { + logger := testlog.Logger(t, log.LevelCrit) +  + l1Genesis, err := genesis.BuildL1DeveloperGenesis(cfg.DeployConfig, config.L1Allocs, config.L1Deployments) +@@ -68,7 +70,7 @@ } else if ecotoneTime := cfg.DeployConfig.EcotoneTime(l1Block.Time()); ecotoneTime != nil && *ecotoneTime <= 0 { + allocsMode = genesis.L2AllocsEcotone + } + l2Allocs := config.L2Allocs(allocsMode) +- l2Genesis, err := genesis.BuildL2Genesis(cfg.DeployConfig, l2Allocs, l1Block) ++ l2Genesis, err := genesis.BuildL2Genesis(cfg.DeployConfig, l2Allocs, l1Block.Header()) + require.NoError(t, err) + l2GenesisBlock := l2Genesis.ToBlock() +  +@@ -92,7 +94,7 @@ require.NoError(t, err) + require.NoError(t, gethNode.Node.Start()) + node = gethNode + } else { +- externalNode := (&ExternalRunner{ ++ externalNode := (&e2esys.ExternalRunner{ + Name: "l2", + BinPath: cfg.ExternalL2Shim, + Genesis: l2Genesis, +@@ -106,7 +108,7 @@ l2Node, err := client.NewRPC(ctx, logger, node.AuthRPC().RPC(), client.WithGethRPCOptions(auth)) + require.NoError(t, err) +  + // Finally create the engine client +- rollupCfg, err := cfg.DeployConfig.RollupConfig(l1Block, l2GenesisBlock.Hash(), l2GenesisBlock.NumberU64()) ++ rollupCfg, err := cfg.DeployConfig.RollupConfig(l1Block.Header(), l2GenesisBlock.Hash(), l2GenesisBlock.NumberU64()) + require.NoError(t, err) + rollupCfg.Genesis = rollupGenesis + l2Engine, err := sources.NewEngineClient(
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+52
+
-48
+ +
+ +
+
+
diff --git OP/op-e2e/op_geth_test.go CELO/op-e2e/opgeth/op_geth_test.go +rename from op-e2e/op_geth_test.go +rename to op-e2e/opgeth/op_geth_test.go +index f34dfb81633b943bfeeefe34b039f8b78e46b21c..0f27e7b7f04738dedffea03be3dd5af87e580232 100644 +--- OP/op-e2e/op_geth_test.go ++++ CELO/op-e2e/opgeth/op_geth_test.go +@@ -1,4 +1,4 @@ +-package op_e2e ++package opgeth +  + import ( + "context" +@@ -6,6 +6,10 @@ "fmt" + "math/big" + "testing" + "time" ++ ++ op_e2e "github.com/ethereum-optimism/optimism/op-e2e" ++ ++ "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" +  + "github.com/ethereum-optimism/optimism/op-node/rollup" + "github.com/ethereum-optimism/optimism/op-node/rollup/derive" +@@ -32,8 +36,8 @@ ) +  + // TestMissingGasLimit tests that op-geth cannot build a block without gas limit while optimism is active in the chain config. + func TestMissingGasLimit(t *testing.T) { +- InitParallel(t) +- cfg := DefaultSystemConfig(t) ++ op_e2e.InitParallel(t) ++ cfg := e2esys.DefaultSystemConfig(t) + ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) + defer cancel() + opGeth, err := NewOpGeth(t, ctx, &cfg) +@@ -55,8 +59,8 @@ + // TestTxGasSameAsBlockGasLimit tests that op-geth rejects transactions that attempt to use the full block gas limit. + // The L1 Info deposit always takes gas so the effective gas limit is lower than the full block gas limit. + func TestTxGasSameAsBlockGasLimit(t *testing.T) { +- InitParallel(t) +- cfg := DefaultSystemConfig(t) ++ op_e2e.InitParallel(t) ++ cfg := e2esys.DefaultSystemConfig(t) + sys, err := cfg.Start(t) + require.Nil(t, err, "Error starting up system") +  +@@ -75,8 +79,8 @@ + // TestInvalidDepositInFCU runs an invalid deposit through a FCU/GetPayload/NewPayload/FCU set of calls. + // This tests that deposits must always allow the block to be built even if they are invalid. + func TestInvalidDepositInFCU(t *testing.T) { +- InitParallel(t) +- cfg := DefaultSystemConfig(t) ++ op_e2e.InitParallel(t) ++ cfg := e2esys.DefaultSystemConfig(t) + ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) + defer cancel() + opGeth, err := NewOpGeth(t, ctx, &cfg) +@@ -115,8 +119,8 @@ // TestGethOnlyPendingBlockIsLatest walks through an engine-API block building job, + // and asserts that the pending block is set to match the latest block at every stage, + // for stability and tx-privacy. + func TestGethOnlyPendingBlockIsLatest(t *testing.T) { +- InitParallel(t) +- cfg := DefaultSystemConfig(t) ++ op_e2e.InitParallel(t) ++ cfg := e2esys.DefaultSystemConfig(t) + cfg.DeployConfig.FundDevAccounts = true + ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) + defer cancel() +@@ -125,7 +129,7 @@ require.NoError(t, err) + defer opGeth.Close() +  + checkPending := func(stage string, number uint64) { +- // TODO(CLI-4044): pending-block ID change ++ // TODO: pending-block ID change + pendingBlock, err := opGeth.L2Client.BlockByNumber(ctx, big.NewInt(-1)) + require.NoError(t, err, "failed to fetch pending block at stage "+stage) + require.Equal(t, number, pendingBlock.NumberU64(), "pending block must have expected number") +@@ -241,10 +245,10 @@ } + for _, test := range tests { + test := test + t.Run("GasUsed_"+test.name, func(t *testing.T) { +- InitParallel(t) ++ op_e2e.InitParallel(t) + // Setup an L2 EE and create a client connection to the engine. + // We also need to setup a L1 Genesis to create the rollup genesis. +- cfg := RegolithSystemConfig(t, test.regolithTime) ++ cfg := e2esys.RegolithSystemConfig(t, test.regolithTime) +  + ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) + defer cancel() +@@ -289,10 +293,10 @@ require.Equal(t, oldBalance, newBalance, "should not repay sender for unused gas") + }) +  + t.Run("DepositNonce_"+test.name, func(t *testing.T) { +- InitParallel(t) ++ op_e2e.InitParallel(t) + // Setup an L2 EE and create a client connection to the engine. + // We also need to setup a L1 Genesis to create the rollup genesis. +- cfg := RegolithSystemConfig(t, test.regolithTime) ++ cfg := e2esys.RegolithSystemConfig(t, test.regolithTime) +  + ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) + defer cancel() +@@ -347,8 +351,8 @@ require.Zero(t, *tx.EffectiveNonce(), "should report 0 as tx nonce") + }) +  + t.Run("UnusedGasConsumed_"+test.name, func(t *testing.T) { +- InitParallel(t) +- cfg := RegolithSystemConfig(t, test.regolithTime) ++ op_e2e.InitParallel(t) ++ cfg := e2esys.RegolithSystemConfig(t, test.regolithTime) +  + ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) + defer cancel() +@@ -388,8 +392,8 @@ require.ErrorContains(t, err, "Invalid payload attributes", "block should be invalid due to using too much gas") + }) +  + t.Run("AllowSystemTx_"+test.name, func(t *testing.T) { +- InitParallel(t) +- cfg := RegolithSystemConfig(t, test.regolithTime) ++ op_e2e.InitParallel(t) ++ cfg := e2esys.RegolithSystemConfig(t, test.regolithTime) +  + ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) + defer cancel() +@@ -424,10 +428,10 @@ } + for _, test := range tests { + test := test + t.Run("GasUsedIsAccurate_"+test.name, func(t *testing.T) { +- InitParallel(t) ++ op_e2e.InitParallel(t) + // Setup an L2 EE and create a client connection to the engine. + // We also need to setup a L1 Genesis to create the rollup genesis. +- cfg := RegolithSystemConfig(t, &test.regolithTime) ++ cfg := e2esys.RegolithSystemConfig(t, &test.regolithTime) +  + ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) + defer cancel() +@@ -475,10 +479,10 @@ require.Equal(t, oldBalance, newBalance, "should not repay sender for unused gas") + }) +  + t.Run("DepositNonceCorrect_"+test.name, func(t *testing.T) { +- InitParallel(t) ++ op_e2e.InitParallel(t) + // Setup an L2 EE and create a client connection to the engine. + // We also need to setup a L1 Genesis to create the rollup genesis. +- cfg := RegolithSystemConfig(t, &test.regolithTime) ++ cfg := e2esys.RegolithSystemConfig(t, &test.regolithTime) +  + ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) + defer cancel() +@@ -536,8 +540,8 @@ require.Empty(t, logs) + }) +  + t.Run("ReturnUnusedGasToPool_"+test.name, func(t *testing.T) { +- InitParallel(t) +- cfg := RegolithSystemConfig(t, &test.regolithTime) ++ op_e2e.InitParallel(t) ++ cfg := e2esys.RegolithSystemConfig(t, &test.regolithTime) +  + ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) + defer cancel() +@@ -578,8 +582,8 @@ require.NoError(t, err, "block should be valid as cumulativeGasUsed only tracks actual usage now") + }) +  + t.Run("RejectSystemTx_"+test.name, func(t *testing.T) { +- InitParallel(t) +- cfg := RegolithSystemConfig(t, &test.regolithTime) ++ op_e2e.InitParallel(t) ++ cfg := e2esys.RegolithSystemConfig(t, &test.regolithTime) +  + ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) + defer cancel() +@@ -600,7 +604,7 @@ require.ErrorIs(t, err, ErrNewPayloadNotValid, "should reject blocks containing system tx") + }) +  + t.Run("IncludeGasRefunds_"+test.name, func(t *testing.T) { +- InitParallel(t) ++ op_e2e.InitParallel(t) + // Simple constructor that is prefixed to the actual contract code + // Results in the contract code being returned as the code for the new contract + deployPrefixSize := byte(16) +@@ -638,7 +642,7 @@ } +  + deployData := append(deployPrefix, sstoreContract...) +  +- cfg := RegolithSystemConfig(t, &test.regolithTime) ++ cfg := e2esys.RegolithSystemConfig(t, &test.regolithTime) +  + ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) + defer cancel() +@@ -735,8 +739,8 @@ for _, test := range tests { + test := test +  + t.Run(fmt.Sprintf("ReturnsNilWithdrawals_%s", test.name), func(t *testing.T) { +- InitParallel(t) +- cfg := CanyonSystemConfig(t, test.canyonTime) ++ op_e2e.InitParallel(t) ++ cfg := e2esys.CanyonSystemConfig(t, test.canyonTime) +  + ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) + defer cancel() +@@ -755,8 +759,8 @@ assert.Equal(t, types.Withdrawals(nil), l1Block.Withdrawals()) + }) +  + t.Run(fmt.Sprintf("RejectPushZeroTx_%s", test.name), func(t *testing.T) { +- InitParallel(t) +- cfg := CanyonSystemConfig(t, test.canyonTime) ++ op_e2e.InitParallel(t) ++ cfg := e2esys.CanyonSystemConfig(t, test.canyonTime) +  + ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) + defer cancel() +@@ -801,8 +805,8 @@ } + for _, test := range tests { + test := test + t.Run(fmt.Sprintf("ReturnsEmptyWithdrawals_%s", test.name), func(t *testing.T) { +- InitParallel(t) +- cfg := CanyonSystemConfig(t, &test.canyonTime) ++ op_e2e.InitParallel(t) ++ cfg := e2esys.CanyonSystemConfig(t, &test.canyonTime) +  + ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) + defer cancel() +@@ -823,8 +827,8 @@ assert.Equal(t, l1Block.Withdrawals(), types.Withdrawals{}) + }) +  + t.Run(fmt.Sprintf("AcceptsPushZeroTxn_%s", test.name), func(t *testing.T) { +- InitParallel(t) +- cfg := CanyonSystemConfig(t, &test.canyonTime) ++ op_e2e.InitParallel(t) ++ cfg := e2esys.CanyonSystemConfig(t, &test.canyonTime) +  + ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) + defer cancel() +@@ -869,8 +873,8 @@ for _, test := range tests { + test := test +  + t.Run(fmt.Sprintf("NilParentBeaconRoot_%s", test.name), func(t *testing.T) { +- InitParallel(t) +- cfg := EcotoneSystemConfig(t, test.ecotoneTime) ++ op_e2e.InitParallel(t) ++ cfg := e2esys.EcotoneSystemConfig(t, test.ecotoneTime) +  + ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) + defer cancel() +@@ -889,8 +893,8 @@ assert.Nil(t, l2Block.Header().ParentBeaconRoot) + }) +  + t.Run(fmt.Sprintf("RejectTstoreTxn_%s", test.name), func(t *testing.T) { +- InitParallel(t) +- cfg := EcotoneSystemConfig(t, test.ecotoneTime) ++ op_e2e.InitParallel(t) ++ cfg := e2esys.EcotoneSystemConfig(t, test.ecotoneTime) +  + ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) + defer cancel() +@@ -937,8 +941,8 @@ } + for _, test := range tests { + test := test + t.Run(fmt.Sprintf("HashParentBeaconBlockRoot_%s", test.name), func(t *testing.T) { +- InitParallel(t) +- cfg := EcotoneSystemConfig(t, &test.ecotoneTime) ++ op_e2e.InitParallel(t) ++ cfg := e2esys.EcotoneSystemConfig(t, &test.ecotoneTime) +  + ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) + defer cancel() +@@ -961,8 +965,8 @@ assert.Equal(t, l2Block.Header().ParentBeaconRoot, opGeth.L1Head.ParentBeaconRoot()) + }) +  + t.Run(fmt.Sprintf("TstoreTxn_%s", test.name), func(t *testing.T) { +- InitParallel(t) +- cfg := EcotoneSystemConfig(t, &test.ecotoneTime) ++ op_e2e.InitParallel(t) ++ cfg := e2esys.EcotoneSystemConfig(t, &test.ecotoneTime) +  + ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) + defer cancel() +@@ -1013,8 +1017,8 @@ for _, test := range tests { + test := test +  + t.Run(fmt.Sprintf("RIP7212_%s", test.name), func(t *testing.T) { +- InitParallel(t) +- cfg := FjordSystemConfig(t, test.fjordTime) ++ op_e2e.InitParallel(t) ++ cfg := e2esys.FjordSystemConfig(t, test.fjordTime) +  + ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) + defer cancel() +@@ -1061,8 +1065,8 @@ + for _, test := range tests { + test := test + t.Run(fmt.Sprintf("RIP7212_%s", test.name), func(t *testing.T) { +- InitParallel(t) +- cfg := FjordSystemConfig(t, &test.fjordTime) ++ op_e2e.InitParallel(t) ++ cfg := e2esys.FjordSystemConfig(t, &test.fjordTime) +  + ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) + defer cancel()
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+11
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/system/altda/altda_test.go CELO/op-e2e/system/altda/altda_test.go +new file mode 100644 +index 0000000000000000000000000000000000000000..9a9546328c0280a878e4b7221fbd9d93053a7d86 +--- /dev/null ++++ CELO/op-e2e/system/altda/altda_test.go +@@ -0,0 +1,11 @@ ++package altda ++ ++import ( ++ "testing" ++ ++ op_e2e "github.com/ethereum-optimism/optimism/op-e2e" ++) ++ ++func TestMain(m *testing.M) { ++ op_e2e.RunMain(m) ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+77
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/system/altda/concurrent_test.go CELO/op-e2e/system/altda/concurrent_test.go +new file mode 100644 +index 0000000000000000000000000000000000000000..4d6835b1fc5518cc57fbb9fbb1e80076ad3eda2f +--- /dev/null ++++ CELO/op-e2e/system/altda/concurrent_test.go +@@ -0,0 +1,77 @@ ++package altda ++ ++import ( ++ "context" ++ "math/big" ++ "testing" ++ "time" ++ ++ op_e2e "github.com/ethereum-optimism/optimism/op-e2e" ++ ++ "github.com/ethereum-optimism/optimism/op-batcher/flags" ++ "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" ++ "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/transactions" ++ "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" ++ "github.com/ethereum-optimism/optimism/op-node/rollup/derive" ++ "github.com/stretchr/testify/require" ++) ++ ++func TestBatcherConcurrentAltDARequests(t *testing.T) { ++ op_e2e.InitParallel(t) ++ ++ numL1TxsExpected := int64(10) ++ ++ cfg := e2esys.DefaultSystemConfig(t) ++ cfg.DeployConfig.UseAltDA = true ++ cfg.BatcherMaxPendingTransactions = 0 // no limit on parallel txs ++ // ensures that batcher txs are as small as possible ++ cfg.BatcherMaxL1TxSizeBytes = derive.FrameV0OverHeadSize + 1 /*version bytes*/ + 1 ++ cfg.BatcherBatchType = 0 ++ cfg.DataAvailabilityType = flags.CalldataType ++ cfg.BatcherMaxConcurrentDARequest = uint64(numL1TxsExpected) ++ ++ // disable batcher because we start it manually below ++ cfg.DisableBatcher = true ++ sys, err := cfg.Start(t) ++ require.NoError(t, err, "Error starting up system") ++ defer sys.Close() ++ ++ // make every request take 5 seconds, such that only concurrent requests will be able to make progress fast enough ++ sys.FakeAltDAServer.SetPutRequestLatency(5 * time.Second) ++ ++ l1Client := sys.NodeClient("l1") ++ l2Seq := sys.NodeClient("sequencer") ++ ++ // we wait for numL1TxsExpected L2 blocks to have been produced, just to make sure the sequencer is working properly ++ _, err = geth.WaitForBlock(big.NewInt(numL1TxsExpected), l2Seq, time.Duration(cfg.DeployConfig.L2BlockTime*uint64(numL1TxsExpected))*time.Second) ++ require.NoError(t, err, "Waiting for L2 blocks") ++ ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) ++ defer cancel() ++ startingL1BlockNum, err := l1Client.BlockNumber(ctx) ++ require.NoError(t, err) ++ ++ // start batch submission ++ driver := sys.BatchSubmitter.TestDriver() ++ err = driver.StartBatchSubmitting() ++ require.NoError(t, err) ++ ++ totalBatcherTxsCount := int64(0) ++ // wait for up to 5 L1 blocks, expecting 10 L2 batcher txs in them. ++ // usually only 3 is required, but it's possible additional L1 blocks will be created ++ // before the batcher starts, so we wait additional blocks. ++ for i := int64(0); i < 5; i++ { ++ block, err := geth.WaitForBlock(big.NewInt(int64(startingL1BlockNum)+i), l1Client, time.Duration(cfg.DeployConfig.L1BlockTime*2)*time.Second) ++ require.NoError(t, err, "Waiting for l1 blocks") ++ // there are possibly other services (proposer/challenger) in the background sending txs ++ // so we only count the batcher txs ++ batcherTxCount, err := transactions.TransactionsBySender(block, cfg.DeployConfig.BatchSenderAddress) ++ require.NoError(t, err) ++ totalBatcherTxsCount += int64(batcherTxCount) ++ ++ if totalBatcherTxsCount >= numL1TxsExpected { ++ return ++ } ++ } ++ ++ t.Fatal("Expected at least 10 transactions from the batcher") ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+11
+
-3
+ +
+ +
+
+
diff --git OP/op-e2e/bridge_test.go CELO/op-e2e/system/bridge/bridge_test.go +rename from op-e2e/bridge_test.go +rename to op-e2e/system/bridge/bridge_test.go +index 2846e3218688a8c117b28e07e4126014a5ecca14..655cf612c9ad43521a8395f5d2b61dcd3ead4d55 100644 +--- OP/op-e2e/bridge_test.go ++++ CELO/op-e2e/system/bridge/bridge_test.go +@@ -1,10 +1,14 @@ +-package op_e2e ++package bridge +  + import ( + "context" + "math" + "math/big" + "testing" ++ ++ op_e2e "github.com/ethereum-optimism/optimism/op-e2e" ++ ++ "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" +  + "github.com/ethereum-optimism/optimism/op-e2e/bindings" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/receipts" +@@ -20,12 +24,16 @@ "github.com/ethereum/go-ethereum/params" + "github.com/stretchr/testify/require" + ) +  ++func TestMain(m *testing.M) { ++ op_e2e.RunMain(m) ++} ++ + // TestERC20BridgeDeposits tests the the L1StandardBridge bridge ERC20 + // functionality. + func TestERC20BridgeDeposits(t *testing.T) { +- InitParallel(t) ++ op_e2e.InitParallel(t) +  +- cfg := DefaultSystemConfig(t) ++ cfg := e2esys.DefaultSystemConfig(t) +  + sys, err := cfg.Start(t) + require.Nil(t, err, "Error starting up system")
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+12
+
-7
+ +
+ +
+
+
diff --git OP/op-e2e/deposit_test.go CELO/op-e2e/system/bridge/deposit_test.go +rename from op-e2e/deposit_test.go +rename to op-e2e/system/bridge/deposit_test.go +index c36d8aa4458411a300b4c24a2269ef724bfc76db..d01e9b3f3be9c9729f3213d234450975dc18c35a 100644 +--- OP/op-e2e/deposit_test.go ++++ CELO/op-e2e/system/bridge/deposit_test.go +@@ -1,4 +1,4 @@ +-package op_e2e ++package bridge +  + import ( + "context" +@@ -6,6 +6,11 @@ "math/big" + "testing" + "time" +  ++ op_e2e "github.com/ethereum-optimism/optimism/op-e2e" ++ ++ "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" ++ "github.com/ethereum-optimism/optimism/op-e2e/system/helpers" ++ + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" +  + "github.com/ethereum/go-ethereum/accounts/abi/bind" +@@ -16,8 +21,8 @@ "github.com/stretchr/testify/require" + ) +  + func TestMintOnRevertedDeposit(t *testing.T) { +- InitParallel(t) +- cfg := DefaultSystemConfig(t) ++ op_e2e.InitParallel(t) ++ cfg := e2esys.DefaultSystemConfig(t) + delete(cfg.Nodes, "verifier") + sys, err := cfg.Start(t) + require.NoError(t, err, "Error starting up system") +@@ -44,7 +49,7 @@ + toAddr := common.Address{0xff, 0xff} + mintAmount := big.NewInt(9_000_000) + opts.Value = mintAmount +- SendDepositTx(t, cfg, l1Client, l2Verif, opts, func(l2Opts *DepositTxOpts) { ++ helpers.SendDepositTx(t, cfg, l1Client, l2Verif, opts, func(l2Opts *helpers.DepositTxOpts) { + l2Opts.ToAddr = toAddr + // trigger a revert by transferring more than we have available + l2Opts.Value = new(big.Int).Mul(common.Big2, startBalance) +@@ -75,8 +80,8 @@ require.Equal(t, startNonce+1, endNonce, "Nonce of deposit sender should increment on L2, even if the deposit fails") + } +  + func TestDepositTxCreateContract(t *testing.T) { +- InitParallel(t) +- cfg := DefaultSystemConfig(t) ++ op_e2e.InitParallel(t) ++ cfg := e2esys.DefaultSystemConfig(t) + delete(cfg.Nodes, "verifier") +  + sys, err := cfg.Start(t) +@@ -125,7 +130,7 @@ } +  + deployData := append(deployPrefix, sstoreContract...) +  +- l2Receipt := SendDepositTx(t, cfg, l1Client, l2Client, opts, func(l2Opts *DepositTxOpts) { ++ l2Receipt := helpers.SendDepositTx(t, cfg, l1Client, l2Client, opts, func(l2Opts *helpers.DepositTxOpts) { + l2Opts.Data = deployData + l2Opts.Value = common.Big0 + l2Opts.IsCreation = true
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+55
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/system/bridge/rpc_test.go CELO/op-e2e/system/bridge/rpc_test.go +new file mode 100644 +index 0000000000000000000000000000000000000000..74a243ac2a93f5f3c13747fb857d1cd4fb048ebf +--- /dev/null ++++ CELO/op-e2e/system/bridge/rpc_test.go +@@ -0,0 +1,55 @@ ++package bridge ++ ++import ( ++ "context" ++ "math/big" ++ "testing" ++ "time" ++ ++ op_e2e "github.com/ethereum-optimism/optimism/op-e2e" ++ ++ "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" ++ "github.com/ethereum/go-ethereum/common" ++ "github.com/ethereum/go-ethereum/core/types" ++ "github.com/ethereum/go-ethereum/crypto" ++ "github.com/stretchr/testify/require" ++) ++ ++// TestL2SequencerRPCDepositTx checks that the L2 sequencer will not accept DepositTx type transactions. ++// The acceptance of these transactions would allow for arbitrary minting of ETH in L2. ++func TestL2SequencerRPCDepositTx(t *testing.T) { ++ op_e2e.InitParallel(t) ++ ++ // Create our system configuration for L1/L2 and start it ++ cfg := e2esys.DefaultSystemConfig(t) ++ sys, err := cfg.Start(t) ++ require.Nil(t, err, "Error starting up system") ++ ++ // Obtain our sequencer, verifier, and transactor keypair. ++ l2Seq := sys.NodeClient("sequencer") ++ l2Verif := sys.NodeClient("verifier") ++ txSigningKey := sys.Cfg.Secrets.Alice ++ require.Nil(t, err) ++ ++ // Create a deposit tx to send over RPC. ++ tx := types.NewTx(&types.DepositTx{ ++ SourceHash: common.Hash{}, ++ From: crypto.PubkeyToAddress(txSigningKey.PublicKey), ++ To: &common.Address{0xff, 0xff}, ++ Mint: big.NewInt(1000), ++ Value: big.NewInt(1000), ++ Gas: 0, ++ IsSystemTransaction: false, ++ Data: nil, ++ }) ++ ++ ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) ++ err = l2Seq.SendTransaction(ctx, tx) ++ cancel() ++ require.Error(t, err, "a DepositTx was accepted by L2 sequencer over RPC when it should not have been.") ++ ++ ctx, cancel = context.WithTimeout(context.Background(), 5*time.Second) ++ err = l2Verif.SendTransaction(ctx, tx) ++ cancel() ++ require.Error(t, err, "a DepositTx was accepted by L2 verifier over RPC when it should not have been.") ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+18
+
-135
+ +
+ +
+
+
diff --git OP/op-e2e/system_tob_test.go CELO/op-e2e/system/bridge/validity_test.go +rename from op-e2e/system_tob_test.go +rename to op-e2e/system/bridge/validity_test.go +index 99668d995acff65ce6ce7fdcaf43cf42f6e04c2e..e87800dafdd965b8a275be3fb711bd8f68bc7b73 100644 +--- OP/op-e2e/system_tob_test.go ++++ CELO/op-e2e/system/bridge/validity_test.go +@@ -1,26 +1,28 @@ +-package op_e2e ++package bridge +  + import ( + "bytes" + "context" + "crypto/ecdsa" + "fmt" +- "math" + "math/big" + "math/rand" + "testing" + "time" +  ++ op_e2e "github.com/ethereum-optimism/optimism/op-e2e" ++ ++ "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" ++ "github.com/ethereum-optimism/optimism/op-e2e/system/helpers" ++ + "github.com/ethereum-optimism/optimism/op-chain-ops/crossdomain" + legacybindings "github.com/ethereum-optimism/optimism/op-e2e/bindings" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/challenger" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/disputegame" +- "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" + "github.com/ethereum-optimism/optimism/op-node/bindings" + bindingspreview "github.com/ethereum-optimism/optimism/op-node/bindings/preview" +- "github.com/ethereum-optimism/optimism/op-service/eth" + "github.com/ethereum-optimism/optimism/op-service/predeploys" + "github.com/ethereum-optimism/optimism/op-service/testutils/fuzzerutils" + "github.com/ethereum/go-ethereum/accounts" +@@ -36,127 +38,6 @@ fuzz "github.com/google/gofuzz" + "github.com/stretchr/testify/require" + ) +  +-// TestGasPriceOracleFeeUpdates checks that the gas price oracle cannot be locked by mis-configuring parameters. +-func TestGasPriceOracleFeeUpdates(t *testing.T) { +- ctx, ctxCancel := context.WithCancel(context.Background()) +- defer ctxCancel() +- +- InitParallel(t) +- maxScalars := eth.EcotoneScalars{ +- BaseFeeScalar: math.MaxUint32, +- BlobBaseFeeScalar: math.MaxUint32, +- } +- var cancel context.CancelFunc +- +- // Create our system configuration for L1/L2 and start it +- cfg := DefaultSystemConfig(t) +- sys, err := cfg.Start(t) +- require.NoError(t, err, "Error starting up system") +- +- // Obtain our sequencer, verifier, and transactor keypair. +- l1Client := sys.NodeClient("l1") +- l2Seq := sys.NodeClient("sequencer") +- // l2Verif := sys.NodeClient("verifier") +- ethPrivKey := cfg.Secrets.SysCfgOwner +- +- // Bind to the SystemConfig & GasPriceOracle contracts +- sysconfig, err := legacybindings.NewSystemConfig(cfg.L1Deployments.SystemConfigProxy, l1Client) +- require.NoError(t, err) +- gpoContract, err := legacybindings.NewGasPriceOracleCaller(predeploys.GasPriceOracleAddr, l2Seq) +- require.NoError(t, err) +- +- // Obtain our signer. +- opts, err := bind.NewKeyedTransactorWithChainID(ethPrivKey, cfg.L1ChainIDBig()) +- require.NoError(t, err) +- +- // Define our L1 transaction timeout duration. +- txTimeoutDuration := 10 * time.Duration(cfg.DeployConfig.L1BlockTime) * time.Second +- +- // Update the gas config, wait for it to show up on L2, & verify that it was set as intended +- opts.Context, cancel = context.WithTimeout(ctx, txTimeoutDuration) +- tx, err := sysconfig.SetGasConfigEcotone(opts, maxScalars.BaseFeeScalar, maxScalars.BlobBaseFeeScalar) +- cancel() +- require.NoError(t, err, "SetGasConfigEcotone update tx") +- +- receipt, err := wait.ForReceiptOK(ctx, l1Client, tx.Hash()) +- require.NoError(t, err, "Waiting for sysconfig set gas config update tx") +- +- _, err = geth.WaitForL1OriginOnL2(sys.RollupConfig, receipt.BlockNumber.Uint64(), l2Seq, txTimeoutDuration) +- require.NoError(t, err, "waiting for L2 block to include the sysconfig update") +- +- baseFeeScalar, err := gpoContract.BaseFeeScalar(&bind.CallOpts{}) +- require.NoError(t, err, "reading base fee scalar") +- require.Equal(t, baseFeeScalar, maxScalars.BaseFeeScalar) +- +- blobBaseFeeScalar, err := gpoContract.BlobBaseFeeScalar(&bind.CallOpts{}) +- require.NoError(t, err, "reading blob base fee scalar") +- require.Equal(t, blobBaseFeeScalar, maxScalars.BlobBaseFeeScalar) +- +- // Now modify the scalar value & ensure that the gas params can be modified +- normalScalars := eth.EcotoneScalars{ +- BaseFeeScalar: 1e6, +- BlobBaseFeeScalar: 1e6, +- } +- +- opts.Context, cancel = context.WithTimeout(context.Background(), txTimeoutDuration) +- tx, err = sysconfig.SetGasConfigEcotone(opts, normalScalars.BaseFeeScalar, normalScalars.BlobBaseFeeScalar) +- cancel() +- require.NoError(t, err, "SetGasConfigEcotone update tx") +- +- receipt, err = wait.ForReceiptOK(ctx, l1Client, tx.Hash()) +- require.NoError(t, err, "Waiting for sysconfig set gas config update tx") +- +- _, err = geth.WaitForL1OriginOnL2(sys.RollupConfig, receipt.BlockNumber.Uint64(), l2Seq, txTimeoutDuration) +- require.NoError(t, err, "waiting for L2 block to include the sysconfig update") +- +- baseFeeScalar, err = gpoContract.BaseFeeScalar(&bind.CallOpts{}) +- require.NoError(t, err, "reading base fee scalar") +- require.Equal(t, baseFeeScalar, normalScalars.BaseFeeScalar) +- +- blobBaseFeeScalar, err = gpoContract.BlobBaseFeeScalar(&bind.CallOpts{}) +- require.NoError(t, err, "reading blob base fee scalar") +- require.Equal(t, blobBaseFeeScalar, normalScalars.BlobBaseFeeScalar) +-} +- +-// TestL2SequencerRPCDepositTx checks that the L2 sequencer will not accept DepositTx type transactions. +-// The acceptance of these transactions would allow for arbitrary minting of ETH in L2. +-func TestL2SequencerRPCDepositTx(t *testing.T) { +- InitParallel(t) +- +- // Create our system configuration for L1/L2 and start it +- cfg := DefaultSystemConfig(t) +- sys, err := cfg.Start(t) +- require.Nil(t, err, "Error starting up system") +- +- // Obtain our sequencer, verifier, and transactor keypair. +- l2Seq := sys.NodeClient("sequencer") +- l2Verif := sys.NodeClient("verifier") +- txSigningKey := sys.Cfg.Secrets.Alice +- require.Nil(t, err) +- +- // Create a deposit tx to send over RPC. +- tx := types.NewTx(&types.DepositTx{ +- SourceHash: common.Hash{}, +- From: crypto.PubkeyToAddress(txSigningKey.PublicKey), +- To: &common.Address{0xff, 0xff}, +- Mint: big.NewInt(1000), +- Value: big.NewInt(1000), +- Gas: 0, +- IsSystemTransaction: false, +- Data: nil, +- }) +- +- ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) +- err = l2Seq.SendTransaction(ctx, tx) +- cancel() +- require.Error(t, err, "a DepositTx was accepted by L2 sequencer over RPC when it should not have been.") +- +- ctx, cancel = context.WithTimeout(context.Background(), 5*time.Second) +- err = l2Verif.SendTransaction(ctx, tx) +- cancel() +- require.Error(t, err, "a DepositTx was accepted by L2 verifier over RPC when it should not have been.") +-} +- + // TestAccount defines an account generated by startConfigWithTestAccounts + type TestAccount struct { + HDPath string +@@ -169,7 +50,7 @@ + // startConfigWithTestAccounts takes a SystemConfig, generates additional accounts, adds them to the config, so they + // are funded on startup, starts the system, and imports the keys into the keystore, and obtains transaction opts for + // each account. +-func startConfigWithTestAccounts(t *testing.T, cfg *SystemConfig, accountsToGenerate int) (*System, []*TestAccount, error) { ++func startConfigWithTestAccounts(t *testing.T, cfg *e2esys.SystemConfig, accountsToGenerate int) (*e2esys.System, []*TestAccount, error) { + // Create our test accounts and add them to the pre-mine cfg. + testAccounts := make([]*TestAccount, 0) + var err error +@@ -223,7 +104,7 @@ + // TestMixedDepositValidity makes a number of deposit transactions, some which will succeed in transferring value, + // while others do not. It ensures that the expected nonces/balances match after several interactions. + func TestMixedDepositValidity(t *testing.T) { +- InitParallel(t) ++ op_e2e.InitParallel(t) + // Define how many deposit txs we'll make. Each deposit mints a fixed amount and transfers up to 1/3 of the user's + // balance. As such, this number cannot be too high or else the test will always fail due to lack of balance in L1. + const depositTxCount = 15 +@@ -232,7 +113,7 @@ // Define how many accounts we'll use to deposit funds + const accountUsedToDeposit = 5 +  + // Create our system configuration, funding all accounts we created for L1/L2, and start it +- cfg := DefaultSystemConfig(t) ++ cfg := e2esys.DefaultSystemConfig(t) + sys, testAccounts, err := startConfigWithTestAccounts(t, &cfg, accountUsedToDeposit) + require.Nil(t, err, "Error starting up system") +  +@@ -315,7 +196,7 @@ transferValue = new(big.Int).Div(transactor.ExpectedL2Balance, common.Big3) // send 1/3 our balance which should succeed. + } else { + transferValue = new(big.Int).Mul(common.Big2, transactor.ExpectedL2Balance) // trigger a revert by trying to transfer our current balance * 2 + } +- SendDepositTx(t, cfg, l1Client, l2Verif, transactor.Account.L1Opts, func(l2Opts *DepositTxOpts) { ++ helpers.SendDepositTx(t, cfg, l1Client, l2Verif, transactor.Account.L1Opts, func(l2Opts *helpers.DepositTxOpts) { + l2Opts.GasLimit = 100_000 + l2Opts.IsCreation = false + l2Opts.Data = nil +@@ -386,7 +267,9 @@ + // TestMixedWithdrawalValidity makes a number of withdrawal transactions and ensures ones with modified parameters are + // rejected while unmodified ones are accepted. This runs test cases in different systems. + func TestMixedWithdrawalValidity(t *testing.T) { +- InitParallel(t) ++ t.Skipf("Skipping withdrawal tests for now, must check in more detail!") ++ ++ op_e2e.InitParallel(t) +  + // There are 7 different fields we try modifying to cause a failure, plus one "good" test result we test. + for i := 0; i <= 8; i++ { +@@ -395,10 +278,10 @@ t.Run(fmt.Sprintf("withdrawal test#%d", i+1), func(t *testing.T) { + ctx, bgCancel := context.WithCancel(context.Background()) + defer bgCancel() +  +- InitParallel(t) ++ op_e2e.InitParallel(t) +  + // Create our system configuration, funding all accounts we created for L1/L2, and start it +- cfg := DefaultSystemConfig(t) ++ cfg := e2esys.DefaultSystemConfig(t) + cfg.Nodes["sequencer"].SafeDBPath = t.TempDir() + cfg.DeployConfig.L2BlockTime = 2 + require.LessOrEqual(t, cfg.DeployConfig.FinalizationPeriodSeconds, uint64(6)) +@@ -529,7 +412,7 @@ txCancel() + require.Nil(t, err) +  + // Calculate gas fees for the withdrawal in L2 to later adjust our balance. +- withdrawalL2GasFee := calcGasFees(receipt.GasUsed, tx.GasTipCap(), tx.GasFeeCap(), header.BaseFee) ++ withdrawalL2GasFee := helpers.CalcGasFees(receipt.GasUsed, tx.GasTipCap(), tx.GasFeeCap(), header.BaseFee) +  + // Adjust our expected L2 balance (should've decreased by withdraw amount + fees) + transactor.ExpectedL2Balance = new(big.Int).Sub(transactor.ExpectedL2Balance, withdrawAmount) +@@ -557,7 +440,7 @@ receiptCl := ethclient.NewClient(rpcClient) + blockCl := ethclient.NewClient(rpcClient) +  + // Now create the withdrawal +- params, err := ProveWithdrawalParameters(context.Background(), proofCl, receiptCl, blockCl, tx.Hash(), header, l2OutputOracle, disputeGameFactory, optimismPortal2) ++ params, err := helpers.ProveWithdrawalParameters(context.Background(), proofCl, receiptCl, blockCl, tx.Hash(), header, l2OutputOracle, disputeGameFactory, optimismPortal2) + require.Nil(t, err) +  + // Obtain our withdrawal parameters +@@ -662,7 +545,7 @@ require.NoError(t, err) +  + // Ensure that withdrawal - gas fees are added to the L1 balance + // Fun fact, the fee is greater than the withdrawal amount +- withdrawalL1GasFee := calcGasFees(receipt.GasUsed, tx.GasTipCap(), tx.GasFeeCap(), header.BaseFee) ++ withdrawalL1GasFee := helpers.CalcGasFees(receipt.GasUsed, tx.GasTipCap(), tx.GasFeeCap(), header.BaseFee) + transactor.ExpectedL1Balance = new(big.Int).Add(transactor.ExpectedL2Balance, withdrawAmount) + transactor.ExpectedL1Balance = new(big.Int).Sub(transactor.ExpectedL2Balance, withdrawalL1GasFee) + transactor.ExpectedL1Nonce++
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+12
+
-9
+ +
+ +
+
+
diff --git OP/op-e2e/withdrawal.go CELO/op-e2e/system/bridge/withdrawal.go +rename from op-e2e/withdrawal.go +rename to op-e2e/system/bridge/withdrawal.go +index a5f44434a8eede400b1ac22aea6f2cbb554a1442..29864db02dbfcaabfb33d5069bff21af4ccb6689 100644 +--- OP/op-e2e/withdrawal.go ++++ CELO/op-e2e/system/bridge/withdrawal.go +@@ -1,4 +1,4 @@ +-package op_e2e ++package bridge +  + import ( + "context" +@@ -6,6 +6,9 @@ "crypto/ecdsa" + "math/big" + "testing" + "time" ++ ++ "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" ++ "github.com/ethereum-optimism/optimism/op-e2e/system/helpers" +  + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" +@@ -22,7 +25,7 @@ + type CommonSystem interface { + NodeClient(role string) *ethclient.Client + RollupClient(role string) *sources.RollupClient +- Config() SystemConfig ++ Config() e2esys.SystemConfig + TestAccount(int) *ecdsa.PrivateKey + } +  +@@ -33,9 +36,9 @@ func RunWithdrawalsTest(t *testing.T, sys CommonSystem) { + t.Logf("WithdrawalsTest: running with FP == %t", e2eutils.UseFaultProofs()) + cfg := sys.Config() +  +- l1Client := sys.NodeClient(RoleL1) +- l2Seq := sys.NodeClient(RoleSeq) +- l2Verif := sys.NodeClient(RoleVerif) ++ l1Client := sys.NodeClient(e2esys.RoleL1) ++ l2Seq := sys.NodeClient(e2esys.RoleSeq) ++ l2Verif := sys.NodeClient(e2esys.RoleVerif) +  + // Transactor Account + ethPrivKey := sys.TestAccount(0) +@@ -55,7 +58,7 @@ // Send deposit tx + mintAmount := big.NewInt(1_000_000_000_000) + opts.Value = mintAmount + t.Logf("WithdrawalsTest: depositing %v with L2 start balance %v...", mintAmount, startBalanceBeforeDeposit) +- SendDepositTx(t, cfg, l1Client, l2Verif, opts, func(l2Opts *DepositTxOpts) { ++ helpers.SendDepositTx(t, cfg, l1Client, l2Verif, opts, func(l2Opts *helpers.DepositTxOpts) { + l2Opts.Value = common.Big0 + }) + t.Log("WithdrawalsTest: waiting for balance change...") +@@ -78,7 +81,7 @@ require.NoError(t, err) +  + withdrawAmount := big.NewInt(500_000_000_000) + t.Logf("WithdrawalsTest: sending L2 withdrawal for %v...", withdrawAmount) +- tx, receipt := SendWithdrawal(t, cfg, l2Seq, ethPrivKey, func(opts *WithdrawalTxOpts) { ++ tx, receipt := helpers.SendWithdrawal(t, cfg, l2Seq, ethPrivKey, func(opts *helpers.WithdrawalTxOpts) { + opts.Value = withdrawAmount + opts.VerifyOnClients(l2Verif) + }) +@@ -97,7 +100,7 @@ require.NoError(t, err) +  + // Take fee into account + diff = new(big.Int).Sub(startBalanceBeforeWithdrawal, endBalanceAfterWithdrawal) +- fees := calcGasFees(receipt.GasUsed, tx.GasTipCap(), tx.GasFeeCap(), header.BaseFee) ++ fees := helpers.CalcGasFees(receipt.GasUsed, tx.GasTipCap(), tx.GasFeeCap(), header.BaseFee) + fees = fees.Add(fees, receipt.L1Fee) + diff = diff.Sub(diff, fees) + require.Equal(t, withdrawAmount, diff) +@@ -109,7 +112,7 @@ startBalanceBeforeFinalize, err := l1Client.BalanceAt(ctx, fromAddr, nil) + require.NoError(t, err) +  + t.Log("WithdrawalsTest: ProveAndFinalizeWithdrawal...") +- proveReceipt, finalizeReceipt, resolveClaimReceipt, resolveReceipt := ProveAndFinalizeWithdrawal(t, cfg, sys, RoleVerif, ethPrivKey, receipt) ++ proveReceipt, finalizeReceipt, resolveClaimReceipt, resolveReceipt := helpers.ProveAndFinalizeWithdrawal(t, cfg, sys, e2esys.RoleVerif, ethPrivKey, receipt) +  + // Verify balance after withdrawal + ctx, cancel = context.WithTimeout(context.Background(), 30*time.Second)
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+26
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/system/bridge/withdrawal_test.go CELO/op-e2e/system/bridge/withdrawal_test.go +new file mode 100644 +index 0000000000000000000000000000000000000000..9f37240cbdbefbde9e8bdc8b5e442349118ee122 +--- /dev/null ++++ CELO/op-e2e/system/bridge/withdrawal_test.go +@@ -0,0 +1,26 @@ ++package bridge ++ ++import ( ++ "testing" ++ ++ op_e2e "github.com/ethereum-optimism/optimism/op-e2e" ++ ++ "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" ++ "github.com/stretchr/testify/require" ++) ++ ++// TestWithdrawals checks that a deposit and then withdrawal execution succeeds. It verifies the ++// balance changes on L1 and L2 and has to include gas fees in the balance checks. ++// It does not check that the withdrawal can be executed prior to the end of the finality period. ++func TestWithdrawals(t *testing.T) { ++ op_e2e.InitParallel(t) ++ ++ cfg := e2esys.DefaultSystemConfig(t) ++ cfg.DeployConfig.FinalizationPeriodSeconds = 2 // 2s finalization period ++ cfg.L1FinalizedDistance = 2 // Finalize quick, don't make the proposer wait too long ++ ++ sys, err := cfg.Start(t) ++ require.NoError(t, err, "Error starting up system") ++ ++ RunWithdrawalsTest(t, sys) ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+11
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/system/conductor/conductor_test.go CELO/op-e2e/system/conductor/conductor_test.go +new file mode 100644 +index 0000000000000000000000000000000000000000..ec4175807f8ccfbb87a640f0998a277c2f753674 +--- /dev/null ++++ CELO/op-e2e/system/conductor/conductor_test.go +@@ -0,0 +1,11 @@ ++package conductor ++ ++import ( ++ "testing" ++ ++ op_e2e "github.com/ethereum-optimism/optimism/op-e2e" ++) ++ ++func TestMain(m *testing.M) { ++ op_e2e.RunMain(m) ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+29
+
-20
+ +
+ +
+
+
diff --git OP/op-e2e/sequencer_failover_setup.go CELO/op-e2e/system/conductor/sequencer_failover_setup.go +rename from op-e2e/sequencer_failover_setup.go +rename to op-e2e/system/conductor/sequencer_failover_setup.go +index db4e05bff433663b21c3bf03e1b87c59b06ee4f9..ea515ecc1e64d33fc0231713b5b16e067c844d93 100644 +--- OP/op-e2e/sequencer_failover_setup.go ++++ CELO/op-e2e/system/conductor/sequencer_failover_setup.go +@@ -1,4 +1,4 @@ +-package op_e2e ++package conductor +  + import ( + "context" +@@ -9,6 +9,11 @@ "strings" + "testing" + "time" +  ++ op_e2e "github.com/ethereum-optimism/optimism/op-e2e" ++ ++ "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" ++ "github.com/ethereum/go-ethereum/common/hexutil" ++ + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/rpc" + "github.com/stretchr/testify/require" +@@ -18,6 +23,7 @@ batcherFlags "github.com/ethereum-optimism/optimism/op-batcher/flags" + con "github.com/ethereum-optimism/optimism/op-conductor/conductor" + "github.com/ethereum-optimism/optimism/op-conductor/consensus" + conrpc "github.com/ethereum-optimism/optimism/op-conductor/rpc" ++ "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/setuputils" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" + rollupNode "github.com/ethereum-optimism/optimism/op-node/node" + "github.com/ethereum-optimism/optimism/op-node/rollup" +@@ -59,11 +65,11 @@ func (c *conductor) RPCEndpoint() string { + return fmt.Sprintf("http://%s:%d", localhost, c.rpcPort) + } +  +-func setupSequencerFailoverTest(t *testing.T) (*System, map[string]*conductor, func()) { +- InitParallel(t) ++func setupSequencerFailoverTest(t *testing.T) (*e2esys.System, map[string]*conductor, func()) { ++ op_e2e.InitParallel(t) + ctx := context.Background() +  +- sys, conductors, err := retry.Do2(ctx, maxSetupRetries, retryStrategy, func() (*System, map[string]*conductor, error) { ++ sys, conductors, err := retry.Do2(ctx, maxSetupRetries, retryStrategy, func() (*e2esys.System, map[string]*conductor, error) { + return setupHAInfra(t, ctx) + }) + require.NoError(t, err, "Expected to successfully setup sequencers and conductors after retry") +@@ -137,10 +143,10 @@ } + } + } +  +-func setupHAInfra(t *testing.T, ctx context.Context) (*System, map[string]*conductor, error) { ++func setupHAInfra(t *testing.T, ctx context.Context) (*e2esys.System, map[string]*conductor, error) { + startTime := time.Now() +  +- var sys *System ++ var sys *e2esys.System + var conductors map[string]*conductor + var err error +  +@@ -208,14 +214,17 @@ rollupCfg rollup.Config, + ) (*conductor, error) { + consensusPort := findAvailablePort(t) + cfg := con.Config{ +- ConsensusAddr: localhost, +- ConsensusPort: consensusPort, +- RaftServerID: serverID, +- RaftStorageDir: dir, +- RaftBootstrap: bootstrap, +- NodeRPC: nodeRPC, +- ExecutionRPC: engineRPC, +- Paused: true, ++ ConsensusAddr: localhost, ++ ConsensusPort: consensusPort, ++ RaftServerID: serverID, ++ RaftStorageDir: dir, ++ RaftBootstrap: bootstrap, ++ RaftSnapshotInterval: 120 * time.Second, ++ RaftSnapshotThreshold: 8192, ++ RaftTrailingLogs: 10240, ++ NodeRPC: nodeRPC, ++ ExecutionRPC: engineRPC, ++ Paused: true, + HealthCheck: con.HealthCheckConfig{ + Interval: 1, // per test setup, l2 block time is 1s. + MinPeerCount: 2, // per test setup, each sequencer has 2 peers +@@ -263,7 +272,7 @@ rpcPort: rpcPort, + }, nil + } +  +-func setupBatcher(t *testing.T, sys *System, conductors map[string]*conductor) { ++func setupBatcher(t *testing.T, sys *e2esys.System, conductors map[string]*conductor) { + // enable active sequencer follow mode. + // in sequencer HA, all batcher / proposer requests will be proxied by conductor so that we can make sure + // that requests are always handled by leader. +@@ -288,7 +297,7 @@ TargetNumFrames: 1, + ApproxComprRatio: 0.4, + SubSafetyMargin: 4, + PollInterval: 1 * time.Second, +- TxMgrConfig: newTxMgrConfig(sys.EthInstances["l1"].UserRPC().RPC(), sys.Cfg.Secrets.Batcher), ++ TxMgrConfig: setuputils.NewTxMgrConfig(sys.EthInstances["l1"].UserRPC(), sys.Cfg.Secrets.Batcher), + LogConfig: oplog.CLIConfig{ + Level: log.LevelDebug, + Format: oplog.FormatText, +@@ -307,8 +316,8 @@ require.NoError(t, err) + sys.BatchSubmitter = batcher + } +  +-func sequencerFailoverSystemConfig(t *testing.T, ports map[string]int) SystemConfig { +- cfg := EcotoneSystemConfig(t, &genesisTime) ++func sequencerFailoverSystemConfig(t *testing.T, ports map[string]int) e2esys.SystemConfig { ++ cfg := e2esys.EcotoneSystemConfig(t, new(hexutil.Uint64)) + delete(cfg.Nodes, "sequencer") + cfg.Nodes[Sequencer1Name] = sequencerCfg(ports[Sequencer1Name]) + cfg.Nodes[Sequencer2Name] = sequencerCfg(ports[Sequencer2Name]) +@@ -368,7 +377,7 @@ + return wait.For(ctx, 1*time.Second, condition) + } +  +-func waitForLeadershipChange(t *testing.T, prev *conductor, prevID string, conductors map[string]*conductor, sys *System) string { ++func waitForLeadershipChange(t *testing.T, prev *conductor, prevID string, conductors map[string]*conductor, sys *e2esys.System) string { + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() +  +@@ -482,7 +491,7 @@ } + return "", nil + } +  +-func ensureOnlyOneLeader(t *testing.T, sys *System, conductors map[string]*conductor) { ++func ensureOnlyOneLeader(t *testing.T, sys *e2esys.System, conductors map[string]*conductor) { + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() +
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+1
+
-1
+ +
+ +
+
+
diff --git OP/op-e2e/sequencer_failover_test.go CELO/op-e2e/system/conductor/sequencer_failover_test.go +rename from op-e2e/sequencer_failover_test.go +rename to op-e2e/system/conductor/sequencer_failover_test.go +index c153832b9f7686a27cd2b9a74331e36b8b47e844..1b49b989654f47276c5f5c5e1c7d73db3110d606 100644 +--- OP/op-e2e/sequencer_failover_test.go ++++ CELO/op-e2e/system/conductor/sequencer_failover_test.go +@@ -1,4 +1,4 @@ +-package op_e2e ++package conductor +  + import ( + "context"
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+24
+
-11
+ +
+ +
+
+
diff --git OP/op-e2e/system_adminrpc_test.go CELO/op-e2e/system/conductor/system_adminrpc_test.go +rename from op-e2e/system_adminrpc_test.go +rename to op-e2e/system/conductor/system_adminrpc_test.go +index aabae9d6047b3006df92a59130a860539e3c40fc..5501ece79fff96d7764708a14cfd914f36145433 100644 +--- OP/op-e2e/system_adminrpc_test.go ++++ CELO/op-e2e/system/conductor/system_adminrpc_test.go +@@ -1,4 +1,4 @@ +-package op_e2e ++package conductor +  + import ( + "context" +@@ -6,6 +6,11 @@ "math/big" + "testing" + "time" +  ++ op_e2e "github.com/ethereum-optimism/optimism/op-e2e" ++ ++ "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" ++ "github.com/ethereum/go-ethereum/ethclient" ++ + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/rpc" + "github.com/stretchr/testify/require" +@@ -18,9 +23,9 @@ "github.com/ethereum-optimism/optimism/op-service/sources" + ) +  + func TestStopStartSequencer(t *testing.T) { +- InitParallel(t) ++ op_e2e.InitParallel(t) +  +- cfg := DefaultSystemConfig(t) ++ cfg := e2esys.DefaultSystemConfig(t) + sys, err := cfg.Start(t) + require.Nil(t, err, "Error starting up system") +  +@@ -74,13 +79,21 @@ "Chain did not advance after starting sequencer", + ) + } +  ++func latestBlock(t *testing.T, client *ethclient.Client) uint64 { ++ ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) ++ defer cancel() ++ blockAfter, err := client.BlockNumber(ctx) ++ require.Nil(t, err, "Error getting latest block") ++ return blockAfter ++} ++ + func TestPersistSequencerStateWhenChanged(t *testing.T) { +- InitParallel(t) ++ op_e2e.InitParallel(t) + ctx := context.Background() + dir := t.TempDir() + stateFile := dir + "/state.json" +  +- cfg := DefaultSystemConfig(t) ++ cfg := e2esys.DefaultSystemConfig(t) + // We don't need a verifier - just the sequencer is enough + delete(cfg.Nodes, "verifier") + cfg.Nodes["sequencer"].ConfigPersistence = node.NewConfigPersistence(stateFile) +@@ -104,7 +117,7 @@ assertPersistedSequencerState(t, stateFile, node.StateStopped) + } +  + func TestLoadSequencerStateOnStarted_Stopped(t *testing.T) { +- InitParallel(t) ++ op_e2e.InitParallel(t) + ctx := context.Background() + dir := t.TempDir() + stateFile := dir + "/state.json" +@@ -113,7 +126,7 @@ // Prepare the persisted state file with sequencer stopped + configReader := node.NewConfigPersistence(stateFile) + require.NoError(t, configReader.SequencerStopped()) +  +- cfg := DefaultSystemConfig(t) ++ cfg := e2esys.DefaultSystemConfig(t) + // We don't need a verifier - just the sequencer is enough + delete(cfg.Nodes, "verifier") + seqCfg := cfg.Nodes["sequencer"] +@@ -136,7 +149,7 @@ assertPersistedSequencerState(t, stateFile, node.StateStopped) + } +  + func TestLoadSequencerStateOnStarted_Started(t *testing.T) { +- InitParallel(t) ++ op_e2e.InitParallel(t) + ctx := context.Background() + dir := t.TempDir() + stateFile := dir + "/state.json" +@@ -145,7 +158,7 @@ // Prepare the persisted state file with sequencer stopped + configReader := node.NewConfigPersistence(stateFile) + require.NoError(t, configReader.SequencerStarted()) +  +- cfg := DefaultSystemConfig(t) ++ cfg := e2esys.DefaultSystemConfig(t) + // We don't need a verifier - just the sequencer is enough + delete(cfg.Nodes, "verifier") + seqCfg := cfg.Nodes["sequencer"] +@@ -169,10 +182,10 @@ assertPersistedSequencerState(t, stateFile, node.StateStarted) + } +  + func TestPostUnsafePayload(t *testing.T) { +- InitParallel(t) ++ op_e2e.InitParallel(t) + ctx := context.Background() +  +- cfg := DefaultSystemConfig(t) ++ cfg := e2esys.DefaultSystemConfig(t) + cfg.Nodes["verifier"].RPC.EnableAdmin = true + cfg.DisableBatcher = true +
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+5
+
-3
+ +
+ +
+
+
diff --git OP/op-e2e/artifactsfs_test.go CELO/op-e2e/system/contracts/artifactsfs_test.go +rename from op-e2e/artifactsfs_test.go +rename to op-e2e/system/contracts/artifactsfs_test.go +index 98d23be8e112899e0bc243022e58281dab37c646..a52680a0b2d1d602a95c2ae95f45bd57ed5047e2 100644 +--- OP/op-e2e/artifactsfs_test.go ++++ CELO/op-e2e/system/contracts/artifactsfs_test.go +@@ -1,8 +1,10 @@ +-package op_e2e ++package contracts +  + import ( + "errors" + "testing" ++ ++ op_e2e "github.com/ethereum-optimism/optimism/op-e2e" +  + "github.com/stretchr/testify/require" +  +@@ -13,9 +15,9 @@ "github.com/ethereum-optimism/optimism/op-service/testlog" + ) +  + func TestArtifacts(t *testing.T) { +- InitParallel(t) ++ op_e2e.InitParallel(t) + logger := testlog.Logger(t, log.LevelWarn) // lower this log level to get verbose test dump of all artifacts +- af := foundry.OpenArtifactsDir("../packages/contracts-bedrock/forge-artifacts") ++ af := foundry.OpenArtifactsDir("../../../packages/contracts-bedrock/forge-artifacts") + artifacts, err := af.ListArtifacts() + require.NoError(t, err) + require.NotEmpty(t, artifacts)
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+11
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/system/contracts/contracts_test.go CELO/op-e2e/system/contracts/contracts_test.go +new file mode 100644 +index 0000000000000000000000000000000000000000..da4a081a90ca3e4e82a064cbe5cea9d5d2a46edb +--- /dev/null ++++ CELO/op-e2e/system/contracts/contracts_test.go +@@ -0,0 +1,11 @@ ++package contracts ++ ++import ( ++ "testing" ++ ++ op_e2e "github.com/ethereum-optimism/optimism/op-e2e" ++) ++ ++func TestMain(m *testing.M) { ++ op_e2e.RunMain(m) ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+13
+
-8
+ +
+ +
+
+
diff --git OP/op-e2e/brotli_batcher_test.go CELO/op-e2e/system/da/brotli_batcher_test.go +rename from op-e2e/brotli_batcher_test.go +rename to op-e2e/system/da/brotli_batcher_test.go +index ee4a223bf3ea53fe8e16b61192060c5b0a7e3e6c..be8c289088f61b0120b4131ff183301707ce7b81 100644 +--- OP/op-e2e/brotli_batcher_test.go ++++ CELO/op-e2e/system/da/brotli_batcher_test.go +@@ -1,4 +1,4 @@ +-package op_e2e ++package da +  + import ( + "context" +@@ -7,6 +7,11 @@ "math/big" + "testing" + "time" +  ++ op_e2e "github.com/ethereum-optimism/optimism/op-e2e" ++ ++ "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" ++ "github.com/ethereum-optimism/optimism/op-e2e/system/helpers" ++ + "github.com/stretchr/testify/require" +  + batcherFlags "github.com/ethereum-optimism/optimism/op-batcher/flags" +@@ -19,7 +24,7 @@ "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/log" + ) +  +-func setupAliceAccount(t *testing.T, cfg SystemConfig, sys *System, ethPrivKey *ecdsa.PrivateKey) { ++func setupAliceAccount(t *testing.T, cfg e2esys.SystemConfig, sys *e2esys.System, ethPrivKey *ecdsa.PrivateKey) { + l1Client := sys.NodeClient("l1") + l2Verif := sys.NodeClient("verifier") +  +@@ -37,7 +42,7 @@ opts, err := bind.NewKeyedTransactorWithChainID(ethPrivKey, cfg.L1ChainIDBig()) + require.NoError(t, err) + mintAmount := big.NewInt(1_000_000_000_000) + opts.Value = mintAmount +- SendDepositTx(t, cfg, l1Client, l2Verif, opts, func(l2Opts *DepositTxOpts) {}) ++ helpers.SendDepositTx(t, cfg, l1Client, l2Verif, opts, func(l2Opts *helpers.DepositTxOpts) {}) +  + // Confirm balance + ctx, cancel = context.WithTimeout(context.Background(), 15*time.Second) +@@ -50,9 +55,9 @@ require.Equal(t, mintAmount, diff, "Did not get expected balance change") + } +  + func TestBrotliBatcherFjord(t *testing.T) { +- InitParallel(t) ++ op_e2e.InitParallel(t) +  +- cfg := DefaultSystemConfig(t) ++ cfg := e2esys.DefaultSystemConfig(t) + cfg.DataAvailabilityType = batcherFlags.BlobsType +  + genesisActivation := hexutil.Uint64(0) +@@ -62,7 +67,7 @@ cfg.DeployConfig.L2GenesisEcotoneTimeOffset = &genesisActivation + cfg.DeployConfig.L2GenesisFjordTimeOffset = &genesisActivation +  + // set up batcher to use brotli +- sys, err := cfg.Start(t, SystemConfigOption{"compressionAlgo", "brotli", nil}) ++ sys, err := cfg.Start(t, e2esys.SystemConfigOption{Key: "compressionAlgo", Role: "brotli", Action: nil}) + require.Nil(t, err, "Error starting up system") +  + log := testlog.Logger(t, log.LevelInfo) +@@ -76,11 +81,11 @@ ethPrivKey := cfg.Secrets.Alice + setupAliceAccount(t, cfg, sys, ethPrivKey) +  + // Submit TX to L2 sequencer node +- receipt := SendL2Tx(t, cfg, l2Seq, ethPrivKey, func(opts *TxOpts) { ++ receipt := helpers.SendL2Tx(t, cfg, l2Seq, ethPrivKey, func(opts *helpers.TxOpts) { + opts.Value = big.NewInt(1_000_000_000) + opts.Nonce = 1 // Already have deposit + opts.ToAddr = &common.Address{0xff, 0xff} +- opts.Gas, err = core.IntrinsicGas(opts.Data, nil, false, true, true, false) ++ opts.Gas, err = core.IntrinsicGas(opts.Data, nil, false, true, true, false, nil, nil) + require.NoError(t, err) + opts.VerifyOnClients(l2Verif) + })
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+11
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/system/da/da_test.go CELO/op-e2e/system/da/da_test.go +new file mode 100644 +index 0000000000000000000000000000000000000000..ae5606e8df5321519921575b235cd935a89ae9f3 +--- /dev/null ++++ CELO/op-e2e/system/da/da_test.go +@@ -0,0 +1,11 @@ ++package da ++ ++import ( ++ "testing" ++ ++ op_e2e "github.com/ethereum-optimism/optimism/op-e2e" ++) ++ ++func TestMain(m *testing.M) { ++ op_e2e.RunMain(m) ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+53
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/system/da/dencun_test.go CELO/op-e2e/system/da/dencun_test.go +new file mode 100644 +index 0000000000000000000000000000000000000000..4bdaee540c008a865a36bd2a37e372aa5da35d59 +--- /dev/null ++++ CELO/op-e2e/system/da/dencun_test.go +@@ -0,0 +1,53 @@ ++package da ++ ++import ( ++ "context" ++ "testing" ++ "time" ++ ++ op_e2e "github.com/ethereum-optimism/optimism/op-e2e" ++ ++ "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" ++ "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/transactions" ++ "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" ++ "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" ++ "github.com/ethereum/go-ethereum/common/hexutil" ++ "github.com/ethereum/go-ethereum/core/types" ++ "github.com/stretchr/testify/require" ++) ++ ++// TestSystemE2EDencunAtGenesis tests if L2 finalizes when blobs are present on L1 ++func TestSystemE2EDencunAtGenesisWithBlobs(t *testing.T) { ++ op_e2e.InitParallel(t) ++ ++ ctx, cancel := context.WithCancel(context.Background()) ++ defer cancel() ++ ++ cfg := e2esys.DefaultSystemConfig(t) ++ cfg.DeployConfig.L1CancunTimeOffset = new(hexutil.Uint64) ++ ++ sys, err := cfg.Start(t) ++ require.Nil(t, err, "Error starting up system") ++ ++ // send a blob-containing txn on l1 ++ ethPrivKey := sys.Cfg.Secrets.Alice ++ txData := transactions.CreateEmptyBlobTx(true, sys.Cfg.L1ChainIDBig().Uint64()) ++ tx := types.MustSignNewTx(ethPrivKey, types.LatestSignerForChainID(cfg.L1ChainIDBig()), txData) ++ // send blob-containing txn ++ sendCtx, sendCancel := context.WithTimeout(context.Background(), 15*time.Second) ++ defer sendCancel() ++ ++ l1Client := sys.NodeClient("l1") ++ err = l1Client.SendTransaction(sendCtx, tx) ++ require.NoError(t, err, "Sending L1 empty blob tx") ++ // Wait for transaction on L1 ++ blockContainsBlob, err := wait.ForReceiptOK(ctx, l1Client, tx.Hash()) ++ require.Nil(t, err, "Waiting for blob tx on L1") ++ // end sending blob-containing txns on l1 ++ l2Client := sys.NodeClient("sequencer") ++ finalizedBlock, err := geth.WaitForL1OriginOnL2(sys.RollupConfig, blockContainsBlob.BlockNumber.Uint64(), l2Client, 30*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) ++ require.Nil(t, err, "Waiting for L1 origin of blob tx on L2") ++ finalizationTimeout := 30 * time.Duration(cfg.DeployConfig.L1BlockTime) * time.Second ++ _, err = geth.WaitForBlockToBeSafe(finalizedBlock.Header().Number, l2Client, finalizationTimeout) ++ require.Nil(t, err, "Waiting for safety of L2 block") ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+16
+
-11
+ +
+ +
+
+
diff --git OP/op-e2e/eip4844_test.go CELO/op-e2e/system/da/eip4844_test.go +rename from op-e2e/eip4844_test.go +rename to op-e2e/system/da/eip4844_test.go +index 7069fba72afc3e7b7c3bac8ca31026363cc647c8..3ab4c59512a508f186ea35de7f8c8bc4faebfcf1 100644 +--- OP/op-e2e/eip4844_test.go ++++ CELO/op-e2e/system/da/eip4844_test.go +@@ -1,4 +1,4 @@ +-package op_e2e ++package da +  + import ( + "context" +@@ -6,6 +6,11 @@ "math/big" + "math/rand" + "testing" + "time" ++ ++ op_e2e "github.com/ethereum-optimism/optimism/op-e2e" ++ ++ "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" ++ "github.com/ethereum-optimism/optimism/op-e2e/system/helpers" +  + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +@@ -38,9 +43,9 @@ t.Run("multi-blob", func(t *testing.T) { testSystem4844E2E(t, true, batcherFlags.BlobsType) }) + } +  + func testSystem4844E2E(t *testing.T, multiBlob bool, daType batcherFlags.DataAvailabilityType) { +- InitParallel(t) ++ op_e2e.InitParallel(t) +  +- cfg := EcotoneSystemConfig(t, &genesisTime) ++ cfg := e2esys.EcotoneSystemConfig(t, new(hexutil.Uint64)) + cfg.DataAvailabilityType = daType + cfg.BatcherBatchType = derive.SpanBatchType + cfg.DeployConfig.L1GenesisBlockBaseFeePerGas = (*hexutil.Big)(big.NewInt(7000)) +@@ -62,9 +67,9 @@ // transaction. The hook used here makes sure we make the jamming call before batch submission + // is started, as is required by the function. + var jamChan chan error + jamCtx, jamCancel := context.WithTimeout(context.Background(), 20*time.Second) +- action := SystemConfigOption{ +- key: "beforeBatcherStart", +- action: func(cfg *SystemConfig, s *System) { ++ action := e2esys.SystemConfigOption{ ++ Key: "beforeBatcherStart", ++ Action: func(cfg *e2esys.SystemConfig, s *e2esys.System) { + driver := s.BatchSubmitter.TestDriver() + err := driver.JamTxPool(jamCtx) + require.NoError(t, err) +@@ -108,7 +113,7 @@ opts, err := bind.NewKeyedTransactorWithChainID(ethPrivKey, cfg.L1ChainIDBig()) + require.NoError(t, err) + mintAmount := big.NewInt(1_000_000_000_000) + opts.Value = mintAmount +- SendDepositTx(t, cfg, l1Client, l2Verif, opts, func(l2Opts *DepositTxOpts) {}) ++ helpers.SendDepositTx(t, cfg, l1Client, l2Verif, opts, func(l2Opts *helpers.DepositTxOpts) {}) +  + // Confirm balance + ctx2, cancel2 := context.WithTimeout(context.Background(), 20*time.Second) +@@ -120,13 +125,13 @@ diff := new(big.Int).Sub(endBalance, startBalance) + require.Equal(t, mintAmount, diff, "Did not get expected balance change") +  + // Submit TX to L2 sequencer node +- receipt := SendL2Tx(t, cfg, l2Seq, ethPrivKey, func(opts *TxOpts) { ++ receipt := helpers.SendL2Tx(t, cfg, l2Seq, ethPrivKey, func(opts *helpers.TxOpts) { + opts.Value = big.NewInt(1_000_000_000) + opts.Nonce = 1 // Already have deposit + opts.ToAddr = &common.Address{0xff, 0xff} + // put some random data in the tx to make it fill up 6 blobs (multi-blob case) + opts.Data = testutils.RandomData(rand.New(rand.NewSource(420)), 400) +- opts.Gas, err = core.IntrinsicGas(opts.Data, nil, false, true, true, false) ++ opts.Gas, err = core.IntrinsicGas(opts.Data, nil, false, true, true, false, nil, nil) + require.NoError(t, err) + opts.VerifyOnClients(l2Verif) + }) +@@ -237,9 +242,9 @@ // So in the first few L1 blocks, calldata will be cheaper than blobs. + // We then send a couple of expensive Deposit transactions, which drives up the + // gas price. The L1 blob gas limit is set to a low value to speed up this process. + func TestBatcherAutoDA(t *testing.T) { +- InitParallel(t) ++ op_e2e.InitParallel(t) +  +- cfg := EcotoneSystemConfig(t, &genesisTime) ++ cfg := e2esys.EcotoneSystemConfig(t, new(hexutil.Uint64)) + cfg.DataAvailabilityType = batcherFlags.AutoType + // We set the genesis fee values and block gas limit such that calldata txs are initially cheaper, + // but then drive up the base fee over the coming L1 blocks such that blobs become cheaper again.
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+10
+
-5
+ +
+ +
+
+
diff --git OP/op-e2e/l1_beacon_client_test.go CELO/op-e2e/system/da/l1_beacon_client_test.go +rename from op-e2e/l1_beacon_client_test.go +rename to op-e2e/system/da/l1_beacon_client_test.go +index 93094d4884e7673b4f94f184a9b06924fdc9b674..68698a5e3187aad2174f8d03579d72930b4cf6a0 100644 +--- OP/op-e2e/l1_beacon_client_test.go ++++ CELO/op-e2e/system/da/l1_beacon_client_test.go +@@ -1,9 +1,12 @@ +-package op_e2e ++package da +  + import ( + "context" + "testing" +  ++ op_e2e "github.com/ethereum-optimism/optimism/op-e2e" ++ ++ "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/fakebeacon" + "github.com/ethereum-optimism/optimism/op-service/client" + "github.com/ethereum-optimism/optimism/op-service/eth" +@@ -15,11 +18,12 @@ "github.com/stretchr/testify/require" + ) +  + func TestGetVersion(t *testing.T) { +- InitParallel(t) ++ op_e2e.InitParallel(t) +  + l := testlog.Logger(t, log.LevelInfo) +  +- beaconApi := fakebeacon.NewBeacon(l, t.TempDir(), uint64(0), uint64(0)) ++ blobStore := e2eutils.NewBlobStore() ++ beaconApi := fakebeacon.NewBeacon(l, blobStore, uint64(0), uint64(0)) + t.Cleanup(func() { + _ = beaconApi.Close() + }) +@@ -34,11 +38,12 @@ require.Equal(t, "fakebeacon 1.2.3", version) + } +  + func Test404NotFound(t *testing.T) { +- InitParallel(t) ++ op_e2e.InitParallel(t) +  + l := testlog.Logger(t, log.LevelInfo) +  +- beaconApi := fakebeacon.NewBeacon(l, t.TempDir(), uint64(0), uint64(12)) ++ blobStore := e2eutils.NewBlobStore() ++ beaconApi := fakebeacon.NewBeacon(l, blobStore, uint64(0), uint64(12)) + t.Cleanup(func() { + _ = beaconApi.Close() + })
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+64
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/system/da/multi_test.go CELO/op-e2e/system/da/multi_test.go +new file mode 100644 +index 0000000000000000000000000000000000000000..8272930da765b3de6cd8b7aa9a3fbbc246890651 +--- /dev/null ++++ CELO/op-e2e/system/da/multi_test.go +@@ -0,0 +1,64 @@ ++package da ++ ++import ( ++ "context" ++ "math/big" ++ "testing" ++ "time" ++ ++ op_e2e "github.com/ethereum-optimism/optimism/op-e2e" ++ ++ "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" ++ "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/transactions" ++ "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" ++ "github.com/ethereum-optimism/optimism/op-node/rollup/derive" ++ "github.com/stretchr/testify/require" ++) ++ ++func TestBatcherMultiTx(t *testing.T) { ++ op_e2e.InitParallel(t) ++ ++ cfg := e2esys.DefaultSystemConfig(t) ++ cfg.BatcherMaxPendingTransactions = 0 // no limit on parallel txs ++ // ensures that batcher txs are as small as possible ++ cfg.BatcherMaxL1TxSizeBytes = derive.FrameV0OverHeadSize + 1 /*version bytes*/ + 1 ++ cfg.DisableBatcher = true ++ sys, err := cfg.Start(t) ++ require.NoError(t, err, "Error starting up system") ++ ++ l1Client := sys.NodeClient("l1") ++ l2Seq := sys.NodeClient("sequencer") ++ ++ _, err = geth.WaitForBlock(big.NewInt(10), l2Seq, time.Duration(cfg.DeployConfig.L2BlockTime*15)*time.Second) ++ require.NoError(t, err, "Waiting for L2 blocks") ++ ++ ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) ++ defer cancel() ++ l1Number, err := l1Client.BlockNumber(ctx) ++ require.NoError(t, err) ++ ++ // start batch submission ++ driver := sys.BatchSubmitter.TestDriver() ++ err = driver.StartBatchSubmitting() ++ require.NoError(t, err) ++ ++ totalBatcherTxsCount := int64(0) ++ // wait for up to 5 L1 blocks, usually only 3 is required, but it's ++ // possible additional L1 blocks will be created before the batcher starts, ++ // so we wait additional blocks. ++ for i := int64(0); i < 5; i++ { ++ block, err := geth.WaitForBlock(big.NewInt(int64(l1Number)+i), l1Client, time.Duration(cfg.DeployConfig.L1BlockTime*2)*time.Second) ++ require.NoError(t, err, "Waiting for l1 blocks") ++ // there are possibly other services (proposer/challenger) in the background sending txs ++ // so we only count the batcher txs ++ batcherTxCount, err := transactions.TransactionsBySender(block, cfg.DeployConfig.BatchSenderAddress) ++ require.NoError(t, err) ++ totalBatcherTxsCount += int64(batcherTxCount) ++ ++ if totalBatcherTxsCount >= 10 { ++ return ++ } ++ } ++ ++ t.Fatal("Expected at least 10 transactions from the batcher") ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+131
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/system/da/startstop_test.go CELO/op-e2e/system/da/startstop_test.go +new file mode 100644 +index 0000000000000000000000000000000000000000..c15c1c03943898533df4c2db9150f449a110a5b3 +--- /dev/null ++++ CELO/op-e2e/system/da/startstop_test.go +@@ -0,0 +1,131 @@ ++package da ++ ++import ( ++ "context" ++ "math/big" ++ "testing" ++ "time" ++ ++ op_e2e "github.com/ethereum-optimism/optimism/op-e2e" ++ ++ "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" ++ "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" ++ "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" ++ "github.com/ethereum-optimism/optimism/op-e2e/system/helpers" ++ "github.com/ethereum-optimism/optimism/op-node/rollup/derive" ++ "github.com/ethereum/go-ethereum/common" ++ "github.com/ethereum/go-ethereum/core/types" ++ "github.com/stretchr/testify/require" ++) ++ ++// TestSystemBatchType run each system e2e test case in singular batch mode and span batch mode. ++// If the test case tests batch submission and advancing safe head, it should be tested in both singular and span batch mode. ++func TestSystemBatchType(t *testing.T) { ++ tests := []struct { ++ name string ++ f func(*testing.T, func(*e2esys.SystemConfig)) ++ }{ ++ {"StopStartBatcher", StopStartBatcher}, ++ } ++ for _, test := range tests { ++ test := test ++ t.Run(test.name+"_SingularBatch", func(t *testing.T) { ++ test.f(t, func(sc *e2esys.SystemConfig) { ++ sc.BatcherBatchType = derive.SingularBatchType ++ }) ++ }) ++ t.Run(test.name+"_SpanBatch", func(t *testing.T) { ++ test.f(t, func(sc *e2esys.SystemConfig) { ++ sc.BatcherBatchType = derive.SpanBatchType ++ }) ++ }) ++ t.Run(test.name+"_SpanBatchMaxBlocks", func(t *testing.T) { ++ test.f(t, func(sc *e2esys.SystemConfig) { ++ sc.BatcherBatchType = derive.SpanBatchType ++ sc.BatcherMaxBlocksPerSpanBatch = 2 ++ }) ++ }) ++ } ++} ++ ++func StopStartBatcher(t *testing.T, cfgMod func(*e2esys.SystemConfig)) { ++ op_e2e.InitParallel(t) ++ ++ cfg := e2esys.DefaultSystemConfig(t) ++ cfgMod(&cfg) ++ sys, err := cfg.Start(t) ++ require.NoError(t, err, "Error starting up system") ++ ++ rollupClient := sys.RollupClient("verifier") ++ ++ l2Seq := sys.NodeClient("sequencer") ++ l2Verif := sys.NodeClient("verifier") ++ ++ // retrieve the initial sync status ++ seqStatus, err := rollupClient.SyncStatus(context.Background()) ++ require.NoError(t, err) ++ ++ nonce := uint64(0) ++ sendTx := func() *types.Receipt { ++ // Submit TX to L2 sequencer node ++ receipt := helpers.SendL2Tx(t, cfg, l2Seq, cfg.Secrets.Alice, func(opts *helpers.TxOpts) { ++ opts.ToAddr = &common.Address{0xff, 0xff} ++ opts.Value = big.NewInt(1_000_000_000) ++ opts.Nonce = nonce ++ }) ++ nonce++ ++ return receipt ++ } ++ // send a transaction ++ receipt := sendTx() ++ ++ // wait until the block the tx was first included in shows up in the safe chain on the verifier ++ safeBlockInclusionDuration := time.Duration(6*cfg.DeployConfig.L1BlockTime) * time.Second ++ _, err = geth.WaitForBlock(receipt.BlockNumber, l2Verif, safeBlockInclusionDuration) ++ require.NoError(t, err, "Waiting for block on verifier") ++ require.NoError(t, wait.ForProcessingFullBatch(context.Background(), rollupClient)) ++ ++ // ensure the safe chain advances ++ newSeqStatus, err := rollupClient.SyncStatus(context.Background()) ++ require.NoError(t, err) ++ require.Greater(t, newSeqStatus.SafeL2.Number, seqStatus.SafeL2.Number, "Safe chain did not advance") ++ ++ driver := sys.BatchSubmitter.TestDriver() ++ // stop the batch submission ++ err = driver.StopBatchSubmitting(context.Background()) ++ require.NoError(t, err) ++ ++ // wait for any old safe blocks being submitted / derived ++ time.Sleep(safeBlockInclusionDuration) ++ ++ // get the initial sync status ++ seqStatus, err = rollupClient.SyncStatus(context.Background()) ++ require.NoError(t, err) ++ ++ // send another tx ++ sendTx() ++ time.Sleep(safeBlockInclusionDuration) ++ ++ // ensure that the safe chain does not advance while the batcher is stopped ++ newSeqStatus, err = rollupClient.SyncStatus(context.Background()) ++ require.NoError(t, err) ++ require.Equal(t, newSeqStatus.SafeL2.Number, seqStatus.SafeL2.Number, "Safe chain advanced while batcher was stopped") ++ ++ // start the batch submission ++ err = driver.StartBatchSubmitting() ++ require.NoError(t, err) ++ time.Sleep(safeBlockInclusionDuration) ++ ++ // send a third tx ++ receipt = sendTx() ++ ++ // wait until the block the tx was first included in shows up in the safe chain on the verifier ++ _, err = geth.WaitForBlock(receipt.BlockNumber, l2Verif, safeBlockInclusionDuration) ++ require.NoError(t, err, "Waiting for block on verifier") ++ require.NoError(t, wait.ForProcessingFullBatch(context.Background(), rollupClient)) ++ ++ // ensure that the safe chain advances after restarting the batcher ++ newSeqStatus, err = rollupClient.SyncStatus(context.Background()) ++ require.NoError(t, err) ++ require.Greater(t, newSeqStatus.SafeL2.Number, seqStatus.SafeL2.Number, "Safe chain did not advance after batcher was restarted") ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+1
+
-1
+ +
+ +
+
+
diff --git OP/op-e2e/external.go CELO/op-e2e/system/e2esys/external.go +rename from op-e2e/external.go +rename to op-e2e/system/e2esys/external.go +index 7b83aef4ff661efde2deb6620c825e5e377bf50d..cfdc4fcb88cc77d0aac1a8d7812b97c58600ce10 100644 +--- OP/op-e2e/external.go ++++ CELO/op-e2e/system/e2esys/external.go +@@ -1,4 +1,4 @@ +-package op_e2e ++package e2esys +  + import ( + "encoding/json"
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+103
+
-62
+ +
+ +
+
+
diff --git OP/op-e2e/setup.go CELO/op-e2e/system/e2esys/setup.go +rename from op-e2e/setup.go +rename to op-e2e/system/e2esys/setup.go +index cd07e081d0dd4b96d27feb28c1f694a6b9f14559..7d6a51a64b9a195b79be133c70e078cdc7f17acf 100644 +--- OP/op-e2e/setup.go ++++ CELO/op-e2e/system/e2esys/setup.go +@@ -1,4 +1,4 @@ +-package op_e2e ++package e2esys +  + import ( + "context" +@@ -33,12 +33,14 @@ "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/types" ++ "github.com/ethereum/go-ethereum/eth/ethconfig" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/node" + "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/rpc" +  ++ altda "github.com/ethereum-optimism/optimism/op-alt-da" + bss "github.com/ethereum-optimism/optimism/op-batcher/batcher" + batcherFlags "github.com/ethereum-optimism/optimism/op-batcher/flags" + "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" +@@ -49,6 +51,7 @@ "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/fakebeacon" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/opnode" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/services" ++ "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/setuputils" + "github.com/ethereum-optimism/optimism/op-node/chaincfg" + rollupNode "github.com/ethereum-optimism/optimism/op-node/node" + "github.com/ethereum-optimism/optimism/op-node/p2p" +@@ -67,7 +70,6 @@ oplog "github.com/ethereum-optimism/optimism/op-service/log" + "github.com/ethereum-optimism/optimism/op-service/predeploys" + "github.com/ethereum-optimism/optimism/op-service/sources" + "github.com/ethereum-optimism/optimism/op-service/testlog" +- "github.com/ethereum-optimism/optimism/op-service/txmgr" + ) +  + const ( +@@ -81,20 +83,6 @@ testingJWTSecret = [32]byte{123} + genesisTime = hexutil.Uint64(0) + ) +  +-func newTxMgrConfig(l1Addr string, privKey *ecdsa.PrivateKey) txmgr.CLIConfig { +- return txmgr.CLIConfig{ +- L1RPCURL: l1Addr, +- PrivateKey: hexPriv(privKey), +- NumConfirmations: 1, +- SafeAbortNonceTooLowCount: 3, +- FeeLimitMultiplier: 5, +- ResubmissionTimeout: 3 * time.Second, +- ReceiptQueryInterval: 50 * time.Millisecond, +- NetworkTimeout: 2 * time.Second, +- TxNotInMempoolTimeout: 2 * time.Minute, +- } +-} +- + func DefaultSystemConfig(t testing.TB) SystemConfig { + config.ExternalL2TestParms.SkipIfNecessary(t) +  +@@ -164,18 +152,19 @@ Sync: sync.Config{SyncMode: sync.CLSync}, + }, + }, + Loggers: map[string]log.Logger{ +- RoleVerif: testlog.Logger(t, log.LevelInfo).New("role", RoleVerif), +- RoleSeq: testlog.Logger(t, log.LevelInfo).New("role", RoleSeq), +- "batcher": testlog.Logger(t, log.LevelInfo).New("role", "batcher"), +- "proposer": testlog.Logger(t, log.LevelInfo).New("role", "proposer"), ++ RoleVerif: testlog.Logger(t, log.LevelInfo).New("role", RoleVerif), ++ RoleSeq: testlog.Logger(t, log.LevelInfo).New("role", RoleSeq), ++ "batcher": testlog.Logger(t, log.LevelInfo).New("role", "batcher"), ++ "proposer": testlog.Logger(t, log.LevelInfo).New("role", "proposer"), ++ "da-server": testlog.Logger(t, log.LevelInfo).New("role", "da-server"), + }, +- GethOptions: map[string][]geth.GethOption{}, +- P2PTopology: nil, // no P2P connectivity by default +- NonFinalizedProposals: false, +- ExternalL2Shim: config.ExternalL2Shim, +- DataAvailabilityType: batcherFlags.CalldataType, +- MaxPendingTransactions: 1, +- BatcherTargetNumFrames: 1, ++ GethOptions: map[string][]geth.GethOption{}, ++ P2PTopology: nil, // no P2P connectivity by default ++ NonFinalizedProposals: false, ++ ExternalL2Shim: config.ExternalL2Shim, ++ DataAvailabilityType: batcherFlags.CalldataType, ++ BatcherMaxPendingTransactions: 1, ++ BatcherTargetNumFrames: 1, + } + } +  +@@ -278,6 +267,9 @@ + // Explicitly disable batcher, for tests that rely on unsafe L2 payloads + DisableBatcher bool +  ++ // Explicitly disable setting `RollupSequencerHTTP` to forward txs from sentry nodes ++ DisableTxForwarder bool ++ + // Configure data-availability type that is used by the batcher. + DataAvailabilityType batcherFlags.DataAvailabilityType +  +@@ -298,12 +290,16 @@ + // If >0, limits the number of blocks per span batch + BatcherMaxBlocksPerSpanBatch int +  ++ // BatcherMaxPendingTransactions determines how many transactions the batcher will try to send ++ // concurrently. 0 means unlimited. ++ BatcherMaxPendingTransactions uint64 ++ ++ // BatcherMaxConcurrentDARequest determines how many DAserver requests the batcher is allowed to ++ // make concurrently. 0 means unlimited. ++ BatcherMaxConcurrentDARequest uint64 ++ + // SupportL1TimeTravel determines if the L1 node supports quickly skipping forward in time + SupportL1TimeTravel bool +- +- // MaxPendingTransactions determines how many transactions the batcher will try to send +- // concurrently. 0 means unlimited. +- MaxPendingTransactions uint64 + } +  + type System struct { +@@ -319,6 +315,7 @@ RollupNodes map[string]services.RollupNode + L2OutputSubmitter *l2os.ProposerService + BatchSubmitter *bss.BatcherService + Mocknet mocknet.Mocknet ++ FakeAltDAServer *altda.FakeDAServer +  + L1BeaconAPIAddr endpoint.RestHTTP +  +@@ -438,25 +435,25 @@ } + require.NoError(sys.t, combinedErr, "Failed to stop system") + } +  +-type systemConfigHook func(sCfg *SystemConfig, s *System) ++type SystemConfigHook func(sCfg *SystemConfig, s *System) +  + type SystemConfigOption struct { +- key string +- role string +- action systemConfigHook ++ Key string ++ Role string ++ Action SystemConfigHook + } +  + type SystemConfigOptions struct { +- opts map[string]systemConfigHook ++ opts map[string]SystemConfigHook + } +  + func NewSystemConfigOptions(_opts []SystemConfigOption) (SystemConfigOptions, error) { +- opts := make(map[string]systemConfigHook) ++ opts := make(map[string]SystemConfigHook) + for _, opt := range _opts { +- if _, ok := opts[opt.key+":"+opt.role]; ok { +- return SystemConfigOptions{}, fmt.Errorf("duplicate option for key %s and role %s", opt.key, opt.role) ++ if _, ok := opts[opt.Key+":"+opt.Role]; ok { ++ return SystemConfigOptions{}, fmt.Errorf("duplicate option for key %s and role %s", opt.Key, opt.Role) + } +- opts[opt.key+":"+opt.role] = opt.action ++ opts[opt.Key+":"+opt.Role] = opt.Action + } +  + return SystemConfigOptions{ +@@ -464,7 +461,7 @@ opts: opts, + }, nil + } +  +-func (s *SystemConfigOptions) Get(key, role string) (systemConfigHook, bool) { ++func (s *SystemConfigOptions) Get(key, role string) (SystemConfigHook, bool) { + v, ok := s.opts[key+":"+role] + return v, ok + } +@@ -522,7 +519,7 @@ allocsMode := cfg.DeployConfig.AllocMode(l1Block.Time()) +  + t.Log("Generating L2 genesis", "l2_allocs_mode", string(allocsMode)) + l2Allocs := config.L2Allocs(allocsMode) +- l2Genesis, err := genesis.BuildL2Genesis(cfg.DeployConfig, l2Allocs, l1Block) ++ l2Genesis, err := genesis.BuildL2Genesis(cfg.DeployConfig, l2Allocs, l1Block.Header()) + if err != nil { + return nil, err + } +@@ -543,6 +540,16 @@ } + } + } +  ++ var rollupAltDAConfig *rollup.AltDAConfig ++ if cfg.DeployConfig.UseAltDA { ++ rollupAltDAConfig = &rollup.AltDAConfig{ ++ DAChallengeAddress: cfg.L1Deployments.DataAvailabilityChallengeProxy, ++ DAChallengeWindow: cfg.DeployConfig.DAChallengeWindow, ++ DAResolveWindow: cfg.DeployConfig.DAResolveWindow, ++ CommitmentType: altda.GenericCommitmentString, ++ } ++ } ++ + makeRollupConfig := func() rollup.Config { + return rollup.Config{ + Genesis: rollup.Genesis{ +@@ -573,7 +580,9 @@ EcotoneTime: cfg.DeployConfig.EcotoneTime(uint64(cfg.DeployConfig.L1GenesisBlockTimestamp)), + FjordTime: cfg.DeployConfig.FjordTime(uint64(cfg.DeployConfig.L1GenesisBlockTimestamp)), + GraniteTime: cfg.DeployConfig.GraniteTime(uint64(cfg.DeployConfig.L1GenesisBlockTimestamp)), + InteropTime: cfg.DeployConfig.InteropTime(uint64(cfg.DeployConfig.L1GenesisBlockTimestamp)), ++ Cel2Time: cfg.DeployConfig.RegolithTime(uint64(cfg.DeployConfig.L1GenesisBlockTimestamp)), + ProtocolVersionsAddress: cfg.L1Deployments.ProtocolVersionsProxy, ++ AltDAConfig: rollupAltDAConfig, + } + } + defaultConfig := makeRollupConfig() +@@ -584,7 +593,7 @@ sys.RollupConfig = &defaultConfig +  + // Create a fake Beacon node to hold on to blobs created by the L1 miner, and to serve them to L2 + bcn := fakebeacon.NewBeacon(testlog.Logger(t, log.LevelInfo).New("role", "l1_cl"), +- path.Join(cfg.BlobsPath, "l1_cl"), l1Genesis.Timestamp, cfg.DeployConfig.L1BlockTime) ++ e2eutils.NewBlobStore(), l1Genesis.Timestamp, cfg.DeployConfig.L1BlockTime) + t.Cleanup(func() { + _ = bcn.Close() + }) +@@ -606,25 +615,44 @@ if err != nil { + return nil, err + } +  ++ // Ordered such that the Sequencer is initialized first. Setup this way so that ++ // the `RollupSequencerHTTP` GethOption can be supplied to any sentry nodes. ++ l2Nodes := []string{RoleSeq} + for name := range cfg.Nodes { +- if name == RoleL1 { +- return nil, fmt.Errorf("node name %s is reserved for L1 node", RoleL1) ++ if name == RoleSeq { ++ continue + } ++ l2Nodes = append(l2Nodes, name) ++ } ++ ++ for _, name := range l2Nodes { + var ethClient services.EthInstance + if cfg.ExternalL2Shim == "" { ++ if name != RoleSeq && !cfg.DisableTxForwarder { ++ cfg.GethOptions[name] = append(cfg.GethOptions[name], func(ethCfg *ethconfig.Config, nodeCfg *node.Config) error { ++ ethCfg.RollupSequencerHTTP = sys.EthInstances[RoleSeq].UserRPC().RPC() ++ return nil ++ }) ++ } ++ + l2Geth, err := geth.InitL2(name, l2Genesis, cfg.JWTFilePath, cfg.GethOptions[name]...) + if err != nil { + return nil, err + } +- err = l2Geth.Node.Start() +- if err != nil { ++ if err := l2Geth.Node.Start(); err != nil { + return nil, err + } ++ + ethClient = l2Geth + } else { + if len(cfg.GethOptions[name]) > 0 { + t.Skip("External L2 nodes do not support configuration through GethOptions") + } ++ ++ if name != RoleSeq && !cfg.DisableTxForwarder { ++ cfg.Loggers[name].Warn("External L2 nodes do not support `RollupSequencerHTTP` configuration. No tx forwarding support.") ++ } ++ + ethClient = (&ExternalRunner{ + Name: name, + BinPath: cfg.ExternalL2Shim, +@@ -632,6 +660,7 @@ Genesis: l2Genesis, + JWTPath: cfg.JWTFilePath, + }).Run(t) + } ++ + sys.EthInstances[name] = ethClient + } +  +@@ -639,8 +668,8 @@ // Configure connections to L1 and L2 for rollup nodes. + // TODO: refactor testing to allow use of in-process rpc connections instead + // of only websockets (which are required for external eth client tests). + for name, nodeCfg := range cfg.Nodes { +- configureL1(nodeCfg, sys.EthInstances[RoleL1], sys.L1BeaconEndpoint()) +- configureL2(nodeCfg, sys.EthInstances[name], cfg.JWTSecret) ++ ConfigureL1(nodeCfg, sys.EthInstances[RoleL1], sys.L1BeaconEndpoint()) ++ ConfigureL2(nodeCfg, sys.EthInstances[name], cfg.JWTSecret) + } +  + l1Client := sys.NodeClient(RoleL1) +@@ -658,7 +687,7 @@ initHostMaybe := func(name string) (*p2p.Prepared, error) { + if p, ok := p2pNodes[name]; ok { + return p, nil + } +- h, err := sys.newMockNetPeer() ++ h, err := sys.NewMockNetPeer() + if err != nil { + return nil, fmt.Errorf("failed to init p2p host for node %s", name) + } +@@ -771,7 +800,7 @@ DGFAddress: config.L1Deployments.DisputeGameFactoryProxy.Hex(), + ProposalInterval: 6 * time.Second, + DisputeGameType: 254, // Fast game type + PollInterval: 500 * time.Millisecond, +- TxMgrConfig: newTxMgrConfig(sys.EthInstances[RoleL1].UserRPC().RPC(), cfg.Secrets.Proposer), ++ TxMgrConfig: setuputils.NewTxMgrConfig(sys.EthInstances[RoleL1].UserRPC(), cfg.Secrets.Proposer), + AllowNonFinalized: cfg.NonFinalizedProposals, + LogConfig: oplog.CLIConfig{ + Level: log.LvlInfo, +@@ -784,7 +813,7 @@ L1EthRpc: sys.EthInstances[RoleL1].UserRPC().RPC(), + RollupRpc: sys.RollupNodes[RoleSeq].UserRPC().RPC(), + L2OOAddress: config.L1Deployments.L2OutputOracleProxy.Hex(), + PollInterval: 500 * time.Millisecond, +- TxMgrConfig: newTxMgrConfig(sys.EthInstances[RoleL1].UserRPC().RPC(), cfg.Secrets.Proposer), ++ TxMgrConfig: setuputils.NewTxMgrConfig(sys.EthInstances[RoleL1].UserRPC(), cfg.Secrets.Proposer), + AllowNonFinalized: cfg.NonFinalizedProposals, + LogConfig: oplog.CLIConfig{ + Level: log.LvlInfo, +@@ -819,11 +848,27 @@ if _, ok := opts.Get("compressionAlgo", "brotli"); ok { + compressionAlgo = derive.Brotli10 + } +  ++ var batcherAltDACLIConfig altda.CLIConfig ++ if cfg.DeployConfig.UseAltDA { ++ fakeAltDAServer := altda.NewFakeDAServer("127.0.0.1", 0, sys.Cfg.Loggers["da-server"]) ++ if err := fakeAltDAServer.Start(); err != nil { ++ return nil, fmt.Errorf("failed to start fake altDA server: %w", err) ++ } ++ sys.FakeAltDAServer = fakeAltDAServer ++ ++ batcherAltDACLIConfig = altda.CLIConfig{ ++ Enabled: cfg.DeployConfig.UseAltDA, ++ DAServerURL: fakeAltDAServer.HttpEndpoint(), ++ VerifyOnRead: true, ++ GenericDA: true, ++ MaxConcurrentRequests: cfg.BatcherMaxConcurrentDARequest, ++ } ++ } + batcherCLIConfig := &bss.CLIConfig{ + L1EthRpc: sys.EthInstances[RoleL1].UserRPC().RPC(), + L2EthRpc: sys.EthInstances[RoleSeq].UserRPC().RPC(), + RollupRpc: sys.RollupNodes[RoleSeq].UserRPC().RPC(), +- MaxPendingTransactions: cfg.MaxPendingTransactions, ++ MaxPendingTransactions: cfg.BatcherMaxPendingTransactions, + MaxChannelDuration: 1, + MaxL1TxSize: batcherMaxL1TxSizeBytes, + TestUseMaxTxSizeForBlobs: cfg.BatcherUseMaxTxSizeForBlobs, +@@ -831,7 +876,7 @@ TargetNumFrames: int(batcherTargetNumFrames), + ApproxComprRatio: 0.4, + SubSafetyMargin: 4, + PollInterval: 50 * time.Millisecond, +- TxMgrConfig: newTxMgrConfig(sys.EthInstances[RoleL1].UserRPC().RPC(), cfg.Secrets.Batcher), ++ TxMgrConfig: setuputils.NewTxMgrConfig(sys.EthInstances[RoleL1].UserRPC(), cfg.Secrets.Batcher), + LogConfig: oplog.CLIConfig{ + Level: log.LevelInfo, + Format: oplog.FormatText, +@@ -841,6 +886,7 @@ BatchType: cfg.BatcherBatchType, + MaxBlocksPerSpanBatch: cfg.BatcherMaxBlocksPerSpanBatch, + DataAvailabilityType: sys.Cfg.DataAvailabilityType, + CompressionAlgo: compressionAlgo, ++ AltDA: batcherAltDACLIConfig, + } + // Batch Submitter + batcher, err := bss.BatcherServiceFromCLIConfig(context.Background(), "0.0.1", batcherCLIConfig, sys.Cfg.Loggers["batcher"]) +@@ -862,7 +908,7 @@ // the internet). + var blackholeIP6 = net.ParseIP("100::") +  + // mocknet doesn't allow us to add a peerstore without fully creating the peer ourselves +-func (sys *System) newMockNetPeer() (host.Host, error) { ++func (sys *System) NewMockNetPeer() (host.Host, error) { + sk, _, err := ic.GenerateECDSAKeyPair(rand.Reader) + if err != nil { + return nil, err +@@ -919,7 +965,7 @@ panic(fmt.Sprintf("System: no test account for index %d", idx)) + } + } +  +-func configureL1(rollupNodeCfg *rollupNode.Config, l1Node services.EthInstance, beaconEndpoint endpoint.RestHTTP) { ++func ConfigureL1(rollupNodeCfg *rollupNode.Config, l1Node services.EthInstance, beaconEndpoint endpoint.RestHTTP) { + rollupNodeCfg.L1 = &rollupNode.L1EndpointConfig{ + L1NodeAddr: endpoint.SelectRPC(EnvRPCPreference(), l1Node.UserRPC()), + L1TrustRPC: false, +@@ -934,7 +980,7 @@ BeaconAddr: beaconEndpoint.RestHTTP(), + } + } +  +-func configureL2(rollupNodeCfg *rollupNode.Config, l2Node services.EthInstance, jwtSecret [32]byte) { ++func ConfigureL2(rollupNodeCfg *rollupNode.Config, l2Node services.EthInstance, jwtSecret [32]byte) { + rollupNodeCfg.L2 = &rollupNode.L2EndpointConfig{ + L2EngineAddr: endpoint.SelectRPC(EnvRPCPreference(), l2Node.AuthRPC()), + L2EngineJWTSecret: jwtSecret, +@@ -947,11 +993,6 @@ } +  + func (cfg SystemConfig) L2ChainIDBig() *big.Int { + return new(big.Int).SetUint64(cfg.DeployConfig.L2ChainID) +-} +- +-func hexPriv(in *ecdsa.PrivateKey) string { +- b := e2eutils.EncodePrivKey(in) +- return hexutil.Encode(b) + } +  + func (sys *System) RollupClient(name string) *sources.RollupClient {
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+267
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/system/fees/fees_test.go CELO/op-e2e/system/fees/fees_test.go +new file mode 100644 +index 0000000000000000000000000000000000000000..b1dfd1c73fd961c745fdf4c6b5400499557859a2 +--- /dev/null ++++ CELO/op-e2e/system/fees/fees_test.go +@@ -0,0 +1,267 @@ ++package fees ++ ++import ( ++ "context" ++ "math/big" ++ "testing" ++ "time" ++ ++ op_e2e "github.com/ethereum-optimism/optimism/op-e2e" ++ ++ "github.com/ethereum-optimism/optimism/op-e2e/bindings" ++ "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" ++ "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" ++ "github.com/ethereum-optimism/optimism/op-e2e/system/helpers" ++ "github.com/ethereum-optimism/optimism/op-service/predeploys" ++ "github.com/ethereum/go-ethereum/accounts/abi/bind" ++ "github.com/ethereum/go-ethereum/common" ++ "github.com/ethereum/go-ethereum/common/hexutil" ++ "github.com/ethereum/go-ethereum/core/types" ++ "github.com/ethereum/go-ethereum/crypto" ++ "github.com/ethereum/go-ethereum/ethclient" ++ "github.com/ethereum/go-ethereum/params" ++ "github.com/ethereum/go-ethereum/rpc" ++ "github.com/stretchr/testify/require" ++) ++ ++func TestMain(m *testing.M) { ++ op_e2e.RunMain(m) ++} ++ ++type stateGetterAdapter struct { ++ ctx context.Context ++ t *testing.T ++ client *ethclient.Client ++ blockNum *big.Int ++} ++ ++func (sga *stateGetterAdapter) GetState(addr common.Address, key common.Hash) common.Hash { ++ sga.t.Helper() ++ val, err := sga.client.StorageAt(sga.ctx, addr, key, sga.blockNum) ++ require.NoError(sga.t, err) ++ var res common.Hash ++ copy(res[:], val) ++ return res ++} ++ ++// TestFees checks that L1/L2 fees are handled. ++func TestFees(t *testing.T) { ++ t.Run("pre-regolith", func(t *testing.T) { ++ op_e2e.InitParallel(t) ++ cfg := e2esys.RegolithSystemConfig(t, nil) ++ cfg.DeployConfig.L1GenesisBlockBaseFeePerGas = (*hexutil.Big)(big.NewInt(7)) ++ ++ testFees(t, cfg) ++ }) ++ t.Run("regolith", func(t *testing.T) { ++ op_e2e.InitParallel(t) ++ cfg := e2esys.RegolithSystemConfig(t, new(hexutil.Uint64)) ++ cfg.DeployConfig.L1GenesisBlockBaseFeePerGas = (*hexutil.Big)(big.NewInt(7)) ++ ++ testFees(t, cfg) ++ }) ++ t.Run("ecotone", func(t *testing.T) { ++ op_e2e.InitParallel(t) ++ cfg := e2esys.EcotoneSystemConfig(t, new(hexutil.Uint64)) ++ cfg.DeployConfig.L1GenesisBlockBaseFeePerGas = (*hexutil.Big)(big.NewInt(7)) ++ ++ testFees(t, cfg) ++ }) ++ t.Run("fjord", func(t *testing.T) { ++ op_e2e.InitParallel(t) ++ cfg := e2esys.DefaultSystemConfig(t) ++ cfg.DeployConfig.L1GenesisBlockBaseFeePerGas = (*hexutil.Big)(big.NewInt(7)) ++ ++ cfg.DeployConfig.L2GenesisRegolithTimeOffset = new(hexutil.Uint64) ++ cfg.DeployConfig.L2GenesisCanyonTimeOffset = new(hexutil.Uint64) ++ cfg.DeployConfig.L2GenesisDeltaTimeOffset = new(hexutil.Uint64) ++ cfg.DeployConfig.L2GenesisEcotoneTimeOffset = new(hexutil.Uint64) ++ cfg.DeployConfig.L2GenesisFjordTimeOffset = new(hexutil.Uint64) ++ testFees(t, cfg) ++ }) ++} ++ ++func testFees(t *testing.T, cfg e2esys.SystemConfig) { ++ t.Skipf("Skipping fee tests for tests for now, Celo changes fee handling and the tests need more work!") ++ sys, err := cfg.Start(t) ++ require.Nil(t, err, "Error starting up system") ++ ++ l2Seq := sys.NodeClient("sequencer") ++ l2Verif := sys.NodeClient("verifier") ++ l1 := sys.NodeClient("l1") ++ ++ // Wait for first block after genesis. The genesis block has zero L1Block values and will throw off the GPO checks ++ _, err = geth.WaitForBlock(big.NewInt(1), l2Verif, time.Minute) ++ require.NoError(t, err) ++ ++ config := sys.L2Genesis().Config ++ ++ sga := &stateGetterAdapter{ ++ ctx: context.Background(), ++ t: t, ++ client: l2Seq, ++ } ++ ++ l1CostFn := types.NewL1CostFunc(config, sga) ++ ++ // Transactor Account ++ ethPrivKey := cfg.Secrets.Alice ++ fromAddr := crypto.PubkeyToAddress(ethPrivKey.PublicKey) ++ ++ require.NotEqual(t, cfg.DeployConfig.L2OutputOracleProposer, fromAddr) ++ require.NotEqual(t, cfg.DeployConfig.BatchSenderAddress, fromAddr) ++ ++ // Find gaspriceoracle contract ++ gpoContract, err := bindings.NewGasPriceOracle(predeploys.GasPriceOracleAddr, l2Seq) ++ require.Nil(t, err) ++ ++ if !sys.RollupConfig.IsEcotone(sys.L2GenesisCfg.Timestamp) { ++ overhead, err := gpoContract.Overhead(&bind.CallOpts{}) ++ require.Nil(t, err, "reading gpo overhead") ++ require.Equal(t, overhead.Uint64(), cfg.DeployConfig.GasPriceOracleOverhead, "wrong gpo overhead") ++ ++ scalar, err := gpoContract.Scalar(&bind.CallOpts{}) ++ require.Nil(t, err, "reading gpo scalar") ++ feeScalar := cfg.DeployConfig.FeeScalar() ++ require.Equal(t, scalar, new(big.Int).SetBytes(feeScalar[:]), "wrong gpo scalar") ++ } else { ++ _, err := gpoContract.Overhead(&bind.CallOpts{}) ++ require.ErrorContains(t, err, "deprecated") ++ _, err = gpoContract.Scalar(&bind.CallOpts{}) ++ require.ErrorContains(t, err, "deprecated") ++ } ++ ++ decimals, err := gpoContract.Decimals(&bind.CallOpts{}) ++ require.Nil(t, err, "reading gpo decimals") ++ ++ require.Equal(t, decimals.Uint64(), uint64(6), "wrong gpo decimals") ++ ++ // BaseFee Recipient ++ baseFeeRecipientStartBalance, err := l2Seq.BalanceAt(context.Background(), predeploys.BaseFeeVaultAddr, big.NewInt(rpc.EarliestBlockNumber.Int64())) ++ require.Nil(t, err) ++ ++ // L1Fee Recipient ++ l1FeeRecipientStartBalance, err := l2Seq.BalanceAt(context.Background(), predeploys.L1FeeVaultAddr, big.NewInt(rpc.EarliestBlockNumber.Int64())) ++ require.Nil(t, err) ++ ++ sequencerFeeVaultStartBalance, err := l2Seq.BalanceAt(context.Background(), predeploys.SequencerFeeVaultAddr, big.NewInt(rpc.EarliestBlockNumber.Int64())) ++ require.Nil(t, err) ++ ++ genesisBlock, err := l2Seq.BlockByNumber(context.Background(), big.NewInt(rpc.EarliestBlockNumber.Int64())) ++ require.NoError(t, err) ++ ++ coinbaseStartBalance, err := l2Seq.BalanceAt(context.Background(), genesisBlock.Coinbase(), big.NewInt(rpc.EarliestBlockNumber.Int64())) ++ require.NoError(t, err) ++ ++ // Simple transfer from signer to random account ++ startBalance, err := l2Seq.BalanceAt(context.Background(), fromAddr, big.NewInt(rpc.EarliestBlockNumber.Int64())) ++ require.Nil(t, err) ++ require.Greater(t, startBalance.Uint64(), big.NewInt(params.Ether).Uint64()) ++ ++ transferAmount := big.NewInt(params.Ether) ++ gasTip := big.NewInt(10) ++ receipt := helpers.SendL2Tx(t, cfg, l2Seq, ethPrivKey, func(opts *helpers.TxOpts) { ++ opts.ToAddr = &common.Address{0xff, 0xff} ++ opts.Value = transferAmount ++ opts.GasTipCap = gasTip ++ opts.Gas = 21000 ++ opts.GasFeeCap = big.NewInt(200) ++ opts.VerifyOnClients(l2Verif) ++ }) ++ ++ require.Equal(t, receipt.Status, types.ReceiptStatusSuccessful) ++ ++ header, err := l2Seq.HeaderByNumber(context.Background(), receipt.BlockNumber) ++ require.Nil(t, err) ++ ++ coinbaseEndBalance, err := l2Seq.BalanceAt(context.Background(), header.Coinbase, header.Number) ++ require.Nil(t, err) ++ ++ endBalance, err := l2Seq.BalanceAt(context.Background(), fromAddr, header.Number) ++ require.Nil(t, err) ++ ++ baseFeeRecipientEndBalance, err := l2Seq.BalanceAt(context.Background(), predeploys.BaseFeeVaultAddr, header.Number) ++ require.Nil(t, err) ++ ++ l1Header, err := l1.HeaderByNumber(context.Background(), nil) ++ require.Nil(t, err) ++ ++ l1FeeRecipientEndBalance, err := l2Seq.BalanceAt(context.Background(), predeploys.L1FeeVaultAddr, header.Number) ++ require.Nil(t, err) ++ ++ sequencerFeeVaultEndBalance, err := l2Seq.BalanceAt(context.Background(), predeploys.SequencerFeeVaultAddr, header.Number) ++ require.Nil(t, err) ++ ++ // Diff fee recipient + coinbase balances ++ baseFeeRecipientDiff := new(big.Int).Sub(baseFeeRecipientEndBalance, baseFeeRecipientStartBalance) ++ l1FeeRecipientDiff := new(big.Int).Sub(l1FeeRecipientEndBalance, l1FeeRecipientStartBalance) ++ sequencerFeeVaultDiff := new(big.Int).Sub(sequencerFeeVaultEndBalance, sequencerFeeVaultStartBalance) ++ coinbaseDiff := new(big.Int).Sub(coinbaseEndBalance, coinbaseStartBalance) ++ ++ // Tally L2 Fee ++ l2Fee := gasTip.Mul(gasTip, new(big.Int).SetUint64(receipt.GasUsed)) ++ require.Equal(t, sequencerFeeVaultDiff, coinbaseDiff, "coinbase is always sequencer fee vault") ++ require.Equal(t, l2Fee, coinbaseDiff, "l2 fee mismatch") ++ require.Equal(t, l2Fee, sequencerFeeVaultDiff) ++ ++ // Tally BaseFee ++ baseFee := new(big.Int).Mul(header.BaseFee, new(big.Int).SetUint64(receipt.GasUsed)) ++ require.Equal(t, baseFee, baseFeeRecipientDiff, "base fee mismatch") ++ ++ // Tally L1 Fee ++ tx, _, err := l2Seq.TransactionByHash(context.Background(), receipt.TxHash) ++ require.NoError(t, err, "Should be able to get transaction") ++ bytes, err := tx.MarshalBinary() ++ require.Nil(t, err) ++ ++ l1Fee := l1CostFn(tx.RollupCostData(), header.Time) ++ require.Equalf(t, l1Fee, l1FeeRecipientDiff, "L1 fee mismatch: start balance %v, end balance %v", l1FeeRecipientStartBalance, l1FeeRecipientEndBalance) ++ ++ gpoEcotone, err := gpoContract.IsEcotone(nil) ++ require.NoError(t, err) ++ require.Equal(t, sys.RollupConfig.IsEcotone(header.Time), gpoEcotone, "GPO and chain must have same ecotone view") ++ ++ gpoFjord, err := gpoContract.IsFjord(nil) ++ require.NoError(t, err) ++ require.Equal(t, sys.RollupConfig.IsFjord(header.Time), gpoFjord, "GPO and chain must have same fjord view") ++ ++ gpoL1Fee, err := gpoContract.GetL1Fee(&bind.CallOpts{}, bytes) ++ require.Nil(t, err) ++ ++ adjustedGPOFee := gpoL1Fee ++ if sys.RollupConfig.IsFjord(header.Time) { ++ // The fastlz size of the transaction is 102 bytes ++ require.Equal(t, uint64(102), tx.RollupCostData().FastLzSize) ++ // Which results in both the fjord cost function and GPO using the minimum value for the fastlz regression: ++ // Geth Linear Regression: -42.5856 + 102 * 0.8365 = 42.7374 ++ // GPO Linear Regression: -42.5856 + 170 * 0.8365 = 99.6194 ++ // The additional 68 (170 vs. 102) is due to the GPO adding 68 bytes to account for the signature. ++ require.Greater(t, types.MinTransactionSize.Uint64(), uint64(99)) ++ // Because of this, we don't need to do any adjustment as the GPO and cost func are both bounded to the minimum value. ++ // However, if the fastlz regression output is ever larger than the minimum, this will require an adjustment. ++ } else if sys.RollupConfig.IsRegolith(header.Time) { ++ // if post-regolith, adjust the GPO fee by removing the overhead it adds because of signature data ++ artificialGPOOverhead := big.NewInt(68 * 16) // it adds 68 bytes to cover signature and RLP data ++ l1BaseFee := big.NewInt(7) // we assume the L1 basefee is the minimum, 7 ++ // in our case we already include that, so we subtract it, to do a 1:1 comparison ++ adjustedGPOFee = new(big.Int).Sub(gpoL1Fee, new(big.Int).Mul(artificialGPOOverhead, l1BaseFee)) ++ } ++ require.Equal(t, l1Fee, adjustedGPOFee, "GPO reports L1 fee mismatch") ++ ++ require.Equal(t, receipt.L1Fee, l1Fee, "l1 fee in receipt is correct") ++ if !sys.RollupConfig.IsEcotone(header.Time) { // FeeScalar receipt attribute is removed as of Ecotone ++ require.Equal(t, ++ new(big.Float).Mul( ++ new(big.Float).SetInt(l1Header.BaseFee), ++ new(big.Float).Mul(new(big.Float).SetInt(receipt.L1GasUsed), receipt.FeeScalar), ++ ), ++ new(big.Float).SetInt(receipt.L1Fee), "fee field in receipt matches gas used times scalar times base fee") ++ } ++ ++ // Calculate total fee ++ baseFeeRecipientDiff.Add(baseFeeRecipientDiff, coinbaseDiff) ++ totalFee := new(big.Int).Add(baseFeeRecipientDiff, l1FeeRecipientDiff) ++ balanceDiff := new(big.Int).Sub(startBalance, endBalance) ++ balanceDiff.Sub(balanceDiff, transferAmount) ++ require.Equal(t, balanceDiff, totalFee, "balances should add up") ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+102
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/system/fees/gaspriceoracle_test.go CELO/op-e2e/system/fees/gaspriceoracle_test.go +new file mode 100644 +index 0000000000000000000000000000000000000000..58a679fa86f094a9699f809ff70154bd51582c39 +--- /dev/null ++++ CELO/op-e2e/system/fees/gaspriceoracle_test.go +@@ -0,0 +1,102 @@ ++package fees ++ ++import ( ++ "context" ++ "math" ++ "testing" ++ "time" ++ ++ op_e2e "github.com/ethereum-optimism/optimism/op-e2e" ++ ++ legacybindings "github.com/ethereum-optimism/optimism/op-e2e/bindings" ++ "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" ++ "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" ++ "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" ++ "github.com/ethereum-optimism/optimism/op-service/eth" ++ "github.com/ethereum-optimism/optimism/op-service/predeploys" ++ "github.com/ethereum/go-ethereum/accounts/abi/bind" ++ "github.com/stretchr/testify/require" ++) ++ ++// TestGasPriceOracleFeeUpdates checks that the gas price oracle cannot be locked by mis-configuring parameters. ++func TestGasPriceOracleFeeUpdates(t *testing.T) { ++ op_e2e.InitParallel(t) ++ ++ ctx, ctxCancel := context.WithCancel(context.Background()) ++ defer ctxCancel() ++ ++ maxScalars := eth.EcotoneScalars{ ++ BaseFeeScalar: math.MaxUint32, ++ BlobBaseFeeScalar: math.MaxUint32, ++ } ++ var cancel context.CancelFunc ++ ++ // Create our system configuration for L1/L2 and start it ++ cfg := e2esys.DefaultSystemConfig(t) ++ sys, err := cfg.Start(t) ++ require.NoError(t, err, "Error starting up system") ++ ++ // Obtain our sequencer, verifier, and transactor keypair. ++ l1Client := sys.NodeClient("l1") ++ l2Seq := sys.NodeClient("sequencer") ++ // l2Verif := sys.NodeClient("verifier") ++ ethPrivKey := cfg.Secrets.SysCfgOwner ++ ++ // Bind to the SystemConfig & GasPriceOracle contracts ++ sysconfig, err := legacybindings.NewSystemConfig(cfg.L1Deployments.SystemConfigProxy, l1Client) ++ require.NoError(t, err) ++ gpoContract, err := legacybindings.NewGasPriceOracleCaller(predeploys.GasPriceOracleAddr, l2Seq) ++ require.NoError(t, err) ++ ++ // Obtain our signer. ++ opts, err := bind.NewKeyedTransactorWithChainID(ethPrivKey, cfg.L1ChainIDBig()) ++ require.NoError(t, err) ++ ++ // Define our L1 transaction timeout duration. ++ txTimeoutDuration := 10 * time.Duration(cfg.DeployConfig.L1BlockTime) * time.Second ++ ++ // Update the gas config, wait for it to show up on L2, & verify that it was set as intended ++ opts.Context, cancel = context.WithTimeout(ctx, txTimeoutDuration) ++ tx, err := sysconfig.SetGasConfigEcotone(opts, maxScalars.BaseFeeScalar, maxScalars.BlobBaseFeeScalar) ++ cancel() ++ require.NoError(t, err, "SetGasConfigEcotone update tx") ++ ++ receipt, err := wait.ForReceiptOK(ctx, l1Client, tx.Hash()) ++ require.NoError(t, err, "Waiting for sysconfig set gas config update tx") ++ ++ _, err = geth.WaitForL1OriginOnL2(sys.RollupConfig, receipt.BlockNumber.Uint64(), l2Seq, txTimeoutDuration) ++ require.NoError(t, err, "waiting for L2 block to include the sysconfig update") ++ ++ baseFeeScalar, err := gpoContract.BaseFeeScalar(&bind.CallOpts{}) ++ require.NoError(t, err, "reading base fee scalar") ++ require.Equal(t, baseFeeScalar, maxScalars.BaseFeeScalar) ++ ++ blobBaseFeeScalar, err := gpoContract.BlobBaseFeeScalar(&bind.CallOpts{}) ++ require.NoError(t, err, "reading blob base fee scalar") ++ require.Equal(t, blobBaseFeeScalar, maxScalars.BlobBaseFeeScalar) ++ ++ // Now modify the scalar value & ensure that the gas params can be modified ++ normalScalars := eth.EcotoneScalars{ ++ BaseFeeScalar: 1e6, ++ BlobBaseFeeScalar: 1e6, ++ } ++ ++ opts.Context, cancel = context.WithTimeout(context.Background(), txTimeoutDuration) ++ tx, err = sysconfig.SetGasConfigEcotone(opts, normalScalars.BaseFeeScalar, normalScalars.BlobBaseFeeScalar) ++ cancel() ++ require.NoError(t, err, "SetGasConfigEcotone update tx") ++ ++ receipt, err = wait.ForReceiptOK(ctx, l1Client, tx.Hash()) ++ require.NoError(t, err, "Waiting for sysconfig set gas config update tx") ++ ++ _, err = geth.WaitForL1OriginOnL2(sys.RollupConfig, receipt.BlockNumber.Uint64(), l2Seq, txTimeoutDuration) ++ require.NoError(t, err, "waiting for L2 block to include the sysconfig update") ++ ++ baseFeeScalar, err = gpoContract.BaseFeeScalar(&bind.CallOpts{}) ++ require.NoError(t, err, "reading base fee scalar") ++ require.Equal(t, baseFeeScalar, normalScalars.BaseFeeScalar) ++ ++ blobBaseFeeScalar, err = gpoContract.BlobBaseFeeScalar(&bind.CallOpts{}) ++ require.NoError(t, err, "reading blob base fee scalar") ++ require.Equal(t, blobBaseFeeScalar, normalScalars.BlobBaseFeeScalar) ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+205
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/system/fees/l1info_test.go CELO/op-e2e/system/fees/l1info_test.go +new file mode 100644 +index 0000000000000000000000000000000000000000..2fdd3f70747a0cd54ed0e24ab4c85b3bb9b25b5c +--- /dev/null ++++ CELO/op-e2e/system/fees/l1info_test.go +@@ -0,0 +1,205 @@ ++package fees ++ ++import ( ++ "context" ++ "fmt" ++ "math/big" ++ "testing" ++ "time" ++ ++ op_e2e "github.com/ethereum-optimism/optimism/op-e2e" ++ ++ "github.com/ethereum-optimism/optimism/op-e2e/bindings" ++ "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" ++ "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" ++ "github.com/ethereum-optimism/optimism/op-node/rollup/derive" ++ "github.com/ethereum-optimism/optimism/op-service/eth" ++ "github.com/ethereum/go-ethereum/accounts/abi/bind" ++ "github.com/ethereum/go-ethereum/common" ++ "github.com/ethereum/go-ethereum/consensus/misc/eip4844" ++ "github.com/ethereum/go-ethereum/core/types" ++ "github.com/ethereum/go-ethereum/ethclient" ++ "github.com/stretchr/testify/require" ++) ++ ++func L1InfoFromState(ctx context.Context, contract *bindings.L1Block, l2Number *big.Int, ecotone bool) (*derive.L1BlockInfo, error) { ++ var err error ++ out := &derive.L1BlockInfo{} ++ opts := bind.CallOpts{ ++ BlockNumber: l2Number, ++ Context: ctx, ++ } ++ ++ out.Number, err = contract.Number(&opts) ++ if err != nil { ++ return nil, fmt.Errorf("failed to get number: %w", err) ++ } ++ ++ out.Time, err = contract.Timestamp(&opts) ++ if err != nil { ++ return nil, fmt.Errorf("failed to get timestamp: %w", err) ++ } ++ ++ out.BaseFee, err = contract.Basefee(&opts) ++ if err != nil { ++ return nil, fmt.Errorf("failed to get base fee: %w", err) ++ } ++ ++ blockHashBytes, err := contract.Hash(&opts) ++ if err != nil { ++ return nil, fmt.Errorf("failed to get block hash: %w", err) ++ } ++ out.BlockHash = common.BytesToHash(blockHashBytes[:]) ++ ++ out.SequenceNumber, err = contract.SequenceNumber(&opts) ++ if err != nil { ++ return nil, fmt.Errorf("failed to get sequence number: %w", err) ++ } ++ ++ if !ecotone { ++ overhead, err := contract.L1FeeOverhead(&opts) ++ if err != nil { ++ return nil, fmt.Errorf("failed to get l1 fee overhead: %w", err) ++ } ++ out.L1FeeOverhead = eth.Bytes32(common.BigToHash(overhead)) ++ ++ scalar, err := contract.L1FeeScalar(&opts) ++ if err != nil { ++ return nil, fmt.Errorf("failed to get l1 fee scalar: %w", err) ++ } ++ out.L1FeeScalar = eth.Bytes32(common.BigToHash(scalar)) ++ } ++ ++ batcherHash, err := contract.BatcherHash(&opts) ++ if err != nil { ++ return nil, fmt.Errorf("failed to get batch sender: %w", err) ++ } ++ out.BatcherAddr = common.BytesToAddress(batcherHash[:]) ++ ++ if ecotone { ++ blobBaseFeeScalar, err := contract.BlobBaseFeeScalar(&opts) ++ if err != nil { ++ return nil, fmt.Errorf("failed to get blob basefee scalar: %w", err) ++ } ++ out.BlobBaseFeeScalar = blobBaseFeeScalar ++ ++ baseFeeScalar, err := contract.BaseFeeScalar(&opts) ++ if err != nil { ++ return nil, fmt.Errorf("failed to get basefee scalar: %w", err) ++ } ++ out.BaseFeeScalar = baseFeeScalar ++ ++ blobBaseFee, err := contract.BlobBaseFee(&opts) ++ if err != nil { ++ return nil, fmt.Errorf("failed to get blob basefee: %w", err) ++ } ++ out.BlobBaseFee = blobBaseFee ++ } ++ ++ return out, nil ++} ++ ++func TestL1InfoContract(t *testing.T) { ++ op_e2e.InitParallel(t) ++ ++ cfg := e2esys.DefaultSystemConfig(t) ++ ++ sys, err := cfg.Start(t) ++ require.Nil(t, err, "Error starting up system") ++ ++ l1Client := sys.NodeClient("l1") ++ l2Seq := sys.NodeClient("sequencer") ++ l2Verif := sys.NodeClient("verifier") ++ ++ endVerifBlockNumber := big.NewInt(4) ++ endSeqBlockNumber := big.NewInt(6) ++ endVerifBlock, err := geth.WaitForBlock(endVerifBlockNumber, l2Verif, time.Minute) ++ require.Nil(t, err) ++ endSeqBlock, err := geth.WaitForBlock(endSeqBlockNumber, l2Seq, time.Minute) ++ require.Nil(t, err) ++ ++ seqL1Info, err := bindings.NewL1Block(cfg.L1InfoPredeployAddress, l2Seq) ++ require.Nil(t, err) ++ ++ verifL1Info, err := bindings.NewL1Block(cfg.L1InfoPredeployAddress, l2Verif) ++ require.Nil(t, err) ++ ++ ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) ++ defer cancel() ++ ++ fillInfoLists := func(start *types.Block, contract *bindings.L1Block, client *ethclient.Client) ([]*derive.L1BlockInfo, []*derive.L1BlockInfo) { ++ var txList, stateList []*derive.L1BlockInfo ++ for b := start; ; { ++ var infoFromTx *derive.L1BlockInfo ++ infoFromTx, err := derive.L1BlockInfoFromBytes(sys.RollupConfig, b.Time(), b.Transactions()[0].Data()) ++ require.NoError(t, err) ++ txList = append(txList, infoFromTx) ++ ++ ecotone := sys.RollupConfig.IsEcotone(b.Time()) && !sys.RollupConfig.IsEcotoneActivationBlock(b.Time()) ++ infoFromState, err := L1InfoFromState(ctx, contract, b.Number(), ecotone) ++ require.Nil(t, err) ++ stateList = append(stateList, infoFromState) ++ ++ // Genesis L2 block contains no L1 Deposit TX ++ if b.NumberU64() == 1 { ++ return txList, stateList ++ } ++ b, err = client.BlockByHash(ctx, b.ParentHash()) ++ require.Nil(t, err) ++ } ++ } ++ ++ l1InfosFromSequencerTransactions, l1InfosFromSequencerState := fillInfoLists(endSeqBlock, seqL1Info, l2Seq) ++ l1InfosFromVerifierTransactions, l1InfosFromVerifierState := fillInfoLists(endVerifBlock, verifL1Info, l2Verif) ++ ++ l1blocks := make(map[common.Hash]*derive.L1BlockInfo) ++ maxL1Hash := l1InfosFromSequencerTransactions[0].BlockHash ++ for h := maxL1Hash; ; { ++ b, err := l1Client.BlockByHash(ctx, h) ++ require.Nil(t, err) ++ ++ l1blocks[h] = &derive.L1BlockInfo{ ++ Number: b.NumberU64(), ++ Time: b.Time(), ++ BaseFee: b.BaseFee(), ++ BlockHash: h, ++ SequenceNumber: 0, // ignored, will be overwritten ++ BatcherAddr: sys.RollupConfig.Genesis.SystemConfig.BatcherAddr, ++ } ++ if sys.RollupConfig.IsEcotone(b.Time()) && !sys.RollupConfig.IsEcotoneActivationBlock(b.Time()) { ++ scalars, err := sys.RollupConfig.Genesis.SystemConfig.EcotoneScalars() ++ require.NoError(t, err) ++ l1blocks[h].BlobBaseFeeScalar = scalars.BlobBaseFeeScalar ++ l1blocks[h].BaseFeeScalar = scalars.BaseFeeScalar ++ if excess := b.ExcessBlobGas(); excess != nil { ++ l1blocks[h].BlobBaseFee = eip4844.CalcBlobFee(*excess) ++ } else { ++ l1blocks[h].BlobBaseFee = big.NewInt(1) ++ } ++ } else { ++ l1blocks[h].L1FeeOverhead = sys.RollupConfig.Genesis.SystemConfig.Overhead ++ l1blocks[h].L1FeeScalar = sys.RollupConfig.Genesis.SystemConfig.Scalar ++ } ++ ++ h = b.ParentHash() ++ if b.NumberU64() == 0 { ++ break ++ } ++ } ++ ++ checkInfoList := func(name string, list []*derive.L1BlockInfo) { ++ for _, info := range list { ++ if expected, ok := l1blocks[info.BlockHash]; ok { ++ expected.SequenceNumber = info.SequenceNumber // the seq nr is not part of the L1 info we know in advance, so we ignore it. ++ require.Equal(t, expected, info) ++ } else { ++ t.Fatalf("Did not find block hash for L1 Info: %v in test %s", info, name) ++ } ++ } ++ } ++ ++ checkInfoList("On sequencer with tx", l1InfosFromSequencerTransactions) ++ checkInfoList("On sequencer with state", l1InfosFromSequencerState) ++ checkInfoList("On verifier with tx", l1InfosFromVerifierTransactions) ++ checkInfoList("On verifier with state", l1InfosFromVerifierState) ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+8
+
-4
+ +
+ +
+
+
diff --git OP/op-e2e/check_scripts_test.go CELO/op-e2e/system/fjord/check_scripts_test.go +rename from op-e2e/check_scripts_test.go +rename to op-e2e/system/fjord/check_scripts_test.go +index 151d11fa0197aebe5ae2a179c7a6960aa8aa98ca..b6115dbd7e0b8ad13e4c09c5eca10601e94a893c 100644 +--- OP/op-e2e/check_scripts_test.go ++++ CELO/op-e2e/system/fjord/check_scripts_test.go +@@ -1,8 +1,12 @@ +-package op_e2e ++package fjord +  + import ( + "context" + "testing" ++ ++ op_e2e "github.com/ethereum-optimism/optimism/op-e2e" ++ ++ "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" +  + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/log" +@@ -16,7 +20,7 @@ + // TestCheckFjordScript ensures the op-chain-ops/cmd/check-fjord script runs successfully + // against a test chain with the fjord hardfork activated/unactivated + func TestCheckFjordScript(t *testing.T) { +- InitParallel(t) ++ op_e2e.InitParallel(t) + genesisActivation := hexutil.Uint64(0) + tests := []struct { + name string +@@ -37,11 +41,11 @@ } +  + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { +- InitParallel(t) ++ op_e2e.InitParallel(t) +  + log := testlog.Logger(t, log.LevelInfo) +  +- cfg := DefaultSystemConfig(t) ++ cfg := e2esys.DefaultSystemConfig(t) + cfg.DeployConfig.L1CancunTimeOffset = &genesisActivation + cfg.DeployConfig.L2GenesisRegolithTimeOffset = &genesisActivation + cfg.DeployConfig.L2GenesisCanyonTimeOffset = &genesisActivation
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+11
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/system/fjord/fjord_test.go CELO/op-e2e/system/fjord/fjord_test.go +new file mode 100644 +index 0000000000000000000000000000000000000000..09e2ca47ddd5802327b5da05d9718b7ae0db9fae +--- /dev/null ++++ CELO/op-e2e/system/fjord/fjord_test.go +@@ -0,0 +1,11 @@ ++package fjord ++ ++import ( ++ "testing" ++ ++ op_e2e "github.com/ethereum-optimism/optimism/op-e2e" ++) ++ ++func TestMain(m *testing.M) { ++ op_e2e.RunMain(m) ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+17
+
-8
+ +
+ +
+
+
diff --git OP/op-e2e/custom_gas_token_test.go CELO/op-e2e/system/gastoken/gastoken_test.go +rename from op-e2e/custom_gas_token_test.go +rename to op-e2e/system/gastoken/gastoken_test.go +index 454e73439aec222aa1c26eb58083421e3557e1ab..445f672743cfd11d7c9840d14761d2714fd2b3ac 100644 +--- OP/op-e2e/custom_gas_token_test.go ++++ CELO/op-e2e/system/gastoken/gastoken_test.go +@@ -1,4 +1,4 @@ +-package op_e2e ++package gastoken +  + import ( + "context" +@@ -6,6 +6,11 @@ "fmt" + "math/big" + "testing" + "time" ++ ++ op_e2e "github.com/ethereum-optimism/optimism/op-e2e" ++ ++ "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" ++ "github.com/ethereum-optimism/optimism/op-e2e/system/helpers" +  + "github.com/ethereum-optimism/optimism/op-e2e/bindings" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils" +@@ -22,10 +27,14 @@ "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + ) +  ++func TestMain(m *testing.M) { ++ op_e2e.RunMain(m) ++} ++ + func TestCustomGasToken(t *testing.T) { +- InitParallel(t, SkipOnFaultProofs) // Custom Gas Token feature is not yet compatible with fault proofs ++ op_e2e.InitParallel(t, op_e2e.SkipOnFaultProofs) // Custom Gas Token feature is not yet compatible with fault proofs +  +- cfg := DefaultSystemConfig(t) ++ cfg := e2esys.DefaultSystemConfig(t) + offset := hexutil.Uint64(0) + cfg.DeployConfig.L2GenesisRegolithTimeOffset = &offset + cfg.DeployConfig.L1CancunTimeOffset = &offset +@@ -143,7 +152,7 @@ startBalanceBeforeWithdrawal, err := l2Seq.BalanceAt(context.Background(), fromAddr, nil) + require.NoError(t, err) +  + withdrawAmount := big.NewInt(5) +- tx, receipt := SendWithdrawal(t, cfg, l2Seq, cfg.Secrets.Alice, func(opts *WithdrawalTxOpts) { ++ tx, receipt := helpers.SendWithdrawal(t, cfg, l2Seq, cfg.Secrets.Alice, func(opts *helpers.WithdrawalTxOpts) { + opts.Value = withdrawAmount + opts.VerifyOnClients(l2Verif) + }) +@@ -157,7 +166,7 @@ require.NoError(t, err) +  + // Take fee into account + diff := new(big.Int).Sub(startBalanceBeforeWithdrawal, endBalanceAfterWithdrawal) +- fees := calcGasFees(receipt.GasUsed, tx.GasTipCap(), tx.GasFeeCap(), header.BaseFee) ++ fees := helpers.CalcGasFees(receipt.GasUsed, tx.GasTipCap(), tx.GasFeeCap(), header.BaseFee) + fees = fees.Add(fees, receipt.L1Fee) + diff = diff.Sub(diff, fees) + require.Equal(t, withdrawAmount, diff) +@@ -169,7 +178,7 @@ + startETHBalanceBeforeFinalize, err := l1Client.BalanceAt(context.Background(), fromAddr, nil) + require.NoError(t, err) +  +- proveReceipt, finalizeReceipt, resolveClaimReceipt, resolveReceipt := ProveAndFinalizeWithdrawal(t, cfg, sys, "verifier", ethPrivKey, receipt) ++ proveReceipt, finalizeReceipt, resolveClaimReceipt, resolveReceipt := helpers.ProveAndFinalizeWithdrawal(t, cfg, sys, "verifier", ethPrivKey, receipt) +  + // Verify L1 ETH balance change + proveFee := new(big.Int).Mul(new(big.Int).SetUint64(proveReceipt.GasUsed), proveReceipt.EffectiveGasPrice) +@@ -318,7 +327,7 @@ + withdrawnAmount := it.Event.Value +  + // Finalize the withdrawal +- proveReceipt, finalizeReceipt, resolveClaimReceipt, resolveReceipt := ProveAndFinalizeWithdrawal(t, cfg, sys, "verifier", cfg.Secrets.Alice, receipt) ++ proveReceipt, finalizeReceipt, resolveClaimReceipt, resolveReceipt := helpers.ProveAndFinalizeWithdrawal(t, cfg, sys, "verifier", cfg.Secrets.Alice, receipt) + require.Equal(t, types.ReceiptStatusSuccessful, proveReceipt.Status) + require.Equal(t, types.ReceiptStatusSuccessful, finalizeReceipt.Status) + if e2eutils.UseFaultProofs() { +@@ -462,7 +471,7 @@ + // setCustomGasToeken enables the Custom Gas Token feature on a chain where it wasn't enabled at genesis. + // It reads existing parameters from the SystemConfig contract, inserts the supplied cgtAddress and reinitializes that contract. + // To do this it uses the ProxyAdmin and StorageSetter from the supplied cfg. +-func setCustomGasToken(t *testing.T, cfg SystemConfig, sys *System, cgtAddress common.Address) { ++func setCustomGasToken(t *testing.T, cfg e2esys.SystemConfig, sys *e2esys.System, cgtAddress common.Address) { + l1Client := sys.NodeClient("l1") + deployerOpts, err := bind.NewKeyedTransactorWithChainID(cfg.Secrets.Deployer, cfg.L1ChainIDBig()) + require.NoError(t, err)
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+13
+
-7
+ +
+ +
+
+
diff --git OP/op-e2e/tx_helper.go CELO/op-e2e/system/helpers/tx_helper.go +rename from op-e2e/tx_helper.go +rename to op-e2e/system/helpers/tx_helper.go +index 2a398728689cd53b32d016d02390331fab456f02..f5cb11aa8a1d25050e99b1b9c0d201f74bd5ecae 100644 +--- OP/op-e2e/tx_helper.go ++++ CELO/op-e2e/system/helpers/tx_helper.go +@@ -1,4 +1,4 @@ +-package op_e2e ++package helpers +  + import ( + "context" +@@ -6,6 +6,8 @@ "crypto/ecdsa" + "math/big" + "testing" + "time" ++ ++ "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" +  + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" +  +@@ -24,7 +26,7 @@ // The L1 transaction, including sender, is configured by the l1Opts param. + // The L2 transaction options can be configured by modifying the DepositTxOps value supplied to applyL2Opts + // Will verify that the transaction is included with the expected status on L1 and L2 + // Returns the receipt of the L2 transaction +-func SendDepositTx(t *testing.T, cfg SystemConfig, l1Client *ethclient.Client, l2Client *ethclient.Client, l1Opts *bind.TransactOpts, applyL2Opts DepositTxOptsFn) *types.Receipt { ++func SendDepositTx(t *testing.T, cfg e2esys.SystemConfig, l1Client *ethclient.Client, l2Client *ethclient.Client, l1Opts *bind.TransactOpts, applyL2Opts DepositTxOptsFn) *types.Receipt { + l2Opts := defaultDepositTxOpts(l1Opts) + applyL2Opts(l2Opts) +  +@@ -84,11 +86,11 @@ // SendL2Tx creates and sends a transaction. + // The supplied privKey is used to specify the account to send from and the transaction is sent to the supplied l2Client + // Transaction options and expected status can be configured in the applyTxOpts function by modifying the supplied TxOpts + // Will verify that the transaction is included with the expected status on l2Client and any clients added to TxOpts.VerifyClients +-func SendL2Tx(t *testing.T, cfg SystemConfig, l2Client *ethclient.Client, privKey *ecdsa.PrivateKey, applyTxOpts TxOptsFn) *types.Receipt { ++func SendL2TxWithID(t *testing.T, chainID *big.Int, l2Client *ethclient.Client, privKey *ecdsa.PrivateKey, applyTxOpts TxOptsFn) *types.Receipt { + opts := defaultTxOpts() + applyTxOpts(opts) +- tx := types.MustSignNewTx(privKey, types.LatestSignerForChainID(cfg.L2ChainIDBig()), &types.DynamicFeeTx{ +- ChainID: cfg.L2ChainIDBig(), ++ tx := types.MustSignNewTx(privKey, types.LatestSignerForChainID(chainID), &types.DynamicFeeTx{ ++ ChainID: chainID, + Nonce: opts.Nonce, // Already have deposit + To: opts.ToAddr, + Value: opts.Value, +@@ -113,6 +115,10 @@ require.NoErrorf(t, err, "Waiting for L2 tx on verification client %d", i) + require.Equalf(t, receipt, receiptVerif, "Receipts should be the same on sequencer and verification client %d", i) + } + return receipt ++} ++ ++func SendL2Tx(t *testing.T, cfg e2esys.SystemConfig, l2Client *ethclient.Client, privKey *ecdsa.PrivateKey, applyTxOpts TxOptsFn) *types.Receipt { ++ return SendL2TxWithID(t, cfg.L2ChainIDBig(), l2Client, privKey, applyTxOpts) + } +  + type TxOptsFn func(opts *TxOpts) +@@ -148,9 +154,9 @@ ExpectedStatus: types.ReceiptStatusSuccessful, + } + } +  +-// calcGasFees determines the actual cost of the transaction given a specific base fee ++// CalcGasFees determines the actual cost of the transaction given a specific base fee + // This does not include the L1 data fee charged from L2 transactions. +-func calcGasFees(gasUsed uint64, gasTipCap *big.Int, gasFeeCap *big.Int, baseFee *big.Int) *big.Int { ++func CalcGasFees(gasUsed uint64, gasTipCap *big.Int, gasFeeCap *big.Int, baseFee *big.Int) *big.Int { + x := new(big.Int).Add(gasTipCap, baseFee) + // If tip + basefee > gas fee cap, clamp it to the gas fee cap + if x.Cmp(gasFeeCap) > 0 {
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+8
+
-6
+ +
+ +
+
+
diff --git OP/op-e2e/withdrawal_helper.go CELO/op-e2e/system/helpers/withdrawal_helper.go +rename from op-e2e/withdrawal_helper.go +rename to op-e2e/system/helpers/withdrawal_helper.go +index e2d1c5a03fa9b788bc6370487fa78af04e4d0c24..b7d11a63060c63f3172886f6613796a0ebc395f7 100644 +--- OP/op-e2e/withdrawal_helper.go ++++ CELO/op-e2e/system/helpers/withdrawal_helper.go +@@ -1,4 +1,4 @@ +-package op_e2e ++package helpers +  + import ( + "context" +@@ -7,6 +7,8 @@ "errors" + "math/big" + "testing" + "time" ++ ++ "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" +  + "github.com/ethereum-optimism/optimism/op-chain-ops/crossdomain" + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts" +@@ -37,7 +39,7 @@ type ClientProvider interface { + NodeClient(name string) *ethclient.Client + } +  +-func SendWithdrawal(t *testing.T, cfg SystemConfig, l2Client *ethclient.Client, privKey *ecdsa.PrivateKey, applyOpts WithdrawalTxOptsFn) (*types.Transaction, *types.Receipt) { ++func SendWithdrawal(t *testing.T, cfg e2esys.SystemConfig, l2Client *ethclient.Client, privKey *ecdsa.PrivateKey, applyOpts WithdrawalTxOptsFn) (*types.Transaction, *types.Receipt) { + opts := defaultWithdrawalTxOpts() + applyOpts(opts) +  +@@ -94,18 +96,18 @@ ExpectedStatus: types.ReceiptStatusSuccessful, + } + } +  +-func ProveAndFinalizeWithdrawal(t *testing.T, cfg SystemConfig, clients ClientProvider, l2NodeName string, ethPrivKey *ecdsa.PrivateKey, l2WithdrawalReceipt *types.Receipt) (*types.Receipt, *types.Receipt, *types.Receipt, *types.Receipt) { ++func ProveAndFinalizeWithdrawal(t *testing.T, cfg e2esys.SystemConfig, clients ClientProvider, l2NodeName string, ethPrivKey *ecdsa.PrivateKey, l2WithdrawalReceipt *types.Receipt) (*types.Receipt, *types.Receipt, *types.Receipt, *types.Receipt) { + params, proveReceipt := ProveWithdrawal(t, cfg, clients, l2NodeName, ethPrivKey, l2WithdrawalReceipt) + finalizeReceipt, resolveClaimReceipt, resolveReceipt := FinalizeWithdrawal(t, cfg, clients.NodeClient("l1"), ethPrivKey, proveReceipt, params) + return proveReceipt, finalizeReceipt, resolveClaimReceipt, resolveReceipt + } +  +-func ProveWithdrawal(t *testing.T, cfg SystemConfig, clients ClientProvider, l2NodeName string, ethPrivKey *ecdsa.PrivateKey, l2WithdrawalReceipt *types.Receipt) (withdrawals.ProvenWithdrawalParameters, *types.Receipt) { ++func ProveWithdrawal(t *testing.T, cfg e2esys.SystemConfig, clients ClientProvider, l2NodeName string, ethPrivKey *ecdsa.PrivateKey, l2WithdrawalReceipt *types.Receipt) (withdrawals.ProvenWithdrawalParameters, *types.Receipt) { + // Get l2BlockNumber for proof generation + ctx, cancel := context.WithTimeout(context.Background(), 40*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) + defer cancel() +  +- l1Client := clients.NodeClient(RoleL1) ++ l1Client := clients.NodeClient(e2esys.RoleL1) + var blockNumber uint64 + var err error + if e2eutils.UseFaultProofs() { +@@ -176,7 +178,7 @@ return withdrawals.ProveWithdrawalParameters(ctx, proofCl, l2ReceiptCl, l2BlockCl, txHash, header, l2OutputOracleContract) + } + } +  +-func FinalizeWithdrawal(t *testing.T, cfg SystemConfig, l1Client *ethclient.Client, privKey *ecdsa.PrivateKey, withdrawalProofReceipt *types.Receipt, params withdrawals.ProvenWithdrawalParameters) (*types.Receipt, *types.Receipt, *types.Receipt) { ++func FinalizeWithdrawal(t *testing.T, cfg e2esys.SystemConfig, l1Client *ethclient.Client, privKey *ecdsa.PrivateKey, withdrawalProofReceipt *types.Receipt, params withdrawals.ProvenWithdrawalParameters) (*types.Receipt, *types.Receipt, *types.Receipt) { + // Wait for finalization and then create the Finalized Withdrawal Transaction + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) + defer cancel()
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+203
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/system/p2p/gossip_test.go CELO/op-e2e/system/p2p/gossip_test.go +new file mode 100644 +index 0000000000000000000000000000000000000000..6958bdffcf4f3163536f60b3f7f696c59066412a +--- /dev/null ++++ CELO/op-e2e/system/p2p/gossip_test.go +@@ -0,0 +1,203 @@ ++package p2p ++ ++import ( ++ "context" ++ "math/big" ++ "slices" ++ "testing" ++ "time" ++ ++ op_e2e "github.com/ethereum-optimism/optimism/op-e2e" ++ ++ "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/opnode" ++ "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" ++ "github.com/ethereum-optimism/optimism/op-e2e/system/helpers" ++ rollupNode "github.com/ethereum-optimism/optimism/op-node/node" ++ "github.com/ethereum-optimism/optimism/op-node/p2p" ++ "github.com/ethereum-optimism/optimism/op-node/rollup/driver" ++ "github.com/ethereum-optimism/optimism/op-service/eth" ++ "github.com/ethereum-optimism/optimism/op-service/retry" ++ "github.com/ethereum-optimism/optimism/op-service/testlog" ++ "github.com/ethereum/go-ethereum/common" ++ "github.com/ethereum/go-ethereum/log" ++ "github.com/libp2p/go-libp2p/core/peer" ++ "github.com/stretchr/testify/require" ++) ++ ++// TestSystemMockP2P sets up a L1 Geth node, a rollup node, and a L2 geth node and then confirms that ++// the nodes can sync L2 blocks before they are confirmed on L1. ++func TestSystemMockP2P(t *testing.T) { ++ op_e2e.InitParallel(t) ++ ++ cfg := e2esys.DefaultSystemConfig(t) ++ // Disable batcher, so we don't sync from L1 & set a large sequence window so we only have unsafe blocks ++ cfg.DisableBatcher = true ++ cfg.DeployConfig.SequencerWindowSize = 100_000 ++ cfg.DeployConfig.MaxSequencerDrift = 100_000 ++ // disable at the start, so we don't miss any gossiped blocks. ++ cfg.Nodes["sequencer"].Driver.SequencerStopped = true ++ ++ // connect the nodes ++ cfg.P2PTopology = map[string][]string{ ++ "verifier": {"sequencer"}, ++ } ++ ++ var published, received []common.Hash ++ seqTracer, verifTracer := new(opnode.FnTracer), new(opnode.FnTracer) ++ seqTracer.OnPublishL2PayloadFn = func(ctx context.Context, payload *eth.ExecutionPayloadEnvelope) { ++ published = append(published, payload.ExecutionPayload.BlockHash) ++ } ++ verifTracer.OnUnsafeL2PayloadFn = func(ctx context.Context, from peer.ID, payload *eth.ExecutionPayloadEnvelope) { ++ received = append(received, payload.ExecutionPayload.BlockHash) ++ } ++ cfg.Nodes["sequencer"].Tracer = seqTracer ++ cfg.Nodes["verifier"].Tracer = verifTracer ++ ++ sys, err := cfg.Start(t) ++ require.Nil(t, err, "Error starting up system") ++ ++ // Enable the sequencer now that everyone is ready to receive payloads. ++ rollupClient := sys.RollupClient("sequencer") ++ ++ verifierPeerID := sys.RollupNodes["verifier"].P2P().Host().ID() ++ check := func() bool { ++ sequencerBlocksTopicPeers := sys.RollupNodes["sequencer"].P2P().GossipOut().AllBlockTopicsPeers() ++ return slices.Contains[[]peer.ID](sequencerBlocksTopicPeers, verifierPeerID) ++ } ++ ++ // poll to see if the verifier node is connected & meshed on gossip. ++ // Without this verifier, we shouldn't start sending blocks around, or we'll miss them and fail the test. ++ backOffStrategy := retry.Exponential() ++ for i := 0; i < 10; i++ { ++ if check() { ++ break ++ } ++ time.Sleep(backOffStrategy.Duration(i)) ++ } ++ require.True(t, check(), "verifier must be meshed with sequencer for gossip test to proceed") ++ ++ require.NoError(t, rollupClient.StartSequencer(context.Background(), sys.L2GenesisCfg.ToBlock().Hash())) ++ ++ l2Seq := sys.NodeClient("sequencer") ++ l2Verif := sys.NodeClient("verifier") ++ ++ // Transactor Account ++ ethPrivKey := cfg.Secrets.Alice ++ ++ // Submit TX to L2 sequencer node ++ receiptSeq := helpers.SendL2Tx(t, cfg, l2Seq, ethPrivKey, func(opts *helpers.TxOpts) { ++ opts.ToAddr = &common.Address{0xff, 0xff} ++ opts.Value = big.NewInt(1_000_000_000) ++ ++ // Wait until the block it was first included in shows up in the safe chain on the verifier ++ opts.VerifyOnClients(l2Verif) ++ }) ++ ++ // Verify that everything that was received was published ++ require.GreaterOrEqual(t, len(published), len(received)) ++ require.Subset(t, published, received) ++ ++ // Verify that the tx was received via p2p ++ require.Contains(t, received, receiptSeq.BlockHash) ++} ++ ++// TestSystemDenseTopology sets up a dense p2p topology with 3 verifier nodes and 1 sequencer node. ++func TestSystemDenseTopology(t *testing.T) { ++ t.Skip("Skipping dense topology test to avoid flakiness. @refcell address in p2p scoring pr.") ++ ++ op_e2e.InitParallel(t) ++ ++ cfg := e2esys.DefaultSystemConfig(t) ++ // slow down L1 blocks so we can see the L2 blocks arrive well before the L1 blocks do. ++ // Keep the seq window small so the L2 chain is started quick ++ cfg.DeployConfig.L1BlockTime = 10 ++ ++ // Append additional nodes to the system to construct a dense p2p network ++ cfg.Nodes["verifier2"] = &rollupNode.Config{ ++ Driver: driver.Config{ ++ VerifierConfDepth: 0, ++ SequencerConfDepth: 0, ++ SequencerEnabled: false, ++ }, ++ L1EpochPollInterval: time.Second * 4, ++ } ++ cfg.Nodes["verifier3"] = &rollupNode.Config{ ++ Driver: driver.Config{ ++ VerifierConfDepth: 0, ++ SequencerConfDepth: 0, ++ SequencerEnabled: false, ++ }, ++ L1EpochPollInterval: time.Second * 4, ++ } ++ cfg.Loggers["verifier2"] = testlog.Logger(t, log.LevelInfo).New("role", "verifier") ++ cfg.Loggers["verifier3"] = testlog.Logger(t, log.LevelInfo).New("role", "verifier") ++ ++ // connect the nodes ++ cfg.P2PTopology = map[string][]string{ ++ "verifier": {"sequencer", "verifier2", "verifier3"}, ++ "verifier2": {"sequencer", "verifier", "verifier3"}, ++ "verifier3": {"sequencer", "verifier", "verifier2"}, ++ } ++ ++ // Set peer scoring for each node, but without banning ++ for _, node := range cfg.Nodes { ++ params, err := p2p.GetScoringParams("light", &node.Rollup) ++ require.NoError(t, err) ++ node.P2P = &p2p.Config{ ++ ScoringParams: params, ++ BanningEnabled: false, ++ } ++ } ++ ++ var published, received1, received2, received3 []common.Hash ++ seqTracer, verifTracer, verifTracer2, verifTracer3 := new(opnode.FnTracer), new(opnode.FnTracer), new(opnode.FnTracer), new(opnode.FnTracer) ++ seqTracer.OnPublishL2PayloadFn = func(ctx context.Context, payload *eth.ExecutionPayloadEnvelope) { ++ published = append(published, payload.ExecutionPayload.BlockHash) ++ } ++ verifTracer.OnUnsafeL2PayloadFn = func(ctx context.Context, from peer.ID, payload *eth.ExecutionPayloadEnvelope) { ++ received1 = append(received1, payload.ExecutionPayload.BlockHash) ++ } ++ verifTracer2.OnUnsafeL2PayloadFn = func(ctx context.Context, from peer.ID, payload *eth.ExecutionPayloadEnvelope) { ++ received2 = append(received2, payload.ExecutionPayload.BlockHash) ++ } ++ verifTracer3.OnUnsafeL2PayloadFn = func(ctx context.Context, from peer.ID, payload *eth.ExecutionPayloadEnvelope) { ++ received3 = append(received3, payload.ExecutionPayload.BlockHash) ++ } ++ cfg.Nodes["sequencer"].Tracer = seqTracer ++ cfg.Nodes["verifier"].Tracer = verifTracer ++ cfg.Nodes["verifier2"].Tracer = verifTracer2 ++ cfg.Nodes["verifier3"].Tracer = verifTracer3 ++ ++ sys, err := cfg.Start(t) ++ require.Nil(t, err, "Error starting up system") ++ ++ l2Seq := sys.NodeClient("sequencer") ++ l2Verif := sys.NodeClient("verifier") ++ l2Verif2 := sys.NodeClient("verifier2") ++ l2Verif3 := sys.NodeClient("verifier3") ++ ++ // Transactor Account ++ ethPrivKey := cfg.Secrets.Alice ++ ++ // Submit TX to L2 sequencer node ++ receiptSeq := helpers.SendL2Tx(t, cfg, l2Seq, ethPrivKey, func(opts *helpers.TxOpts) { ++ opts.ToAddr = &common.Address{0xff, 0xff} ++ opts.Value = big.NewInt(1_000_000_000) ++ ++ // Wait until the block it was first included in shows up in the safe chain on the verifiers ++ opts.VerifyOnClients(l2Verif, l2Verif2, l2Verif3) ++ }) ++ ++ // Verify that everything that was received was published ++ require.GreaterOrEqual(t, len(published), len(received1)) ++ require.GreaterOrEqual(t, len(published), len(received2)) ++ require.GreaterOrEqual(t, len(published), len(received3)) ++ require.ElementsMatch(t, published, received1[:len(published)]) ++ require.ElementsMatch(t, published, received2[:len(published)]) ++ require.ElementsMatch(t, published, received3[:len(published)]) ++ ++ // Verify that the tx was received via p2p ++ require.Contains(t, received1, receiptSeq.BlockHash) ++ require.Contains(t, received2, receiptSeq.BlockHash) ++ require.Contains(t, received3, receiptSeq.BlockHash) ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+11
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/system/p2p/p2p_test.go CELO/op-e2e/system/p2p/p2p_test.go +new file mode 100644 +index 0000000000000000000000000000000000000000..e7aa7b0b9b736c87c7be39748d00b0e2fd0f731d +--- /dev/null ++++ CELO/op-e2e/system/p2p/p2p_test.go +@@ -0,0 +1,11 @@ ++package p2p ++ ++import ( ++ "testing" ++ ++ op_e2e "github.com/ethereum-optimism/optimism/op-e2e" ++) ++ ++func TestMain(m *testing.M) { ++ op_e2e.RunMain(m) ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+168
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/system/p2p/reqresp_test.go CELO/op-e2e/system/p2p/reqresp_test.go +new file mode 100644 +index 0000000000000000000000000000000000000000..d3245d8fd257c2f8d845f2e15917a853ec234210 +--- /dev/null ++++ CELO/op-e2e/system/p2p/reqresp_test.go +@@ -0,0 +1,168 @@ ++package p2p ++ ++import ( ++ "context" ++ "math/big" ++ "testing" ++ "time" ++ ++ op_e2e "github.com/ethereum-optimism/optimism/op-e2e" ++ ++ "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" ++ "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/opnode" ++ "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" ++ "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" ++ "github.com/ethereum-optimism/optimism/op-e2e/system/helpers" ++ "github.com/ethereum-optimism/optimism/op-node/metrics" ++ rollupNode "github.com/ethereum-optimism/optimism/op-node/node" ++ "github.com/ethereum-optimism/optimism/op-node/p2p" ++ "github.com/ethereum-optimism/optimism/op-node/rollup/driver" ++ "github.com/ethereum-optimism/optimism/op-service/endpoint" ++ "github.com/ethereum-optimism/optimism/op-service/eth" ++ "github.com/ethereum-optimism/optimism/op-service/oppprof" ++ "github.com/ethereum-optimism/optimism/op-service/testlog" ++ "github.com/ethereum/go-ethereum/common" ++ "github.com/ethereum/go-ethereum/ethclient" ++ "github.com/ethereum/go-ethereum/log" ++ "github.com/libp2p/go-libp2p/core/peer" ++ "github.com/stretchr/testify/require" ++) ++ ++func TestSystemP2PAltSync(t *testing.T) { ++ ctx, cancel := context.WithCancel(context.Background()) ++ defer cancel() ++ ++ op_e2e.InitParallel(t) ++ ++ cfg := e2esys.DefaultSystemConfig(t) ++ ++ // remove default verifier node ++ delete(cfg.Nodes, "verifier") ++ // Add more verifier nodes ++ cfg.Nodes["alice"] = &rollupNode.Config{ ++ Driver: driver.Config{ ++ VerifierConfDepth: 0, ++ SequencerConfDepth: 0, ++ SequencerEnabled: false, ++ }, ++ L1EpochPollInterval: time.Second * 4, ++ } ++ cfg.Nodes["bob"] = &rollupNode.Config{ ++ Driver: driver.Config{ ++ VerifierConfDepth: 0, ++ SequencerConfDepth: 0, ++ SequencerEnabled: false, ++ }, ++ L1EpochPollInterval: time.Second * 4, ++ } ++ cfg.Loggers["alice"] = testlog.Logger(t, log.LevelInfo).New("role", "alice") ++ cfg.Loggers["bob"] = testlog.Logger(t, log.LevelInfo).New("role", "bob") ++ ++ // connect the nodes ++ cfg.P2PTopology = map[string][]string{ ++ "sequencer": {"alice", "bob"}, ++ "alice": {"sequencer", "bob"}, ++ "bob": {"alice", "sequencer"}, ++ } ++ // Enable the P2P req-resp based sync ++ cfg.P2PReqRespSync = true ++ ++ // Disable batcher, so there will not be any L1 data to sync from ++ cfg.DisableBatcher = true ++ ++ var published []string ++ seqTracer := new(opnode.FnTracer) ++ // The sequencer still publishes the blocks to the tracer, even if they do not reach the network due to disabled P2P ++ seqTracer.OnPublishL2PayloadFn = func(ctx context.Context, payload *eth.ExecutionPayloadEnvelope) { ++ published = append(published, payload.ExecutionPayload.ID().String()) ++ } ++ // Blocks are now received via the RPC based alt-sync method ++ cfg.Nodes["sequencer"].Tracer = seqTracer ++ ++ sys, err := cfg.Start(t) ++ require.Nil(t, err, "Error starting up system") ++ ++ l2Seq := sys.NodeClient("sequencer") ++ ++ // Transactor Account ++ ethPrivKey := cfg.Secrets.Alice ++ ++ // Submit a TX to L2 sequencer node ++ receiptSeq := helpers.SendL2Tx(t, cfg, l2Seq, ethPrivKey, func(opts *helpers.TxOpts) { ++ opts.ToAddr = &common.Address{0xff, 0xff} ++ opts.Value = big.NewInt(1_000_000_000) ++ }) ++ ++ // Gossip is able to respond to IWANT messages for the duration of heartbeat_time * message_window = 0.5 * 12 = 6 ++ // Wait till we pass that, and then we'll have missed some blocks that cannot be retrieved in any way from gossip ++ time.Sleep(time.Second * 10) ++ ++ // set up our syncer node, connect it to alice/bob ++ cfg.Loggers["syncer"] = testlog.Logger(t, log.LevelInfo).New("role", "syncer") ++ ++ // Create a peer, and hook up alice and bob ++ h, err := sys.NewMockNetPeer() ++ require.NoError(t, err) ++ _, err = sys.Mocknet.LinkPeers(sys.RollupNodes["alice"].P2P().Host().ID(), h.ID()) ++ require.NoError(t, err) ++ _, err = sys.Mocknet.LinkPeers(sys.RollupNodes["bob"].P2P().Host().ID(), h.ID()) ++ require.NoError(t, err) ++ ++ // Configure the new rollup node that'll be syncing ++ var syncedPayloads []string ++ syncNodeCfg := &rollupNode.Config{ ++ Driver: driver.Config{VerifierConfDepth: 0}, ++ Rollup: *sys.RollupConfig, ++ P2PSigner: nil, ++ RPC: rollupNode.RPCConfig{ ++ ListenAddr: "127.0.0.1", ++ ListenPort: 0, ++ EnableAdmin: true, ++ }, ++ P2P: &p2p.Prepared{HostP2P: h, EnableReqRespSync: true}, ++ Metrics: rollupNode.MetricsConfig{Enabled: false}, // no metrics server ++ Pprof: oppprof.CLIConfig{}, ++ L1EpochPollInterval: time.Second * 10, ++ Tracer: &opnode.FnTracer{ ++ OnUnsafeL2PayloadFn: func(ctx context.Context, from peer.ID, payload *eth.ExecutionPayloadEnvelope) { ++ syncedPayloads = append(syncedPayloads, payload.ExecutionPayload.ID().String()) ++ }, ++ }, ++ } ++ e2esys.ConfigureL1(syncNodeCfg, sys.EthInstances["l1"], sys.L1BeaconEndpoint()) ++ syncerL2Engine, err := geth.InitL2("syncer", sys.L2GenesisCfg, cfg.JWTFilePath) ++ require.NoError(t, err) ++ require.NoError(t, syncerL2Engine.Node.Start()) ++ ++ e2esys.ConfigureL2(syncNodeCfg, syncerL2Engine, cfg.JWTSecret) ++ ++ syncerNode, err := rollupNode.New(ctx, syncNodeCfg, cfg.Loggers["syncer"], "", metrics.NewMetrics("")) ++ require.NoError(t, err) ++ err = syncerNode.Start(ctx) ++ require.NoError(t, err) ++ defer func() { ++ require.NoError(t, syncerNode.Stop(ctx)) ++ }() ++ ++ // connect alice and bob to our new syncer node ++ _, err = sys.Mocknet.ConnectPeers(sys.RollupNodes["alice"].P2P().Host().ID(), syncerNode.P2P().Host().ID()) ++ require.NoError(t, err) ++ _, err = sys.Mocknet.ConnectPeers(sys.RollupNodes["bob"].P2P().Host().ID(), syncerNode.P2P().Host().ID()) ++ require.NoError(t, err) ++ ++ rpc := syncerL2Engine.UserRPC().(endpoint.ClientRPC).ClientRPC() ++ l2Verif := ethclient.NewClient(rpc) ++ ++ // It may take a while to sync, but eventually we should see the sequenced data show up ++ receiptVerif, err := wait.ForReceiptOK(ctx, l2Verif, receiptSeq.TxHash) ++ require.Nil(t, err, "Waiting for L2 tx on verifier") ++ ++ require.Equal(t, receiptSeq, receiptVerif) ++ ++ // Verify that the tx was received via P2P sync ++ require.Contains(t, syncedPayloads, eth.BlockID{Hash: receiptVerif.BlockHash, Number: receiptVerif.BlockNumber.Uint64()}.String()) ++ ++ // Verify that everything that was received was published ++ require.GreaterOrEqual(t, len(published), len(syncedPayloads)) ++ require.Subset(t, published, syncedPayloads) ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+9
+
-4
+ +
+ +
+
+
diff --git OP/op-e2e/l2_gossip_test.go CELO/op-e2e/system/p2p/txpool_test.go +rename from op-e2e/l2_gossip_test.go +rename to op-e2e/system/p2p/txpool_test.go +index 401b30af31741701191903a269c361b04d90fdde..dde89ecdefb1184642726e955a4955bc2fb63b3c 100644 +--- OP/op-e2e/l2_gossip_test.go ++++ CELO/op-e2e/system/p2p/txpool_test.go +@@ -1,9 +1,14 @@ +-package op_e2e ++package p2p +  + import ( + "math/big" + "testing" + "time" ++ ++ op_e2e "github.com/ethereum-optimism/optimism/op-e2e" ++ ++ "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" ++ "github.com/ethereum-optimism/optimism/op-e2e/system/helpers" +  + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" + "github.com/ethereum/go-ethereum/common" +@@ -11,8 +16,8 @@ "github.com/stretchr/testify/require" + ) +  + func TestTxGossip(t *testing.T) { +- InitParallel(t) +- cfg := DefaultSystemConfig(t) ++ op_e2e.InitParallel(t) ++ cfg := e2esys.DefaultSystemConfig(t) + gethOpts := []geth.GethOption{ + geth.WithP2P(), + } +@@ -30,7 +35,7 @@ _, err = geth.WaitForBlock(big.NewInt(10), verifClient, time.Minute) + require.NoError(t, err) +  + // Send a transaction to the verifier and it should be gossiped to the sequencer and included in a block. +- SendL2Tx(t, cfg, verifClient, cfg.Secrets.Alice, func(opts *TxOpts) { ++ helpers.SendL2Tx(t, cfg, verifClient, cfg.Secrets.Alice, func(opts *helpers.TxOpts) { + opts.ToAddr = &common.Address{0xaa} + opts.Value = common.Big1 + opts.VerifyOnClients(seqClient, verifClient)
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+3
+
-3
+ +
+ +
+
+
diff --git OP/op-e2e/build_helper.go CELO/op-e2e/system/proofs/build_helper.go +rename from op-e2e/build_helper.go +rename to op-e2e/system/proofs/build_helper.go +index b84240135c68d8df3c42709dda0164533639bcda..42201279867b0f97530286dab516aee68b0700a5 100644 +--- OP/op-e2e/build_helper.go ++++ CELO/op-e2e/system/proofs/build_helper.go +@@ -1,4 +1,4 @@ +-package op_e2e ++package proofs +  + import ( + "context" +@@ -16,11 +16,11 @@ t.Log("Building op-program-client") + ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) + defer cancel() + cmd := exec.CommandContext(ctx, "make", "op-program-client") +- cmd.Dir = "../op-program" ++ cmd.Dir = "../../../op-program" + var out strings.Builder + cmd.Stdout = &out + cmd.Stderr = &out + require.NoErrorf(t, cmd.Run(), "Failed to build op-program-client: %v", &out) + t.Log("Built op-program-client successfully") +- return "../op-program/bin/op-program-client" ++ return "../../../op-program/bin/op-program-client" + }
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+11
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/system/proofs/proofs_test.go CELO/op-e2e/system/proofs/proofs_test.go +new file mode 100644 +index 0000000000000000000000000000000000000000..6fff52bd465f95524d616d85b74c87e47c435e87 +--- /dev/null ++++ CELO/op-e2e/system/proofs/proofs_test.go +@@ -0,0 +1,11 @@ ++package proofs ++ ++import ( ++ "testing" ++ ++ op_e2e "github.com/ethereum-optimism/optimism/op-e2e" ++) ++ ++func TestMain(m *testing.M) { ++ op_e2e.RunMain(m) ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+77
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/system/proofs/proposer_fp_test.go CELO/op-e2e/system/proofs/proposer_fp_test.go +new file mode 100644 +index 0000000000000000000000000000000000000000..4916d9d521a0c65d3327b38100659f07154c9bf9 +--- /dev/null ++++ CELO/op-e2e/system/proofs/proposer_fp_test.go +@@ -0,0 +1,77 @@ ++package proofs ++ ++import ( ++ "context" ++ "math/big" ++ "testing" ++ "time" ++ ++ op_e2e "github.com/ethereum-optimism/optimism/op-e2e" ++ ++ "github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts" ++ "github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts/metrics" ++ "github.com/ethereum-optimism/optimism/op-e2e/bindings" ++ "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" ++ "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" ++ "github.com/ethereum-optimism/optimism/op-service/sources/batching" ++ "github.com/ethereum/go-ethereum/accounts/abi/bind" ++ "github.com/ethereum/go-ethereum/common" ++ "github.com/stretchr/testify/require" ++) ++ ++func TestL2OutputSubmitterFaultProofs(t *testing.T) { ++ op_e2e.InitParallel(t, op_e2e.SkipOnL2OO) ++ ++ cfg := e2esys.DefaultSystemConfig(t) ++ cfg.NonFinalizedProposals = true // speed up the time till we see output proposals ++ ++ sys, err := cfg.Start(t) ++ require.Nil(t, err, "Error starting up system") ++ ++ l1Client := sys.NodeClient("l1") ++ ++ rollupClient := sys.RollupClient("sequencer") ++ ++ disputeGameFactory, err := bindings.NewDisputeGameFactoryCaller(cfg.L1Deployments.DisputeGameFactoryProxy, l1Client) ++ require.Nil(t, err) ++ ++ initialGameCount, err := disputeGameFactory.GameCount(&bind.CallOpts{}) ++ require.Nil(t, err) ++ ++ l2Verif := sys.NodeClient("verifier") ++ _, err = geth.WaitForBlock(big.NewInt(6), l2Verif, 10*time.Duration(cfg.DeployConfig.L2BlockTime)*time.Second) ++ require.Nil(t, err) ++ ++ timeoutCh := time.After(15 * time.Second) ++ ticker := time.NewTicker(1 * time.Second) ++ defer ticker.Stop() ++ for { ++ latestGameCount, err := disputeGameFactory.GameCount(&bind.CallOpts{}) ++ require.Nil(t, err) ++ ++ if latestGameCount.Cmp(initialGameCount) > 0 { ++ caller := batching.NewMultiCaller(l1Client.Client(), batching.DefaultBatchSize) ++ committedL2Output, err := disputeGameFactory.GameAtIndex(&bind.CallOpts{}, new(big.Int).Sub(latestGameCount, common.Big1)) ++ require.Nil(t, err) ++ proxy, err := contracts.NewFaultDisputeGameContract(context.Background(), metrics.NoopContractMetrics, committedL2Output.Proxy, caller) ++ require.Nil(t, err) ++ claim, err := proxy.GetClaim(context.Background(), 0) ++ require.Nil(t, err) ++ ++ ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) ++ defer cancel() ++ _, gameBlockNumber, err := proxy.GetBlockRange(ctx) ++ require.Nil(t, err) ++ l2Output, err := rollupClient.OutputAtBlock(ctx, gameBlockNumber) ++ require.Nil(t, err) ++ require.EqualValues(t, l2Output.OutputRoot, claim.Value) ++ break ++ } ++ ++ select { ++ case <-timeoutCh: ++ t.Fatalf("State root oracle not updated") ++ case <-ticker.C: ++ } ++ } ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+82
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/system/proofs/proposer_l2oo_test.go CELO/op-e2e/system/proofs/proposer_l2oo_test.go +new file mode 100644 +index 0000000000000000000000000000000000000000..3b737e0971b5987b2af164899cbdd19bf0e8930f +--- /dev/null ++++ CELO/op-e2e/system/proofs/proposer_l2oo_test.go +@@ -0,0 +1,82 @@ ++package proofs ++ ++import ( ++ "context" ++ "math/big" ++ "testing" ++ "time" ++ ++ op_e2e "github.com/ethereum-optimism/optimism/op-e2e" ++ ++ "github.com/ethereum-optimism/optimism/op-e2e/bindings" ++ "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" ++ "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" ++ "github.com/ethereum/go-ethereum/accounts/abi/bind" ++ "github.com/stretchr/testify/require" ++) ++ ++func TestL2OutputSubmitter(t *testing.T) { ++ op_e2e.InitParallel(t, op_e2e.SkipOnFaultProofs) ++ ++ cfg := e2esys.DefaultSystemConfig(t) ++ cfg.NonFinalizedProposals = true // speed up the time till we see output proposals ++ ++ sys, err := cfg.Start(t) ++ require.Nil(t, err, "Error starting up system") ++ ++ l1Client := sys.NodeClient("l1") ++ ++ rollupClient := sys.RollupClient("sequencer") ++ ++ // OutputOracle is already deployed ++ l2OutputOracle, err := bindings.NewL2OutputOracleCaller(cfg.L1Deployments.L2OutputOracleProxy, l1Client) ++ require.Nil(t, err) ++ ++ initialOutputBlockNumber, err := l2OutputOracle.LatestBlockNumber(&bind.CallOpts{}) ++ require.Nil(t, err) ++ ++ // Wait until the second output submission from L2. The output submitter submits outputs from the ++ // unsafe portion of the chain which gets reorged on startup. The sequencer has an out of date view ++ // when it creates it's first block and uses and old L1 Origin. It then does not submit a batch ++ // for that block and subsequently reorgs to match what the verifier derives when running the ++ // reconcillation process. ++ l2Verif := sys.NodeClient("verifier") ++ _, err = geth.WaitForBlock(big.NewInt(6), l2Verif, 10*time.Duration(cfg.DeployConfig.L2BlockTime)*time.Second) ++ require.Nil(t, err) ++ ++ // Wait for batch submitter to update L2 output oracle. ++ timeoutCh := time.After(15 * time.Second) ++ ticker := time.NewTicker(1 * time.Second) ++ defer ticker.Stop() ++ for { ++ l2ooBlockNumber, err := l2OutputOracle.LatestBlockNumber(&bind.CallOpts{}) ++ require.Nil(t, err) ++ ++ // Wait for the L2 output oracle to have been changed from the initial ++ // timestamp set in the contract constructor. ++ if l2ooBlockNumber.Cmp(initialOutputBlockNumber) > 0 { ++ // Retrieve the l2 output committed at this updated timestamp. ++ committedL2Output, err := l2OutputOracle.GetL2OutputAfter(&bind.CallOpts{}, l2ooBlockNumber) ++ require.NotEqual(t, [32]byte{}, committedL2Output.OutputRoot, "Empty L2 Output") ++ require.Nil(t, err) ++ ++ // Fetch the corresponding L2 block and assert the committed L2 ++ // output matches the block's state root. ++ // ++ // NOTE: This assertion will change once the L2 output format is ++ // finalized. ++ ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) ++ defer cancel() ++ l2Output, err := rollupClient.OutputAtBlock(ctx, l2ooBlockNumber.Uint64()) ++ require.Nil(t, err) ++ require.Equal(t, l2Output.OutputRoot[:], committedL2Output.OutputRoot[:]) ++ break ++ } ++ ++ select { ++ case <-timeoutCh: ++ t.Fatalf("State root oracle not updated") ++ case <-ticker.C: ++ } ++ } ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+20
+
-14
+ +
+ +
+
+
diff --git OP/op-e2e/system_fpp_test.go CELO/op-e2e/system/proofs/system_fpp_test.go +rename from op-e2e/system_fpp_test.go +rename to op-e2e/system/proofs/system_fpp_test.go +index c3598880b0cfe66b87963147a40dc032b246d645..8729f2c7055c2b0bec90c8a3528c999771e5ad36 100644 +--- OP/op-e2e/system_fpp_test.go ++++ CELO/op-e2e/system/proofs/system_fpp_test.go +@@ -1,10 +1,15 @@ +-package op_e2e ++package proofs +  + import ( + "context" + "math/big" + "testing" + "time" ++ ++ op_e2e "github.com/ethereum-optimism/optimism/op-e2e" ++ ++ "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" ++ "github.com/ethereum-optimism/optimism/op-e2e/system/helpers" +  + "github.com/stretchr/testify/require" +  +@@ -86,10 +91,10 @@ // - reboot the batch submitter + // - update the state root via a tx + // - run program + func testVerifyL2OutputRootEmptyBlock(t *testing.T, detached bool, spanBatchActivated bool) { +- InitParallel(t) ++ op_e2e.InitParallel(t) + ctx := context.Background() +  +- cfg := DefaultSystemConfig(t) ++ cfg := e2esys.DefaultSystemConfig(t) + // We don't need a verifier - just the sequencer is enough + delete(cfg.Nodes, "verifier") + // Use a small sequencer window size to avoid test timeout while waiting for empty blocks +@@ -117,7 +122,7 @@ require.NoError(t, wait.ForSafeBlock(ctx, rollupClient, ss.NumberU64()+cfg.DeployConfig.SequencerWindowSize+1)) +  + t.Log("Sending transactions to setup existing state, prior to challenged period") + aliceKey := cfg.Secrets.Alice +- receipt := SendL2Tx(t, cfg, l2Seq, aliceKey, func(opts *TxOpts) { ++ receipt := helpers.SendL2Tx(t, cfg, l2Seq, aliceKey, func(opts *helpers.TxOpts) { + opts.ToAddr = &cfg.Secrets.Addresses().Bob + opts.Value = big.NewInt(1_000) + }) +@@ -163,7 +168,7 @@ err = driver.StartBatchSubmitting() + require.NoError(t, err, "could not start batch submitter") +  + t.Log("Add a transaction to the next batch after sequence of empty blocks") +- receipt = SendL2Tx(t, cfg, l2Seq, aliceKey, func(opts *TxOpts) { ++ receipt = helpers.SendL2Tx(t, cfg, l2Seq, aliceKey, func(opts *helpers.TxOpts) { + opts.ToAddr = &cfg.Secrets.Addresses().Bob + opts.Value = big.NewInt(1_000) + opts.Nonce = 1 +@@ -186,10 +191,10 @@ }) + } +  + func testVerifyL2OutputRoot(t *testing.T, detached bool, spanBatchActivated bool) { +- InitParallel(t) ++ op_e2e.InitParallel(t) + ctx := context.Background() +  +- cfg := DefaultSystemConfig(t) ++ cfg := e2esys.DefaultSystemConfig(t) + // We don't need a verifier - just the sequencer is enough + delete(cfg.Nodes, "verifier") + applySpanBatchActivation(spanBatchActivated, cfg.DeployConfig) +@@ -209,15 +214,15 @@ t.Log("Sending transactions to setup existing state, prior to challenged period") + aliceKey := cfg.Secrets.Alice + opts, err := bind.NewKeyedTransactorWithChainID(aliceKey, cfg.L1ChainIDBig()) + require.Nil(t, err) +- SendDepositTx(t, cfg, l1Client, l2Seq, opts, func(l2Opts *DepositTxOpts) { ++ helpers.SendDepositTx(t, cfg, l1Client, l2Seq, opts, func(l2Opts *helpers.DepositTxOpts) { + l2Opts.Value = big.NewInt(100_000_000) + }) +- SendL2Tx(t, cfg, l2Seq, aliceKey, func(opts *TxOpts) { ++ helpers.SendL2Tx(t, cfg, l2Seq, aliceKey, func(opts *helpers.TxOpts) { + opts.ToAddr = &cfg.Secrets.Addresses().Bob + opts.Value = big.NewInt(1_000) + opts.Nonce = 1 + }) +- SendWithdrawal(t, cfg, l2Seq, aliceKey, func(opts *WithdrawalTxOpts) { ++ helpers.SendWithdrawal(t, cfg, l2Seq, aliceKey, func(opts *helpers.WithdrawalTxOpts) { + opts.Value = big.NewInt(500) + opts.Nonce = 2 + }) +@@ -231,14 +236,14 @@ l2Head := agreedL2Output.BlockRef.Hash + l2OutputRoot := agreedL2Output.OutputRoot +  + t.Log("Sending transactions to modify existing state, within challenged period") +- SendDepositTx(t, cfg, l1Client, l2Seq, opts, func(l2Opts *DepositTxOpts) { ++ helpers.SendDepositTx(t, cfg, l1Client, l2Seq, opts, func(l2Opts *helpers.DepositTxOpts) { + l2Opts.Value = big.NewInt(5_000) + }) +- SendL2Tx(t, cfg, l2Seq, cfg.Secrets.Bob, func(opts *TxOpts) { ++ helpers.SendL2Tx(t, cfg, l2Seq, cfg.Secrets.Bob, func(opts *helpers.TxOpts) { + opts.ToAddr = &cfg.Secrets.Addresses().Alice + opts.Value = big.NewInt(100) + }) +- SendWithdrawal(t, cfg, l2Seq, aliceKey, func(opts *WithdrawalTxOpts) { ++ helpers.SendWithdrawal(t, cfg, l2Seq, aliceKey, func(opts *helpers.WithdrawalTxOpts) { + opts.Value = big.NewInt(100) + opts.Nonce = 4 + }) +@@ -276,11 +281,12 @@ Detached bool + } +  + // testFaultProofProgramScenario runs the fault proof program in several contexts, given a test scenario. +-func testFaultProofProgramScenario(t *testing.T, ctx context.Context, sys *System, s *FaultProofProgramTestScenario) { ++func testFaultProofProgramScenario(t *testing.T, ctx context.Context, sys *e2esys.System, s *FaultProofProgramTestScenario) { + preimageDir := t.TempDir() + fppConfig := oppconf.NewConfig(sys.RollupConfig, sys.L2GenesisCfg.Config, s.L1Head, s.L2Head, s.L2OutputRoot, common.Hash(s.L2Claim), s.L2ClaimBlockNumber) + fppConfig.L1URL = sys.NodeEndpoint("l1").RPC() + fppConfig.L2URL = sys.NodeEndpoint("sequencer").RPC() ++ fppConfig.L1BeaconURL = sys.L1BeaconEndpoint().RestHTTP() + fppConfig.DataDir = preimageDir + if s.Detached { + // When running in detached mode we need to compile the client executable since it will be called directly.
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+62
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/system/runcfg/p2p_signer_test.go CELO/op-e2e/system/runcfg/p2p_signer_test.go +new file mode 100644 +index 0000000000000000000000000000000000000000..91ebfb941319c04ceb501b0775845f36601ddffa +--- /dev/null ++++ CELO/op-e2e/system/runcfg/p2p_signer_test.go +@@ -0,0 +1,62 @@ ++package runcfg ++ ++import ( ++ "context" ++ "fmt" ++ "testing" ++ "time" ++ ++ op_e2e "github.com/ethereum-optimism/optimism/op-e2e" ++ ++ "github.com/ethereum-optimism/optimism/op-e2e/bindings" ++ "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" ++ "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" ++ "github.com/ethereum-optimism/optimism/op-service/retry" ++ "github.com/ethereum/go-ethereum/accounts/abi/bind" ++ "github.com/ethereum/go-ethereum/common" ++ "github.com/stretchr/testify/require" ++) ++ ++func TestRuntimeConfigReload(t *testing.T) { ++ op_e2e.InitParallel(t) ++ ++ cfg := e2esys.DefaultSystemConfig(t) ++ // to speed up the test, make it reload the config more often, and do not impose a long conf depth ++ cfg.Nodes["verifier"].RuntimeConfigReloadInterval = time.Second * 5 ++ cfg.Nodes["verifier"].Driver.VerifierConfDepth = 1 ++ ++ sys, err := cfg.Start(t) ++ require.Nil(t, err, "Error starting up system") ++ ++ initialRuntimeConfig := sys.RollupNodes["verifier"].RuntimeConfig() ++ ++ // close the EL node, since we want to block derivation, to solely rely on the reloading mechanism for updates. ++ sys.EthInstances["verifier"].Close() ++ ++ l1 := sys.NodeClient("l1") ++ ++ // Change the system-config via L1 ++ sysCfgContract, err := bindings.NewSystemConfig(cfg.L1Deployments.SystemConfigProxy, l1) ++ require.NoError(t, err) ++ newUnsafeBlocksSigner := common.Address{0x12, 0x23, 0x45} ++ require.NotEqual(t, initialRuntimeConfig.P2PSequencerAddress(), newUnsafeBlocksSigner, "changing to a different address") ++ opts, err := bind.NewKeyedTransactorWithChainID(cfg.Secrets.SysCfgOwner, cfg.L1ChainIDBig()) ++ require.Nil(t, err) ++ // the unsafe signer address is part of the runtime config ++ tx, err := sysCfgContract.SetUnsafeBlockSigner(opts, newUnsafeBlocksSigner) ++ require.NoError(t, err) ++ ++ // wait for the change to confirm ++ _, err = wait.ForReceiptOK(context.Background(), l1, tx.Hash()) ++ require.NoError(t, err) ++ ++ // wait for the address to change ++ _, err = retry.Do(context.Background(), 10, retry.Fixed(time.Second*10), func() (struct{}, error) { ++ v := sys.RollupNodes["verifier"].RuntimeConfig().P2PSequencerAddress() ++ if v == newUnsafeBlocksSigner { ++ return struct{}{}, nil ++ } ++ return struct{}{}, fmt.Errorf("no change yet, seeing %s but looking for %s", v, newUnsafeBlocksSigner) ++ }) ++ require.NoError(t, err) ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+141
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/system/runcfg/protocol_versions_test.go CELO/op-e2e/system/runcfg/protocol_versions_test.go +new file mode 100644 +index 0000000000000000000000000000000000000000..14e056b044354ea55e3c133c6fad57d868ce4334 +--- /dev/null ++++ CELO/op-e2e/system/runcfg/protocol_versions_test.go +@@ -0,0 +1,141 @@ ++package runcfg ++ ++import ( ++ "context" ++ "errors" ++ "fmt" ++ "math/big" ++ "testing" ++ "time" ++ ++ op_e2e "github.com/ethereum-optimism/optimism/op-e2e" ++ ++ "github.com/ethereum-optimism/optimism/op-e2e/bindings" ++ "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" ++ "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" ++ "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" ++ "github.com/ethereum-optimism/optimism/op-service/client" ++ "github.com/ethereum-optimism/optimism/op-service/endpoint" ++ "github.com/ethereum-optimism/optimism/op-service/retry" ++ "github.com/ethereum/go-ethereum/accounts/abi/bind" ++ "github.com/ethereum/go-ethereum/common" ++ "github.com/ethereum/go-ethereum/eth/ethconfig" ++ "github.com/ethereum/go-ethereum/node" ++ "github.com/ethereum/go-ethereum/params" ++ "github.com/stretchr/testify/require" ++) ++ ++func TestRecommendedProtocolVersionChange(t *testing.T) { ++ op_e2e.InitParallel(t) ++ ++ cfg := e2esys.DefaultSystemConfig(t) ++ require.NotEqual(t, common.Address{}, cfg.L1Deployments.ProtocolVersions, "need ProtocolVersions contract deployment") ++ // to speed up the test, make it reload the config more often, and do not impose a long conf depth ++ cfg.Nodes["verifier"].RuntimeConfigReloadInterval = time.Second * 5 ++ cfg.Nodes["verifier"].Driver.VerifierConfDepth = 1 ++ ++ sys, err := cfg.Start(t) ++ require.Nil(t, err, "Error starting up system") ++ ++ runtimeConfig := sys.RollupNodes["verifier"].RuntimeConfig() ++ ++ // Change the superchain-config via L1 ++ l1 := sys.NodeClient("l1") ++ ++ _, build, major, minor, patch, preRelease := params.OPStackSupport.Parse() ++ newRecommendedProtocolVersion := params.ProtocolVersionV0{Build: build, Major: major + 1, Minor: minor, Patch: patch, PreRelease: preRelease}.Encode() ++ require.NotEqual(t, runtimeConfig.RecommendedProtocolVersion(), newRecommendedProtocolVersion, "changing to a different protocol version") ++ ++ protVersions, err := bindings.NewProtocolVersions(cfg.L1Deployments.ProtocolVersionsProxy, l1) ++ require.NoError(t, err) ++ ++ // ProtocolVersions contract is owned by same key as SystemConfig in devnet ++ opts, err := bind.NewKeyedTransactorWithChainID(cfg.Secrets.SysCfgOwner, cfg.L1ChainIDBig()) ++ require.NoError(t, err) ++ ++ // Change recommended protocol version ++ tx, err := protVersions.SetRecommended(opts, new(big.Int).SetBytes(newRecommendedProtocolVersion[:])) ++ require.NoError(t, err) ++ ++ // wait for the change to confirm ++ _, err = wait.ForReceiptOK(context.Background(), l1, tx.Hash()) ++ require.NoError(t, err) ++ ++ // wait for the recommended protocol version to change ++ _, err = retry.Do(context.Background(), 10, retry.Fixed(time.Second*10), func() (struct{}, error) { ++ v := sys.RollupNodes["verifier"].RuntimeConfig().RecommendedProtocolVersion() ++ if v == newRecommendedProtocolVersion { ++ return struct{}{}, nil ++ } ++ return struct{}{}, fmt.Errorf("no change yet, seeing %s but looking for %s", v, newRecommendedProtocolVersion) ++ }) ++ require.NoError(t, err) ++} ++ ++func TestRequiredProtocolVersionChangeAndHalt(t *testing.T) { ++ op_e2e.InitParallel(t) ++ ++ cfg := e2esys.DefaultSystemConfig(t) ++ // to speed up the test, make it reload the config more often, and do not impose a long conf depth ++ cfg.Nodes["verifier"].RuntimeConfigReloadInterval = time.Second * 5 ++ cfg.Nodes["verifier"].Driver.VerifierConfDepth = 1 ++ // configure halt in verifier op-node ++ cfg.Nodes["verifier"].RollupHalt = "major" ++ // configure halt in verifier op-geth node ++ cfg.GethOptions["verifier"] = append(cfg.GethOptions["verifier"], []geth.GethOption{ ++ func(ethCfg *ethconfig.Config, nodeCfg *node.Config) error { ++ ethCfg.RollupHaltOnIncompatibleProtocolVersion = "major" ++ return nil ++ }, ++ }...) ++ ++ sys, err := cfg.Start(t) ++ require.Nil(t, err, "Error starting up system") ++ ++ runtimeConfig := sys.RollupNodes["verifier"].RuntimeConfig() ++ ++ // Change the superchain-config via L1 ++ l1 := sys.NodeClient("l1") ++ ++ _, build, major, minor, patch, preRelease := params.OPStackSupport.Parse() ++ newRequiredProtocolVersion := params.ProtocolVersionV0{Build: build, Major: major + 1, Minor: minor, Patch: patch, PreRelease: preRelease}.Encode() ++ require.NotEqual(t, runtimeConfig.RequiredProtocolVersion(), newRequiredProtocolVersion, "changing to a different protocol version") ++ ++ protVersions, err := bindings.NewProtocolVersions(cfg.L1Deployments.ProtocolVersionsProxy, l1) ++ require.NoError(t, err) ++ ++ // ProtocolVersions contract is owned by same key as SystemConfig in devnet ++ opts, err := bind.NewKeyedTransactorWithChainID(cfg.Secrets.SysCfgOwner, cfg.L1ChainIDBig()) ++ require.NoError(t, err) ++ ++ // Change required protocol version ++ tx, err := protVersions.SetRequired(opts, new(big.Int).SetBytes(newRequiredProtocolVersion[:])) ++ require.NoError(t, err) ++ ++ // wait for the change to confirm ++ _, err = wait.ForReceiptOK(context.Background(), l1, tx.Hash()) ++ require.NoError(t, err) ++ ++ // wait for the required protocol version to take effect by halting the verifier that opted in, and halting the op-geth node that opted in. ++ _, err = retry.Do(context.Background(), 10, retry.Fixed(time.Second*10), func() (struct{}, error) { ++ if !sys.RollupNodes["verifier"].Stopped() { ++ return struct{}{}, errors.New("verifier rollup node is not closed yet") ++ } ++ return struct{}{}, nil ++ }) ++ require.NoError(t, err) ++ t.Log("verified that op-node closed!") ++ // Checking if the engine is down is not trivial in op-e2e. ++ // In op-geth we have halting tests covering the Engine API, in op-e2e we instead check if the API stops. ++ _, err = retry.Do(context.Background(), 10, retry.Fixed(time.Second*10), func() (struct{}, error) { ++ ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) ++ defer cancel() ++ available := client.IsURLAvailable(ctx, sys.NodeEndpoint("verifier").(endpoint.HttpRPC).HttpRPC()) ++ if !available && ctx.Err() == nil { // waiting for client to stop responding to RPC requests (slow dials with timeout don't count) ++ return struct{}{}, nil ++ } ++ return struct{}{}, errors.New("verifier EL node is not closed yet") ++ }) ++ require.NoError(t, err) ++ t.Log("verified that op-geth closed!") ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+11
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/system/runcfg/runcfg_test.go CELO/op-e2e/system/runcfg/runcfg_test.go +new file mode 100644 +index 0000000000000000000000000000000000000000..62cb755538169f6379fb56bc67d45a07da04565b +--- /dev/null ++++ CELO/op-e2e/system/runcfg/runcfg_test.go +@@ -0,0 +1,11 @@ ++package runcfg ++ ++import ( ++ "testing" ++ ++ op_e2e "github.com/ethereum-optimism/optimism/op-e2e" ++) ++ ++func TestMain(m *testing.M) { ++ op_e2e.RunMain(m) ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+113
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/system/verifier/basic_test.go CELO/op-e2e/system/verifier/basic_test.go +new file mode 100644 +index 0000000000000000000000000000000000000000..effe1f4121462da273433f18a7f174a52340698b +--- /dev/null ++++ CELO/op-e2e/system/verifier/basic_test.go +@@ -0,0 +1,113 @@ ++package verifier ++ ++import ( ++ "context" ++ "math/big" ++ "testing" ++ "time" ++ ++ op_e2e "github.com/ethereum-optimism/optimism/op-e2e" ++ ++ "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" ++ "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" ++ "github.com/ethereum-optimism/optimism/op-e2e/system/helpers" ++ "github.com/ethereum-optimism/optimism/op-service/testlog" ++ "github.com/ethereum/go-ethereum/accounts/abi/bind" ++ "github.com/ethereum/go-ethereum/common" ++ "github.com/ethereum/go-ethereum/common/hexutil" ++ "github.com/ethereum/go-ethereum/log" ++ "github.com/stretchr/testify/require" ++) ++ ++func TestSystemE2EDencunAtGenesis(t *testing.T) { ++ op_e2e.InitParallel(t) ++ ++ cfg := e2esys.DefaultSystemConfig(t) ++ cfg.DeployConfig.L1CancunTimeOffset = new(hexutil.Uint64) ++ ++ sys, err := cfg.Start(t) ++ require.Nil(t, err, "Error starting up system") ++ ++ runE2ESystemTest(t, sys) ++ head, err := sys.NodeClient("l1").BlockByNumber(context.Background(), big.NewInt(0)) ++ require.NoError(t, err) ++ require.NotNil(t, head.ExcessBlobGas(), "L1 is building dencun blocks since genesis") ++} ++ ++// TestSystemE2E sets up a L1 Geth node, a rollup node, and a L2 geth node and then confirms that L1 deposits are reflected on L2. ++// All nodes are run in process (but are the full nodes, not mocked or stubbed). ++func TestSystemE2E(t *testing.T) { ++ op_e2e.InitParallel(t) ++ ++ cfg := e2esys.DefaultSystemConfig(t) ++ ++ sys, err := cfg.Start(t) ++ require.Nil(t, err, "Error starting up system") ++ runE2ESystemTest(t, sys) ++ ++} ++ ++func runE2ESystemTest(t *testing.T, sys *e2esys.System) { ++ log := testlog.Logger(t, log.LevelInfo) ++ log.Info("genesis", "l2", sys.RollupConfig.Genesis.L2, "l1", sys.RollupConfig.Genesis.L1, "l2_time", sys.RollupConfig.Genesis.L2Time) ++ ++ l1Client := sys.NodeClient("l1") ++ l2Seq := sys.NodeClient("sequencer") ++ l2Verif := sys.NodeClient("verifier") ++ ++ // Transactor Account ++ ethPrivKey := sys.Cfg.Secrets.Alice ++ ++ // Send Transaction & wait for success ++ fromAddr := sys.Cfg.Secrets.Addresses().Alice ++ ++ ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) ++ defer cancel() ++ startBalance, err := l2Verif.BalanceAt(ctx, fromAddr, nil) ++ require.Nil(t, err) ++ ++ // Send deposit transaction ++ opts, err := bind.NewKeyedTransactorWithChainID(ethPrivKey, sys.Cfg.L1ChainIDBig()) ++ require.Nil(t, err) ++ mintAmount := big.NewInt(1_000_000_000_000) ++ opts.Value = mintAmount ++ helpers.SendDepositTx(t, sys.Cfg, l1Client, l2Verif, opts, func(l2Opts *helpers.DepositTxOpts) {}) ++ ++ // Confirm balance ++ ctx, cancel = context.WithTimeout(context.Background(), 15*time.Second) ++ defer cancel() ++ ++ endBalance, err := wait.ForBalanceChange(ctx, l2Verif, fromAddr, startBalance) ++ require.Nil(t, err) ++ ++ diff := new(big.Int) ++ diff = diff.Sub(endBalance, startBalance) ++ require.Equal(t, mintAmount, diff, "Did not get expected balance change") ++ ++ // Submit TX to L2 sequencer node ++ receipt := helpers.SendL2Tx(t, sys.Cfg, l2Seq, ethPrivKey, func(opts *helpers.TxOpts) { ++ opts.Value = big.NewInt(1_000_000_000) ++ opts.Nonce = 1 // Already have deposit ++ opts.ToAddr = &common.Address{0xff, 0xff} ++ opts.VerifyOnClients(l2Verif) ++ }) ++ ++ // Verify blocks match after batch submission on verifiers and sequencers ++ verifBlock, err := l2Verif.BlockByNumber(context.Background(), receipt.BlockNumber) ++ require.Nil(t, err) ++ seqBlock, err := l2Seq.BlockByNumber(context.Background(), receipt.BlockNumber) ++ require.Nil(t, err) ++ require.Equal(t, verifBlock.NumberU64(), seqBlock.NumberU64(), "Verifier and sequencer blocks not the same after including a batch tx") ++ require.Equal(t, verifBlock.ParentHash(), seqBlock.ParentHash(), "Verifier and sequencer blocks parent hashes not the same after including a batch tx") ++ require.Equal(t, verifBlock.Hash(), seqBlock.Hash(), "Verifier and sequencer blocks not the same after including a batch tx") ++ ++ rollupClient := sys.RollupClient("sequencer") ++ // basic check that sync status works ++ seqStatus, err := rollupClient.SyncStatus(context.Background()) ++ require.Nil(t, err) ++ require.LessOrEqual(t, seqBlock.NumberU64(), seqStatus.UnsafeL2.Number) ++ // basic check that version endpoint works ++ seqVersion, err := rollupClient.Version(context.Background()) ++ require.Nil(t, err) ++ require.NotEqual(t, "", seqVersion) ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+61
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/system/verifier/confdepth_test.go CELO/op-e2e/system/verifier/confdepth_test.go +new file mode 100644 +index 0000000000000000000000000000000000000000..698496c68331942ca21289431dbb17e4376bf19a +--- /dev/null ++++ CELO/op-e2e/system/verifier/confdepth_test.go +@@ -0,0 +1,61 @@ ++package verifier ++ ++import ( ++ "context" ++ "testing" ++ "time" ++ ++ op_e2e "github.com/ethereum-optimism/optimism/op-e2e" ++ ++ "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" ++ "github.com/ethereum-optimism/optimism/op-node/rollup/derive" ++ "github.com/ethereum-optimism/optimism/op-service/testlog" ++ "github.com/ethereum/go-ethereum/log" ++ "github.com/stretchr/testify/require" ++) ++ ++// TestConfirmationDepth runs the rollup with both sequencer and verifier not immediately processing the tip of the chain. ++func TestConfirmationDepth(t *testing.T) { ++ op_e2e.InitParallel(t) ++ ++ cfg := e2esys.DefaultSystemConfig(t) ++ cfg.DeployConfig.SequencerWindowSize = 4 ++ cfg.DeployConfig.MaxSequencerDrift = 10 * cfg.DeployConfig.L1BlockTime ++ seqConfDepth := uint64(2) ++ verConfDepth := uint64(5) ++ cfg.Nodes["sequencer"].Driver.SequencerConfDepth = seqConfDepth ++ cfg.Nodes["sequencer"].Driver.VerifierConfDepth = 0 ++ cfg.Nodes["verifier"].Driver.VerifierConfDepth = verConfDepth ++ ++ sys, err := cfg.Start(t) ++ require.Nil(t, err, "Error starting up system") ++ ++ log := testlog.Logger(t, log.LevelInfo) ++ log.Info("genesis", "l2", sys.RollupConfig.Genesis.L2, "l1", sys.RollupConfig.Genesis.L1, "l2_time", sys.RollupConfig.Genesis.L2Time) ++ ++ l1Client := sys.NodeClient("l1") ++ l2Seq := sys.NodeClient("sequencer") ++ l2Verif := sys.NodeClient("verifier") ++ ++ // Wait enough time for the sequencer to submit a block with distance from L1 head, submit it, ++ // and for the slower verifier to read a full sequence window and cover confirmation depth for reading and some margin ++ <-time.After(time.Duration((cfg.DeployConfig.SequencerWindowSize+verConfDepth+3)*cfg.DeployConfig.L1BlockTime) * time.Second) ++ ++ // within a second, get both L1 and L2 verifier and sequencer block heads ++ ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) ++ defer cancel() ++ l1Head, err := l1Client.BlockByNumber(ctx, nil) ++ require.NoError(t, err) ++ l2SeqHead, err := l2Seq.BlockByNumber(ctx, nil) ++ require.NoError(t, err) ++ l2VerHead, err := l2Verif.BlockByNumber(ctx, nil) ++ require.NoError(t, err) ++ ++ seqInfo, err := derive.L1BlockInfoFromBytes(sys.RollupConfig, l2SeqHead.Time(), l2SeqHead.Transactions()[0].Data()) ++ require.NoError(t, err) ++ require.LessOrEqual(t, seqInfo.Number+seqConfDepth, l1Head.NumberU64(), "the seq L2 head block should have an origin older than the L1 head block by at least the sequencer conf depth") ++ ++ verInfo, err := derive.L1BlockInfoFromBytes(sys.RollupConfig, l2VerHead.Time(), l2VerHead.Transactions()[0].Data()) ++ require.NoError(t, err) ++ require.LessOrEqual(t, verInfo.Number+verConfDepth, l1Head.NumberU64(), "the ver L2 head block should have an origin older than the L1 head block by at least the verifier conf depth") ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+29
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/system/verifier/finalize_test.go CELO/op-e2e/system/verifier/finalize_test.go +new file mode 100644 +index 0000000000000000000000000000000000000000..976d9a9077bf7f706f4162b3d7448bffaa44308a +--- /dev/null ++++ CELO/op-e2e/system/verifier/finalize_test.go +@@ -0,0 +1,29 @@ ++package verifier ++ ++import ( ++ "math/big" ++ "testing" ++ "time" ++ ++ op_e2e "github.com/ethereum-optimism/optimism/op-e2e" ++ ++ "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" ++ "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" ++ "github.com/stretchr/testify/require" ++) ++ ++// TestFinalize tests if L2 finalizes after sufficient time after L1 finalizes ++func TestFinalize(t *testing.T) { ++ op_e2e.InitParallel(t) ++ ++ cfg := e2esys.DefaultSystemConfig(t) ++ ++ sys, err := cfg.Start(t) ++ require.Nil(t, err, "Error starting up system") ++ ++ l2Seq := sys.NodeClient("sequencer") ++ ++ l2Finalized, err := geth.WaitForBlockToBeFinalized(big.NewInt(12), l2Seq, 1*time.Minute) ++ require.NoError(t, err, "must be able to fetch a finalized L2 block") ++ require.NotZerof(t, l2Finalized.NumberU64(), "must have finalized L2 block") ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+120
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/system/verifier/legacy_pending_test.go CELO/op-e2e/system/verifier/legacy_pending_test.go +new file mode 100644 +index 0000000000000000000000000000000000000000..8a3afee5e091d6317c7979a9c11d0d13683d5766 +--- /dev/null ++++ CELO/op-e2e/system/verifier/legacy_pending_test.go +@@ -0,0 +1,120 @@ ++package verifier ++ ++import ( ++ "context" ++ "math/big" ++ "testing" ++ "time" ++ ++ op_e2e "github.com/ethereum-optimism/optimism/op-e2e" ++ ++ "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" ++ "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" ++ "github.com/ethereum-optimism/optimism/op-service/testlog" ++ "github.com/ethereum/go-ethereum/core/types" ++ "github.com/ethereum/go-ethereum/eth/ethconfig" ++ "github.com/ethereum/go-ethereum/ethclient" ++ "github.com/ethereum/go-ethereum/log" ++ "github.com/ethereum/go-ethereum/node" ++ "github.com/ethereum/go-ethereum/rpc" ++ "github.com/stretchr/testify/require" ++) ++ ++// TestPendingGasLimit tests the configuration of the gas limit of the pending block, ++// and if it does not conflict with the regular gas limit on the verifier or sequencer. ++func TestPendingGasLimit(t *testing.T) { ++ op_e2e.InitParallel(t) ++ ++ cfg := e2esys.DefaultSystemConfig(t) ++ ++ // configure the L2 gas limit to be high, and the pending gas limits to be lower for resource saving. ++ cfg.DeployConfig.L2GenesisBlockGasLimit = 30_000_000 ++ cfg.GethOptions["sequencer"] = append(cfg.GethOptions["sequencer"], []geth.GethOption{ ++ func(ethCfg *ethconfig.Config, nodeCfg *node.Config) error { ++ ethCfg.Miner.GasCeil = 10_000_000 ++ ethCfg.Miner.RollupComputePendingBlock = true ++ return nil ++ }, ++ }...) ++ cfg.GethOptions["verifier"] = append(cfg.GethOptions["verifier"], []geth.GethOption{ ++ func(ethCfg *ethconfig.Config, nodeCfg *node.Config) error { ++ ethCfg.Miner.GasCeil = 9_000_000 ++ ethCfg.Miner.RollupComputePendingBlock = true ++ return nil ++ }, ++ }...) ++ ++ sys, err := cfg.Start(t) ++ require.Nil(t, err, "Error starting up system") ++ ++ log := testlog.Logger(t, log.LevelInfo) ++ log.Info("genesis", "l2", sys.RollupConfig.Genesis.L2, "l1", sys.RollupConfig.Genesis.L1, "l2_time", sys.RollupConfig.Genesis.L2Time) ++ ++ l2Verif := sys.NodeClient("verifier") ++ l2Seq := sys.NodeClient("sequencer") ++ ++ checkGasLimit := func(client *ethclient.Client, number *big.Int, expected uint64) *types.Header { ++ ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) ++ header, err := client.HeaderByNumber(ctx, number) ++ cancel() ++ require.NoError(t, err) ++ require.Equal(t, expected, header.GasLimit) ++ return header ++ } ++ ++ // check if the gaslimits are matching the expected values, ++ // and that the verifier/sequencer can use their locally configured gas limit for the pending block. ++ for { ++ checkGasLimit(l2Seq, big.NewInt(-1), 10_000_000) ++ checkGasLimit(l2Verif, big.NewInt(-1), 9_000_000) ++ checkGasLimit(l2Seq, nil, 30_000_000) ++ latestVerifHeader := checkGasLimit(l2Verif, nil, 30_000_000) ++ ++ // Stop once the verifier passes genesis: ++ // this implies we checked a new block from the sequencer, on both sequencer and verifier nodes. ++ if latestVerifHeader.Number.Uint64() > 0 { ++ break ++ } ++ time.Sleep(500 * time.Millisecond) ++ } ++} ++ ++// TestPendingBlockIsLatest tests that we serve the latest block as pending block ++func TestPendingBlockIsLatest(t *testing.T) { ++ op_e2e.InitParallel(t) ++ ++ cfg := e2esys.DefaultSystemConfig(t) ++ sys, err := cfg.Start(t) ++ require.Nil(t, err, "Error starting up system") ++ ++ l2Seq := sys.NodeClient("sequencer") ++ ++ t.Run("block", func(t *testing.T) { ++ for i := 0; i < 10; i++ { ++ pending, err := l2Seq.BlockByNumber(context.Background(), big.NewInt(rpc.PendingBlockNumber.Int64())) ++ require.NoError(t, err) ++ latest, err := l2Seq.BlockByNumber(context.Background(), nil) ++ require.NoError(t, err) ++ if pending.NumberU64() == latest.NumberU64() { ++ require.Equal(t, pending.Hash(), latest.Hash(), "pending must exactly match latest block") ++ return ++ } ++ // re-try until we have the same number, as the requests are not an atomic bundle, and the sequencer may create a block. ++ } ++ t.Fatal("failed to get pending block with same number as latest block") ++ }) ++ t.Run("header", func(t *testing.T) { ++ for i := 0; i < 10; i++ { ++ pending, err := l2Seq.HeaderByNumber(context.Background(), big.NewInt(rpc.PendingBlockNumber.Int64())) ++ require.NoError(t, err) ++ latest, err := l2Seq.HeaderByNumber(context.Background(), nil) ++ require.NoError(t, err) ++ if pending.Number.Uint64() == latest.Number.Uint64() { ++ require.Equal(t, pending.Hash(), latest.Hash(), "pending must exactly match latest header") ++ return ++ } ++ // re-try until we have the same number, as the requests are not an atomic bundle, and the sequencer may create a block. ++ } ++ t.Fatal("failed to get pending header with same number as latest header") ++ }) ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+73
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/system/verifier/sequencer_window_test.go CELO/op-e2e/system/verifier/sequencer_window_test.go +new file mode 100644 +index 0000000000000000000000000000000000000000..aa836402e99b8c10320186be916a5c6e4ad81643 +--- /dev/null ++++ CELO/op-e2e/system/verifier/sequencer_window_test.go +@@ -0,0 +1,73 @@ ++package verifier ++ ++import ( ++ "context" ++ "math/big" ++ "testing" ++ "time" ++ ++ op_e2e "github.com/ethereum-optimism/optimism/op-e2e" ++ ++ "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" ++ "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" ++ "github.com/ethereum-optimism/optimism/op-e2e/system/e2esys" ++ "github.com/ethereum-optimism/optimism/op-e2e/system/helpers" ++ "github.com/ethereum/go-ethereum" ++ "github.com/ethereum/go-ethereum/common" ++ "github.com/stretchr/testify/require" ++) ++ ++func TestMissingBatchE2E(t *testing.T) { ++ op_e2e.InitParallel(t) ++ // Note this test zeroes the balance of the batch-submitter to make the batches unable to go into L1. ++ // The test logs may look scary, but this is expected: ++ // 'batcher unable to publish transaction role=batcher err="insufficient funds for gas * price + value"' ++ ++ cfg := e2esys.DefaultSystemConfig(t) ++ // small sequence window size so the test does not take as long ++ cfg.DeployConfig.SequencerWindowSize = 4 ++ ++ // Specifically set batch submitter balance to stop batches from being included ++ cfg.Premine[cfg.Secrets.Addresses().Batcher] = big.NewInt(0) ++ ++ sys, err := cfg.Start(t) ++ require.Nil(t, err, "Error starting up system") ++ ++ l2Seq := sys.NodeClient("sequencer") ++ l2Verif := sys.NodeClient("verifier") ++ ++ seqRollupClient := sys.RollupClient("sequencer") ++ ++ // Transactor Account ++ ethPrivKey := cfg.Secrets.Alice ++ ++ // Submit TX to L2 sequencer node ++ receipt := helpers.SendL2Tx(t, cfg, l2Seq, ethPrivKey, func(opts *helpers.TxOpts) { ++ opts.ToAddr = &common.Address{0xff, 0xff} ++ opts.Value = big.NewInt(1_000_000_000) ++ }) ++ ++ // Wait until the block it was first included in shows up in the safe chain on the verifier ++ _, err = geth.WaitForBlock(receipt.BlockNumber, l2Verif, time.Duration((sys.RollupConfig.SeqWindowSize+4)*cfg.DeployConfig.L1BlockTime)*time.Second) ++ require.Nil(t, err, "Waiting for block on verifier") ++ ++ // Assert that the transaction is not found on the verifier ++ ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) ++ defer cancel() ++ _, err = l2Verif.TransactionReceipt(ctx, receipt.TxHash) ++ require.Equal(t, ethereum.NotFound, err, "Found transaction in verifier when it should not have been included") ++ ++ // Wait a short time for the L2 reorg to occur on the sequencer as well. ++ err = wait.ForSafeBlock(ctx, seqRollupClient, receipt.BlockNumber.Uint64()) ++ require.Nil(t, err, "timeout waiting for L2 reorg on sequencer safe head") ++ ++ // Assert that the reconciliation process did an L2 reorg on the sequencer to remove the invalid block ++ ctx2, cancel := context.WithTimeout(context.Background(), 30*time.Second) ++ defer cancel() ++ block, err := l2Seq.BlockByNumber(ctx2, receipt.BlockNumber) ++ if err != nil { ++ require.Equal(t, "not found", err.Error(), "A not found error indicates the chain must have re-orged back before it") ++ } else { ++ require.NotEqual(t, block.Hash(), receipt.BlockHash, "L2 Sequencer did not reorg out transaction on it's safe chain") ++ } ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+11
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/system/verifier/verifier_test.go CELO/op-e2e/system/verifier/verifier_test.go +new file mode 100644 +index 0000000000000000000000000000000000000000..33527b62da24d97d900f74d9291fa197b633eb7a +--- /dev/null ++++ CELO/op-e2e/system/verifier/verifier_test.go +@@ -0,0 +1,11 @@ ++package verifier ++ ++import ( ++ "testing" ++ ++ op_e2e "github.com/ethereum-optimism/optimism/op-e2e" ++) ++ ++func TestMain(m *testing.M) { ++ op_e2e.RunMain(m) ++}
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + (deleted) + +
+
+
+ +
+ +
+ +
+0
+
-1612
+ +
+ +
+
+
diff --git OP/op-e2e/system_test.go CELO/op-e2e/system_test.go +deleted file mode 100644 +index a168a8c90df624eb5ac99507a3c4f95fd4379e7f..0000000000000000000000000000000000000000 +--- OP/op-e2e/system_test.go ++++ /dev/null +@@ -1,1612 +0,0 @@ +-package op_e2e +- +-import ( +- "context" +- "errors" +- "fmt" +- "math/big" +- "os" +- "runtime" +- "slices" +- "testing" +- "time" +- +- "github.com/libp2p/go-libp2p/core/peer" +- "github.com/stretchr/testify/require" +- +- "github.com/ethereum/go-ethereum" +- "github.com/ethereum/go-ethereum/accounts/abi/bind" +- "github.com/ethereum/go-ethereum/common" +- "github.com/ethereum/go-ethereum/common/hexutil" +- "github.com/ethereum/go-ethereum/consensus/misc/eip4844" +- "github.com/ethereum/go-ethereum/core/types" +- "github.com/ethereum/go-ethereum/crypto" +- "github.com/ethereum/go-ethereum/eth/ethconfig" +- "github.com/ethereum/go-ethereum/ethclient" +- "github.com/ethereum/go-ethereum/log" +- "github.com/ethereum/go-ethereum/node" +- "github.com/ethereum/go-ethereum/params" +- "github.com/ethereum/go-ethereum/rpc" +- +- "github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts" +- metrics2 "github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts/metrics" +- "github.com/ethereum-optimism/optimism/op-e2e/bindings" +- "github.com/ethereum-optimism/optimism/op-e2e/config" +- "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth" +- "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/transactions" +- "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait" +- "github.com/ethereum-optimism/optimism/op-node/metrics" +- rollupNode "github.com/ethereum-optimism/optimism/op-node/node" +- "github.com/ethereum-optimism/optimism/op-node/p2p" +- "github.com/ethereum-optimism/optimism/op-node/rollup/derive" +- "github.com/ethereum-optimism/optimism/op-node/rollup/driver" +- "github.com/ethereum-optimism/optimism/op-service/client" +- "github.com/ethereum-optimism/optimism/op-service/endpoint" +- "github.com/ethereum-optimism/optimism/op-service/eth" +- "github.com/ethereum-optimism/optimism/op-service/oppprof" +- "github.com/ethereum-optimism/optimism/op-service/predeploys" +- "github.com/ethereum-optimism/optimism/op-service/retry" +- "github.com/ethereum-optimism/optimism/op-service/sources/batching" +- "github.com/ethereum-optimism/optimism/op-service/testlog" +-) +- +-// TestSystemBatchType run each system e2e test case in singular batch mode and span batch mode. +-// If the test case tests batch submission and advancing safe head, it should be tested in both singular and span batch mode. +-func TestSystemBatchType(t *testing.T) { +- tests := []struct { +- name string +- f func(*testing.T, func(*SystemConfig)) +- }{ +- {"StopStartBatcher", StopStartBatcher}, +- } +- for _, test := range tests { +- test := test +- t.Run(test.name+"_SingularBatch", func(t *testing.T) { +- test.f(t, func(sc *SystemConfig) { +- sc.BatcherBatchType = derive.SingularBatchType +- }) +- }) +- t.Run(test.name+"_SpanBatch", func(t *testing.T) { +- test.f(t, func(sc *SystemConfig) { +- sc.BatcherBatchType = derive.SpanBatchType +- }) +- }) +- t.Run(test.name+"_SpanBatchMaxBlocks", func(t *testing.T) { +- test.f(t, func(sc *SystemConfig) { +- sc.BatcherBatchType = derive.SpanBatchType +- sc.BatcherMaxBlocksPerSpanBatch = 2 +- }) +- }) +- } +-} +- +-func TestMain(m *testing.M) { +- if config.ExternalL2Shim != "" { +- fmt.Println("Running tests with external L2 process adapter at ", config.ExternalL2Shim) +- // As these are integration tests which launch many other processes, the +- // default parallelism makes the tests flaky. This change aims to +- // reduce the flakiness of these tests. +- maxProcs := runtime.NumCPU() / 4 +- if maxProcs == 0 { +- maxProcs = 1 +- } +- runtime.GOMAXPROCS(maxProcs) +- } +- +- os.Exit(m.Run()) +-} +- +-func TestL2OutputSubmitter(t *testing.T) { +- InitParallel(t, SkipOnFaultProofs) +- +- cfg := DefaultSystemConfig(t) +- cfg.NonFinalizedProposals = true // speed up the time till we see output proposals +- +- sys, err := cfg.Start(t) +- require.Nil(t, err, "Error starting up system") +- +- l1Client := sys.NodeClient("l1") +- +- rollupClient := sys.RollupClient("sequencer") +- +- // OutputOracle is already deployed +- l2OutputOracle, err := bindings.NewL2OutputOracleCaller(cfg.L1Deployments.L2OutputOracleProxy, l1Client) +- require.Nil(t, err) +- +- initialOutputBlockNumber, err := l2OutputOracle.LatestBlockNumber(&bind.CallOpts{}) +- require.Nil(t, err) +- +- // Wait until the second output submission from L2. The output submitter submits outputs from the +- // unsafe portion of the chain which gets reorged on startup. The sequencer has an out of date view +- // when it creates it's first block and uses and old L1 Origin. It then does not submit a batch +- // for that block and subsequently reorgs to match what the verifier derives when running the +- // reconcillation process. +- l2Verif := sys.NodeClient("verifier") +- _, err = geth.WaitForBlock(big.NewInt(6), l2Verif, 10*time.Duration(cfg.DeployConfig.L2BlockTime)*time.Second) +- require.Nil(t, err) +- +- // Wait for batch submitter to update L2 output oracle. +- timeoutCh := time.After(15 * time.Second) +- ticker := time.NewTicker(1 * time.Second) +- defer ticker.Stop() +- for { +- l2ooBlockNumber, err := l2OutputOracle.LatestBlockNumber(&bind.CallOpts{}) +- require.Nil(t, err) +- +- // Wait for the L2 output oracle to have been changed from the initial +- // timestamp set in the contract constructor. +- if l2ooBlockNumber.Cmp(initialOutputBlockNumber) > 0 { +- // Retrieve the l2 output committed at this updated timestamp. +- committedL2Output, err := l2OutputOracle.GetL2OutputAfter(&bind.CallOpts{}, l2ooBlockNumber) +- require.NotEqual(t, [32]byte{}, committedL2Output.OutputRoot, "Empty L2 Output") +- require.Nil(t, err) +- +- // Fetch the corresponding L2 block and assert the committed L2 +- // output matches the block's state root. +- // +- // NOTE: This assertion will change once the L2 output format is +- // finalized. +- ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) +- defer cancel() +- l2Output, err := rollupClient.OutputAtBlock(ctx, l2ooBlockNumber.Uint64()) +- require.Nil(t, err) +- require.Equal(t, l2Output.OutputRoot[:], committedL2Output.OutputRoot[:]) +- break +- } +- +- select { +- case <-timeoutCh: +- t.Fatalf("State root oracle not updated") +- case <-ticker.C: +- } +- } +-} +- +-func TestL2OutputSubmitterFaultProofs(t *testing.T) { +- InitParallel(t, SkipOnL2OO) +- +- cfg := DefaultSystemConfig(t) +- cfg.NonFinalizedProposals = true // speed up the time till we see output proposals +- +- sys, err := cfg.Start(t) +- require.Nil(t, err, "Error starting up system") +- +- l1Client := sys.NodeClient("l1") +- +- rollupClient := sys.RollupClient("sequencer") +- +- disputeGameFactory, err := bindings.NewDisputeGameFactoryCaller(cfg.L1Deployments.DisputeGameFactoryProxy, l1Client) +- require.Nil(t, err) +- +- initialGameCount, err := disputeGameFactory.GameCount(&bind.CallOpts{}) +- require.Nil(t, err) +- +- l2Verif := sys.NodeClient("verifier") +- _, err = geth.WaitForBlock(big.NewInt(6), l2Verif, 10*time.Duration(cfg.DeployConfig.L2BlockTime)*time.Second) +- require.Nil(t, err) +- +- timeoutCh := time.After(15 * time.Second) +- ticker := time.NewTicker(1 * time.Second) +- defer ticker.Stop() +- for { +- latestGameCount, err := disputeGameFactory.GameCount(&bind.CallOpts{}) +- require.Nil(t, err) +- +- if latestGameCount.Cmp(initialGameCount) > 0 { +- caller := batching.NewMultiCaller(l1Client.Client(), batching.DefaultBatchSize) +- committedL2Output, err := disputeGameFactory.GameAtIndex(&bind.CallOpts{}, new(big.Int).Sub(latestGameCount, common.Big1)) +- require.Nil(t, err) +- proxy, err := contracts.NewFaultDisputeGameContract(context.Background(), metrics2.NoopContractMetrics, committedL2Output.Proxy, caller) +- require.Nil(t, err) +- claim, err := proxy.GetClaim(context.Background(), 0) +- require.Nil(t, err) +- +- ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) +- defer cancel() +- _, gameBlockNumber, err := proxy.GetBlockRange(ctx) +- require.Nil(t, err) +- l2Output, err := rollupClient.OutputAtBlock(ctx, gameBlockNumber) +- require.Nil(t, err) +- require.EqualValues(t, l2Output.OutputRoot, claim.Value) +- break +- } +- +- select { +- case <-timeoutCh: +- t.Fatalf("State root oracle not updated") +- case <-ticker.C: +- } +- } +-} +- +-func TestSystemE2EDencunAtGenesis(t *testing.T) { +- InitParallel(t) +- +- cfg := DefaultSystemConfig(t) +- cfg.DeployConfig.L1CancunTimeOffset = &genesisTime +- +- sys, err := cfg.Start(t) +- require.Nil(t, err, "Error starting up system") +- +- runE2ESystemTest(t, sys) +- head, err := sys.NodeClient("l1").BlockByNumber(context.Background(), big.NewInt(0)) +- require.NoError(t, err) +- require.NotNil(t, head.ExcessBlobGas(), "L1 is building dencun blocks since genesis") +-} +- +-// TestSystemE2EDencunAtGenesis tests if L2 finalizes when blobs are present on L1 +-func TestSystemE2EDencunAtGenesisWithBlobs(t *testing.T) { +- ctx, cancel := context.WithCancel(context.Background()) +- defer cancel() +- +- InitParallel(t) +- +- cfg := DefaultSystemConfig(t) +- cfg.DeployConfig.L1CancunTimeOffset = &genesisTime +- +- sys, err := cfg.Start(t) +- require.Nil(t, err, "Error starting up system") +- +- // send a blob-containing txn on l1 +- ethPrivKey := sys.Cfg.Secrets.Alice +- txData := transactions.CreateEmptyBlobTx(true, sys.Cfg.L1ChainIDBig().Uint64()) +- tx := types.MustSignNewTx(ethPrivKey, types.LatestSignerForChainID(cfg.L1ChainIDBig()), txData) +- // send blob-containing txn +- sendCtx, sendCancel := context.WithTimeout(context.Background(), 15*time.Second) +- defer sendCancel() +- +- l1Client := sys.NodeClient("l1") +- err = l1Client.SendTransaction(sendCtx, tx) +- require.NoError(t, err, "Sending L1 empty blob tx") +- // Wait for transaction on L1 +- blockContainsBlob, err := wait.ForReceiptOK(ctx, l1Client, tx.Hash()) +- require.Nil(t, err, "Waiting for blob tx on L1") +- // end sending blob-containing txns on l1 +- l2Client := sys.NodeClient("sequencer") +- finalizedBlock, err := geth.WaitForL1OriginOnL2(sys.RollupConfig, blockContainsBlob.BlockNumber.Uint64(), l2Client, 30*time.Duration(cfg.DeployConfig.L1BlockTime)*time.Second) +- require.Nil(t, err, "Waiting for L1 origin of blob tx on L2") +- finalizationTimeout := 30 * time.Duration(cfg.DeployConfig.L1BlockTime) * time.Second +- _, err = geth.WaitForBlockToBeSafe(finalizedBlock.Header().Number, l2Client, finalizationTimeout) +- require.Nil(t, err, "Waiting for safety of L2 block") +-} +- +-// TestSystemE2E sets up a L1 Geth node, a rollup node, and a L2 geth node and then confirms that L1 deposits are reflected on L2. +-// All nodes are run in process (but are the full nodes, not mocked or stubbed). +-func TestSystemE2E(t *testing.T) { +- InitParallel(t) +- +- cfg := DefaultSystemConfig(t) +- +- sys, err := cfg.Start(t) +- require.Nil(t, err, "Error starting up system") +- runE2ESystemTest(t, sys) +- +-} +- +-func runE2ESystemTest(t *testing.T, sys *System) { +- log := testlog.Logger(t, log.LevelInfo) +- log.Info("genesis", "l2", sys.RollupConfig.Genesis.L2, "l1", sys.RollupConfig.Genesis.L1, "l2_time", sys.RollupConfig.Genesis.L2Time) +- +- l1Client := sys.NodeClient("l1") +- l2Seq := sys.NodeClient("sequencer") +- l2Verif := sys.NodeClient("verifier") +- +- // Transactor Account +- ethPrivKey := sys.Cfg.Secrets.Alice +- +- // Send Transaction & wait for success +- fromAddr := sys.Cfg.Secrets.Addresses().Alice +- +- ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) +- defer cancel() +- startBalance, err := l2Verif.BalanceAt(ctx, fromAddr, nil) +- require.Nil(t, err) +- +- // Send deposit transaction +- opts, err := bind.NewKeyedTransactorWithChainID(ethPrivKey, sys.Cfg.L1ChainIDBig()) +- require.Nil(t, err) +- mintAmount := big.NewInt(1_000_000_000_000) +- opts.Value = mintAmount +- SendDepositTx(t, sys.Cfg, l1Client, l2Verif, opts, func(l2Opts *DepositTxOpts) {}) +- +- // Confirm balance +- ctx, cancel = context.WithTimeout(context.Background(), 15*time.Second) +- defer cancel() +- +- endBalance, err := wait.ForBalanceChange(ctx, l2Verif, fromAddr, startBalance) +- require.Nil(t, err) +- +- diff := new(big.Int) +- diff = diff.Sub(endBalance, startBalance) +- require.Equal(t, mintAmount, diff, "Did not get expected balance change") +- +- // Submit TX to L2 sequencer node +- receipt := SendL2Tx(t, sys.Cfg, l2Seq, ethPrivKey, func(opts *TxOpts) { +- opts.Value = big.NewInt(1_000_000_000) +- opts.Nonce = 1 // Already have deposit +- opts.ToAddr = &common.Address{0xff, 0xff} +- opts.VerifyOnClients(l2Verif) +- }) +- +- // Verify blocks match after batch submission on verifiers and sequencers +- verifBlock, err := l2Verif.BlockByNumber(context.Background(), receipt.BlockNumber) +- require.Nil(t, err) +- seqBlock, err := l2Seq.BlockByNumber(context.Background(), receipt.BlockNumber) +- require.Nil(t, err) +- require.Equal(t, verifBlock.NumberU64(), seqBlock.NumberU64(), "Verifier and sequencer blocks not the same after including a batch tx") +- require.Equal(t, verifBlock.ParentHash(), seqBlock.ParentHash(), "Verifier and sequencer blocks parent hashes not the same after including a batch tx") +- require.Equal(t, verifBlock.Hash(), seqBlock.Hash(), "Verifier and sequencer blocks not the same after including a batch tx") +- +- rollupClient := sys.RollupClient("sequencer") +- // basic check that sync status works +- seqStatus, err := rollupClient.SyncStatus(context.Background()) +- require.Nil(t, err) +- require.LessOrEqual(t, seqBlock.NumberU64(), seqStatus.UnsafeL2.Number) +- // basic check that version endpoint works +- seqVersion, err := rollupClient.Version(context.Background()) +- require.Nil(t, err) +- require.NotEqual(t, "", seqVersion) +-} +- +-// TestConfirmationDepth runs the rollup with both sequencer and verifier not immediately processing the tip of the chain. +-func TestConfirmationDepth(t *testing.T) { +- InitParallel(t) +- +- cfg := DefaultSystemConfig(t) +- cfg.DeployConfig.SequencerWindowSize = 4 +- cfg.DeployConfig.MaxSequencerDrift = 10 * cfg.DeployConfig.L1BlockTime +- seqConfDepth := uint64(2) +- verConfDepth := uint64(5) +- cfg.Nodes["sequencer"].Driver.SequencerConfDepth = seqConfDepth +- cfg.Nodes["sequencer"].Driver.VerifierConfDepth = 0 +- cfg.Nodes["verifier"].Driver.VerifierConfDepth = verConfDepth +- +- sys, err := cfg.Start(t) +- require.Nil(t, err, "Error starting up system") +- +- log := testlog.Logger(t, log.LevelInfo) +- log.Info("genesis", "l2", sys.RollupConfig.Genesis.L2, "l1", sys.RollupConfig.Genesis.L1, "l2_time", sys.RollupConfig.Genesis.L2Time) +- +- l1Client := sys.NodeClient("l1") +- l2Seq := sys.NodeClient("sequencer") +- l2Verif := sys.NodeClient("verifier") +- +- // Wait enough time for the sequencer to submit a block with distance from L1 head, submit it, +- // and for the slower verifier to read a full sequence window and cover confirmation depth for reading and some margin +- <-time.After(time.Duration((cfg.DeployConfig.SequencerWindowSize+verConfDepth+3)*cfg.DeployConfig.L1BlockTime) * time.Second) +- +- // within a second, get both L1 and L2 verifier and sequencer block heads +- ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) +- defer cancel() +- l1Head, err := l1Client.BlockByNumber(ctx, nil) +- require.NoError(t, err) +- l2SeqHead, err := l2Seq.BlockByNumber(ctx, nil) +- require.NoError(t, err) +- l2VerHead, err := l2Verif.BlockByNumber(ctx, nil) +- require.NoError(t, err) +- +- seqInfo, err := derive.L1BlockInfoFromBytes(sys.RollupConfig, l2SeqHead.Time(), l2SeqHead.Transactions()[0].Data()) +- require.NoError(t, err) +- require.LessOrEqual(t, seqInfo.Number+seqConfDepth, l1Head.NumberU64(), "the seq L2 head block should have an origin older than the L1 head block by at least the sequencer conf depth") +- +- verInfo, err := derive.L1BlockInfoFromBytes(sys.RollupConfig, l2VerHead.Time(), l2VerHead.Transactions()[0].Data()) +- require.NoError(t, err) +- require.LessOrEqual(t, verInfo.Number+verConfDepth, l1Head.NumberU64(), "the ver L2 head block should have an origin older than the L1 head block by at least the verifier conf depth") +-} +- +-// TestPendingGasLimit tests the configuration of the gas limit of the pending block, +-// and if it does not conflict with the regular gas limit on the verifier or sequencer. +-func TestPendingGasLimit(t *testing.T) { +- InitParallel(t) +- +- cfg := DefaultSystemConfig(t) +- +- // configure the L2 gas limit to be high, and the pending gas limits to be lower for resource saving. +- cfg.DeployConfig.L2GenesisBlockGasLimit = 30_000_000 +- cfg.GethOptions["sequencer"] = append(cfg.GethOptions["sequencer"], []geth.GethOption{ +- func(ethCfg *ethconfig.Config, nodeCfg *node.Config) error { +- ethCfg.Miner.GasCeil = 10_000_000 +- ethCfg.Miner.RollupComputePendingBlock = true +- return nil +- }, +- }...) +- cfg.GethOptions["verifier"] = append(cfg.GethOptions["verifier"], []geth.GethOption{ +- func(ethCfg *ethconfig.Config, nodeCfg *node.Config) error { +- ethCfg.Miner.GasCeil = 9_000_000 +- ethCfg.Miner.RollupComputePendingBlock = true +- return nil +- }, +- }...) +- +- sys, err := cfg.Start(t) +- require.Nil(t, err, "Error starting up system") +- +- log := testlog.Logger(t, log.LevelInfo) +- log.Info("genesis", "l2", sys.RollupConfig.Genesis.L2, "l1", sys.RollupConfig.Genesis.L1, "l2_time", sys.RollupConfig.Genesis.L2Time) +- +- l2Verif := sys.NodeClient("verifier") +- l2Seq := sys.NodeClient("sequencer") +- +- checkGasLimit := func(client *ethclient.Client, number *big.Int, expected uint64) *types.Header { +- ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) +- header, err := client.HeaderByNumber(ctx, number) +- cancel() +- require.NoError(t, err) +- require.Equal(t, expected, header.GasLimit) +- return header +- } +- +- // check if the gaslimits are matching the expected values, +- // and that the verifier/sequencer can use their locally configured gas limit for the pending block. +- for { +- checkGasLimit(l2Seq, big.NewInt(-1), 10_000_000) +- checkGasLimit(l2Verif, big.NewInt(-1), 9_000_000) +- checkGasLimit(l2Seq, nil, 30_000_000) +- latestVerifHeader := checkGasLimit(l2Verif, nil, 30_000_000) +- +- // Stop once the verifier passes genesis: +- // this implies we checked a new block from the sequencer, on both sequencer and verifier nodes. +- if latestVerifHeader.Number.Uint64() > 0 { +- break +- } +- time.Sleep(500 * time.Millisecond) +- } +-} +- +-// TestFinalize tests if L2 finalizes after sufficient time after L1 finalizes +-func TestFinalize(t *testing.T) { +- InitParallel(t) +- +- cfg := DefaultSystemConfig(t) +- +- sys, err := cfg.Start(t) +- require.Nil(t, err, "Error starting up system") +- +- l2Seq := sys.NodeClient("sequencer") +- +- l2Finalized, err := geth.WaitForBlockToBeFinalized(big.NewInt(12), l2Seq, 1*time.Minute) +- require.NoError(t, err, "must be able to fetch a finalized L2 block") +- require.NotZerof(t, l2Finalized.NumberU64(), "must have finalized L2 block") +-} +- +-func TestMissingBatchE2E(t *testing.T) { +- InitParallel(t) +- // Note this test zeroes the balance of the batch-submitter to make the batches unable to go into L1. +- // The test logs may look scary, but this is expected: +- // 'batcher unable to publish transaction role=batcher err="insufficient funds for gas * price + value"' +- +- cfg := DefaultSystemConfig(t) +- // small sequence window size so the test does not take as long +- cfg.DeployConfig.SequencerWindowSize = 4 +- +- // Specifically set batch submitter balance to stop batches from being included +- cfg.Premine[cfg.Secrets.Addresses().Batcher] = big.NewInt(0) +- +- sys, err := cfg.Start(t) +- require.Nil(t, err, "Error starting up system") +- +- l2Seq := sys.NodeClient("sequencer") +- l2Verif := sys.NodeClient("verifier") +- +- seqRollupClient := sys.RollupClient("sequencer") +- +- // Transactor Account +- ethPrivKey := cfg.Secrets.Alice +- +- // Submit TX to L2 sequencer node +- receipt := SendL2Tx(t, cfg, l2Seq, ethPrivKey, func(opts *TxOpts) { +- opts.ToAddr = &common.Address{0xff, 0xff} +- opts.Value = big.NewInt(1_000_000_000) +- }) +- +- // Wait until the block it was first included in shows up in the safe chain on the verifier +- _, err = geth.WaitForBlock(receipt.BlockNumber, l2Verif, time.Duration((sys.RollupConfig.SeqWindowSize+4)*cfg.DeployConfig.L1BlockTime)*time.Second) +- require.Nil(t, err, "Waiting for block on verifier") +- +- // Assert that the transaction is not found on the verifier +- ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) +- defer cancel() +- _, err = l2Verif.TransactionReceipt(ctx, receipt.TxHash) +- require.Equal(t, ethereum.NotFound, err, "Found transaction in verifier when it should not have been included") +- +- // Wait a short time for the L2 reorg to occur on the sequencer as well. +- err = wait.ForSafeBlock(ctx, seqRollupClient, receipt.BlockNumber.Uint64()) +- require.Nil(t, err, "timeout waiting for L2 reorg on sequencer safe head") +- +- // Assert that the reconciliation process did an L2 reorg on the sequencer to remove the invalid block +- ctx2, cancel := context.WithTimeout(context.Background(), 30*time.Second) +- defer cancel() +- block, err := l2Seq.BlockByNumber(ctx2, receipt.BlockNumber) +- if err != nil { +- require.Equal(t, "not found", err.Error(), "A not found error indicates the chain must have re-orged back before it") +- } else { +- require.NotEqual(t, block.Hash(), receipt.BlockHash, "L2 Sequencer did not reorg out transaction on it's safe chain") +- } +-} +- +-func L1InfoFromState(ctx context.Context, contract *bindings.L1Block, l2Number *big.Int, ecotone bool) (*derive.L1BlockInfo, error) { +- var err error +- out := &derive.L1BlockInfo{} +- opts := bind.CallOpts{ +- BlockNumber: l2Number, +- Context: ctx, +- } +- +- out.Number, err = contract.Number(&opts) +- if err != nil { +- return nil, fmt.Errorf("failed to get number: %w", err) +- } +- +- out.Time, err = contract.Timestamp(&opts) +- if err != nil { +- return nil, fmt.Errorf("failed to get timestamp: %w", err) +- } +- +- out.BaseFee, err = contract.Basefee(&opts) +- if err != nil { +- return nil, fmt.Errorf("failed to get base fee: %w", err) +- } +- +- blockHashBytes, err := contract.Hash(&opts) +- if err != nil { +- return nil, fmt.Errorf("failed to get block hash: %w", err) +- } +- out.BlockHash = common.BytesToHash(blockHashBytes[:]) +- +- out.SequenceNumber, err = contract.SequenceNumber(&opts) +- if err != nil { +- return nil, fmt.Errorf("failed to get sequence number: %w", err) +- } +- +- if !ecotone { +- overhead, err := contract.L1FeeOverhead(&opts) +- if err != nil { +- return nil, fmt.Errorf("failed to get l1 fee overhead: %w", err) +- } +- out.L1FeeOverhead = eth.Bytes32(common.BigToHash(overhead)) +- +- scalar, err := contract.L1FeeScalar(&opts) +- if err != nil { +- return nil, fmt.Errorf("failed to get l1 fee scalar: %w", err) +- } +- out.L1FeeScalar = eth.Bytes32(common.BigToHash(scalar)) +- } +- +- batcherHash, err := contract.BatcherHash(&opts) +- if err != nil { +- return nil, fmt.Errorf("failed to get batch sender: %w", err) +- } +- out.BatcherAddr = common.BytesToAddress(batcherHash[:]) +- +- if ecotone { +- blobBaseFeeScalar, err := contract.BlobBaseFeeScalar(&opts) +- if err != nil { +- return nil, fmt.Errorf("failed to get blob basefee scalar: %w", err) +- } +- out.BlobBaseFeeScalar = blobBaseFeeScalar +- +- baseFeeScalar, err := contract.BaseFeeScalar(&opts) +- if err != nil { +- return nil, fmt.Errorf("failed to get basefee scalar: %w", err) +- } +- out.BaseFeeScalar = baseFeeScalar +- +- blobBaseFee, err := contract.BlobBaseFee(&opts) +- if err != nil { +- return nil, fmt.Errorf("failed to get blob basefee: %w", err) +- } +- out.BlobBaseFee = blobBaseFee +- } +- +- return out, nil +-} +- +-// TestSystemMockP2P sets up a L1 Geth node, a rollup node, and a L2 geth node and then confirms that +-// the nodes can sync L2 blocks before they are confirmed on L1. +-func TestSystemMockP2P(t *testing.T) { +- InitParallel(t) +- +- cfg := DefaultSystemConfig(t) +- // Disable batcher, so we don't sync from L1 & set a large sequence window so we only have unsafe blocks +- cfg.DisableBatcher = true +- cfg.DeployConfig.SequencerWindowSize = 100_000 +- cfg.DeployConfig.MaxSequencerDrift = 100_000 +- // disable at the start, so we don't miss any gossiped blocks. +- cfg.Nodes["sequencer"].Driver.SequencerStopped = true +- +- // connect the nodes +- cfg.P2PTopology = map[string][]string{ +- "verifier": {"sequencer"}, +- } +- +- var published, received []common.Hash +- seqTracer, verifTracer := new(FnTracer), new(FnTracer) +- seqTracer.OnPublishL2PayloadFn = func(ctx context.Context, payload *eth.ExecutionPayloadEnvelope) { +- published = append(published, payload.ExecutionPayload.BlockHash) +- } +- verifTracer.OnUnsafeL2PayloadFn = func(ctx context.Context, from peer.ID, payload *eth.ExecutionPayloadEnvelope) { +- received = append(received, payload.ExecutionPayload.BlockHash) +- } +- cfg.Nodes["sequencer"].Tracer = seqTracer +- cfg.Nodes["verifier"].Tracer = verifTracer +- +- sys, err := cfg.Start(t) +- require.Nil(t, err, "Error starting up system") +- +- // Enable the sequencer now that everyone is ready to receive payloads. +- rollupClient := sys.RollupClient("sequencer") +- +- verifierPeerID := sys.RollupNodes["verifier"].P2P().Host().ID() +- check := func() bool { +- sequencerBlocksTopicPeers := sys.RollupNodes["sequencer"].P2P().GossipOut().AllBlockTopicsPeers() +- return slices.Contains[[]peer.ID](sequencerBlocksTopicPeers, verifierPeerID) +- } +- +- // poll to see if the verifier node is connected & meshed on gossip. +- // Without this verifier, we shouldn't start sending blocks around, or we'll miss them and fail the test. +- backOffStrategy := retry.Exponential() +- for i := 0; i < 10; i++ { +- if check() { +- break +- } +- time.Sleep(backOffStrategy.Duration(i)) +- } +- require.True(t, check(), "verifier must be meshed with sequencer for gossip test to proceed") +- +- require.NoError(t, rollupClient.StartSequencer(context.Background(), sys.L2GenesisCfg.ToBlock().Hash())) +- +- l2Seq := sys.NodeClient("sequencer") +- l2Verif := sys.NodeClient("verifier") +- +- // Transactor Account +- ethPrivKey := cfg.Secrets.Alice +- +- // Submit TX to L2 sequencer node +- receiptSeq := SendL2Tx(t, cfg, l2Seq, ethPrivKey, func(opts *TxOpts) { +- opts.ToAddr = &common.Address{0xff, 0xff} +- opts.Value = big.NewInt(1_000_000_000) +- +- // Wait until the block it was first included in shows up in the safe chain on the verifier +- opts.VerifyOnClients(l2Verif) +- }) +- +- // Verify that everything that was received was published +- require.GreaterOrEqual(t, len(published), len(received)) +- require.Subset(t, published, received) +- +- // Verify that the tx was received via p2p +- require.Contains(t, received, receiptSeq.BlockHash) +-} +- +-func TestSystemP2PAltSync(t *testing.T) { +- ctx, cancel := context.WithCancel(context.Background()) +- defer cancel() +- +- InitParallel(t) +- +- cfg := DefaultSystemConfig(t) +- +- // remove default verifier node +- delete(cfg.Nodes, "verifier") +- // Add more verifier nodes +- cfg.Nodes["alice"] = &rollupNode.Config{ +- Driver: driver.Config{ +- VerifierConfDepth: 0, +- SequencerConfDepth: 0, +- SequencerEnabled: false, +- }, +- L1EpochPollInterval: time.Second * 4, +- } +- cfg.Nodes["bob"] = &rollupNode.Config{ +- Driver: driver.Config{ +- VerifierConfDepth: 0, +- SequencerConfDepth: 0, +- SequencerEnabled: false, +- }, +- L1EpochPollInterval: time.Second * 4, +- } +- cfg.Loggers["alice"] = testlog.Logger(t, log.LevelInfo).New("role", "alice") +- cfg.Loggers["bob"] = testlog.Logger(t, log.LevelInfo).New("role", "bob") +- +- // connect the nodes +- cfg.P2PTopology = map[string][]string{ +- "sequencer": {"alice", "bob"}, +- "alice": {"sequencer", "bob"}, +- "bob": {"alice", "sequencer"}, +- } +- // Enable the P2P req-resp based sync +- cfg.P2PReqRespSync = true +- +- // Disable batcher, so there will not be any L1 data to sync from +- cfg.DisableBatcher = true +- +- var published []string +- seqTracer := new(FnTracer) +- // The sequencer still publishes the blocks to the tracer, even if they do not reach the network due to disabled P2P +- seqTracer.OnPublishL2PayloadFn = func(ctx context.Context, payload *eth.ExecutionPayloadEnvelope) { +- published = append(published, payload.ExecutionPayload.ID().String()) +- } +- // Blocks are now received via the RPC based alt-sync method +- cfg.Nodes["sequencer"].Tracer = seqTracer +- +- sys, err := cfg.Start(t) +- require.Nil(t, err, "Error starting up system") +- +- l2Seq := sys.NodeClient("sequencer") +- +- // Transactor Account +- ethPrivKey := cfg.Secrets.Alice +- +- // Submit a TX to L2 sequencer node +- receiptSeq := SendL2Tx(t, cfg, l2Seq, ethPrivKey, func(opts *TxOpts) { +- opts.ToAddr = &common.Address{0xff, 0xff} +- opts.Value = big.NewInt(1_000_000_000) +- }) +- +- // Gossip is able to respond to IWANT messages for the duration of heartbeat_time * message_window = 0.5 * 12 = 6 +- // Wait till we pass that, and then we'll have missed some blocks that cannot be retrieved in any way from gossip +- time.Sleep(time.Second * 10) +- +- // set up our syncer node, connect it to alice/bob +- cfg.Loggers["syncer"] = testlog.Logger(t, log.LevelInfo).New("role", "syncer") +- +- // Create a peer, and hook up alice and bob +- h, err := sys.newMockNetPeer() +- require.NoError(t, err) +- _, err = sys.Mocknet.LinkPeers(sys.RollupNodes["alice"].P2P().Host().ID(), h.ID()) +- require.NoError(t, err) +- _, err = sys.Mocknet.LinkPeers(sys.RollupNodes["bob"].P2P().Host().ID(), h.ID()) +- require.NoError(t, err) +- +- // Configure the new rollup node that'll be syncing +- var syncedPayloads []string +- syncNodeCfg := &rollupNode.Config{ +- Driver: driver.Config{VerifierConfDepth: 0}, +- Rollup: *sys.RollupConfig, +- P2PSigner: nil, +- RPC: rollupNode.RPCConfig{ +- ListenAddr: "127.0.0.1", +- ListenPort: 0, +- EnableAdmin: true, +- }, +- P2P: &p2p.Prepared{HostP2P: h, EnableReqRespSync: true}, +- Metrics: rollupNode.MetricsConfig{Enabled: false}, // no metrics server +- Pprof: oppprof.CLIConfig{}, +- L1EpochPollInterval: time.Second * 10, +- Tracer: &FnTracer{ +- OnUnsafeL2PayloadFn: func(ctx context.Context, from peer.ID, payload *eth.ExecutionPayloadEnvelope) { +- syncedPayloads = append(syncedPayloads, payload.ExecutionPayload.ID().String()) +- }, +- }, +- } +- configureL1(syncNodeCfg, sys.EthInstances["l1"], sys.L1BeaconEndpoint()) +- syncerL2Engine, err := geth.InitL2("syncer", sys.L2GenesisCfg, cfg.JWTFilePath) +- require.NoError(t, err) +- require.NoError(t, syncerL2Engine.Node.Start()) +- +- configureL2(syncNodeCfg, syncerL2Engine, cfg.JWTSecret) +- +- syncerNode, err := rollupNode.New(ctx, syncNodeCfg, cfg.Loggers["syncer"], "", metrics.NewMetrics("")) +- require.NoError(t, err) +- err = syncerNode.Start(ctx) +- require.NoError(t, err) +- defer func() { +- require.NoError(t, syncerNode.Stop(ctx)) +- }() +- +- // connect alice and bob to our new syncer node +- _, err = sys.Mocknet.ConnectPeers(sys.RollupNodes["alice"].P2P().Host().ID(), syncerNode.P2P().Host().ID()) +- require.NoError(t, err) +- _, err = sys.Mocknet.ConnectPeers(sys.RollupNodes["bob"].P2P().Host().ID(), syncerNode.P2P().Host().ID()) +- require.NoError(t, err) +- +- rpc := syncerL2Engine.UserRPC().(endpoint.ClientRPC).ClientRPC() +- l2Verif := ethclient.NewClient(rpc) +- +- // It may take a while to sync, but eventually we should see the sequenced data show up +- receiptVerif, err := wait.ForReceiptOK(ctx, l2Verif, receiptSeq.TxHash) +- require.Nil(t, err, "Waiting for L2 tx on verifier") +- +- require.Equal(t, receiptSeq, receiptVerif) +- +- // Verify that the tx was received via P2P sync +- require.Contains(t, syncedPayloads, eth.BlockID{Hash: receiptVerif.BlockHash, Number: receiptVerif.BlockNumber.Uint64()}.String()) +- +- // Verify that everything that was received was published +- require.GreaterOrEqual(t, len(published), len(syncedPayloads)) +- require.Subset(t, published, syncedPayloads) +-} +- +-// TestSystemDenseTopology sets up a dense p2p topology with 3 verifier nodes and 1 sequencer node. +-func TestSystemDenseTopology(t *testing.T) { +- t.Skip("Skipping dense topology test to avoid flakiness. @refcell address in p2p scoring pr.") +- +- InitParallel(t) +- +- cfg := DefaultSystemConfig(t) +- // slow down L1 blocks so we can see the L2 blocks arrive well before the L1 blocks do. +- // Keep the seq window small so the L2 chain is started quick +- cfg.DeployConfig.L1BlockTime = 10 +- +- // Append additional nodes to the system to construct a dense p2p network +- cfg.Nodes["verifier2"] = &rollupNode.Config{ +- Driver: driver.Config{ +- VerifierConfDepth: 0, +- SequencerConfDepth: 0, +- SequencerEnabled: false, +- }, +- L1EpochPollInterval: time.Second * 4, +- } +- cfg.Nodes["verifier3"] = &rollupNode.Config{ +- Driver: driver.Config{ +- VerifierConfDepth: 0, +- SequencerConfDepth: 0, +- SequencerEnabled: false, +- }, +- L1EpochPollInterval: time.Second * 4, +- } +- cfg.Loggers["verifier2"] = testlog.Logger(t, log.LevelInfo).New("role", "verifier") +- cfg.Loggers["verifier3"] = testlog.Logger(t, log.LevelInfo).New("role", "verifier") +- +- // connect the nodes +- cfg.P2PTopology = map[string][]string{ +- "verifier": {"sequencer", "verifier2", "verifier3"}, +- "verifier2": {"sequencer", "verifier", "verifier3"}, +- "verifier3": {"sequencer", "verifier", "verifier2"}, +- } +- +- // Set peer scoring for each node, but without banning +- for _, node := range cfg.Nodes { +- params, err := p2p.GetScoringParams("light", &node.Rollup) +- require.NoError(t, err) +- node.P2P = &p2p.Config{ +- ScoringParams: params, +- BanningEnabled: false, +- } +- } +- +- var published, received1, received2, received3 []common.Hash +- seqTracer, verifTracer, verifTracer2, verifTracer3 := new(FnTracer), new(FnTracer), new(FnTracer), new(FnTracer) +- seqTracer.OnPublishL2PayloadFn = func(ctx context.Context, payload *eth.ExecutionPayloadEnvelope) { +- published = append(published, payload.ExecutionPayload.BlockHash) +- } +- verifTracer.OnUnsafeL2PayloadFn = func(ctx context.Context, from peer.ID, payload *eth.ExecutionPayloadEnvelope) { +- received1 = append(received1, payload.ExecutionPayload.BlockHash) +- } +- verifTracer2.OnUnsafeL2PayloadFn = func(ctx context.Context, from peer.ID, payload *eth.ExecutionPayloadEnvelope) { +- received2 = append(received2, payload.ExecutionPayload.BlockHash) +- } +- verifTracer3.OnUnsafeL2PayloadFn = func(ctx context.Context, from peer.ID, payload *eth.ExecutionPayloadEnvelope) { +- received3 = append(received3, payload.ExecutionPayload.BlockHash) +- } +- cfg.Nodes["sequencer"].Tracer = seqTracer +- cfg.Nodes["verifier"].Tracer = verifTracer +- cfg.Nodes["verifier2"].Tracer = verifTracer2 +- cfg.Nodes["verifier3"].Tracer = verifTracer3 +- +- sys, err := cfg.Start(t) +- require.Nil(t, err, "Error starting up system") +- +- l2Seq := sys.NodeClient("sequencer") +- l2Verif := sys.NodeClient("verifier") +- l2Verif2 := sys.NodeClient("verifier2") +- l2Verif3 := sys.NodeClient("verifier3") +- +- // Transactor Account +- ethPrivKey := cfg.Secrets.Alice +- +- // Submit TX to L2 sequencer node +- receiptSeq := SendL2Tx(t, cfg, l2Seq, ethPrivKey, func(opts *TxOpts) { +- opts.ToAddr = &common.Address{0xff, 0xff} +- opts.Value = big.NewInt(1_000_000_000) +- +- // Wait until the block it was first included in shows up in the safe chain on the verifiers +- opts.VerifyOnClients(l2Verif, l2Verif2, l2Verif3) +- }) +- +- // Verify that everything that was received was published +- require.GreaterOrEqual(t, len(published), len(received1)) +- require.GreaterOrEqual(t, len(published), len(received2)) +- require.GreaterOrEqual(t, len(published), len(received3)) +- require.ElementsMatch(t, published, received1[:len(published)]) +- require.ElementsMatch(t, published, received2[:len(published)]) +- require.ElementsMatch(t, published, received3[:len(published)]) +- +- // Verify that the tx was received via p2p +- require.Contains(t, received1, receiptSeq.BlockHash) +- require.Contains(t, received2, receiptSeq.BlockHash) +- require.Contains(t, received3, receiptSeq.BlockHash) +-} +- +-func TestL1InfoContract(t *testing.T) { +- InitParallel(t) +- +- cfg := DefaultSystemConfig(t) +- +- sys, err := cfg.Start(t) +- require.Nil(t, err, "Error starting up system") +- +- l1Client := sys.NodeClient("l1") +- l2Seq := sys.NodeClient("sequencer") +- l2Verif := sys.NodeClient("verifier") +- +- endVerifBlockNumber := big.NewInt(4) +- endSeqBlockNumber := big.NewInt(6) +- endVerifBlock, err := geth.WaitForBlock(endVerifBlockNumber, l2Verif, time.Minute) +- require.Nil(t, err) +- endSeqBlock, err := geth.WaitForBlock(endSeqBlockNumber, l2Seq, time.Minute) +- require.Nil(t, err) +- +- seqL1Info, err := bindings.NewL1Block(cfg.L1InfoPredeployAddress, l2Seq) +- require.Nil(t, err) +- +- verifL1Info, err := bindings.NewL1Block(cfg.L1InfoPredeployAddress, l2Verif) +- require.Nil(t, err) +- +- ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) +- defer cancel() +- +- fillInfoLists := func(start *types.Block, contract *bindings.L1Block, client *ethclient.Client) ([]*derive.L1BlockInfo, []*derive.L1BlockInfo) { +- var txList, stateList []*derive.L1BlockInfo +- for b := start; ; { +- var infoFromTx *derive.L1BlockInfo +- infoFromTx, err := derive.L1BlockInfoFromBytes(sys.RollupConfig, b.Time(), b.Transactions()[0].Data()) +- require.NoError(t, err) +- txList = append(txList, infoFromTx) +- +- ecotone := sys.RollupConfig.IsEcotone(b.Time()) && !sys.RollupConfig.IsEcotoneActivationBlock(b.Time()) +- infoFromState, err := L1InfoFromState(ctx, contract, b.Number(), ecotone) +- require.Nil(t, err) +- stateList = append(stateList, infoFromState) +- +- // Genesis L2 block contains no L1 Deposit TX +- if b.NumberU64() == 1 { +- return txList, stateList +- } +- b, err = client.BlockByHash(ctx, b.ParentHash()) +- require.Nil(t, err) +- } +- } +- +- l1InfosFromSequencerTransactions, l1InfosFromSequencerState := fillInfoLists(endSeqBlock, seqL1Info, l2Seq) +- l1InfosFromVerifierTransactions, l1InfosFromVerifierState := fillInfoLists(endVerifBlock, verifL1Info, l2Verif) +- +- l1blocks := make(map[common.Hash]*derive.L1BlockInfo) +- maxL1Hash := l1InfosFromSequencerTransactions[0].BlockHash +- for h := maxL1Hash; ; { +- b, err := l1Client.BlockByHash(ctx, h) +- require.Nil(t, err) +- +- l1blocks[h] = &derive.L1BlockInfo{ +- Number: b.NumberU64(), +- Time: b.Time(), +- BaseFee: b.BaseFee(), +- BlockHash: h, +- SequenceNumber: 0, // ignored, will be overwritten +- BatcherAddr: sys.RollupConfig.Genesis.SystemConfig.BatcherAddr, +- } +- if sys.RollupConfig.IsEcotone(b.Time()) && !sys.RollupConfig.IsEcotoneActivationBlock(b.Time()) { +- scalars, err := sys.RollupConfig.Genesis.SystemConfig.EcotoneScalars() +- require.NoError(t, err) +- l1blocks[h].BlobBaseFeeScalar = scalars.BlobBaseFeeScalar +- l1blocks[h].BaseFeeScalar = scalars.BaseFeeScalar +- if excess := b.ExcessBlobGas(); excess != nil { +- l1blocks[h].BlobBaseFee = eip4844.CalcBlobFee(*excess) +- } else { +- l1blocks[h].BlobBaseFee = big.NewInt(1) +- } +- } else { +- l1blocks[h].L1FeeOverhead = sys.RollupConfig.Genesis.SystemConfig.Overhead +- l1blocks[h].L1FeeScalar = sys.RollupConfig.Genesis.SystemConfig.Scalar +- } +- +- h = b.ParentHash() +- if b.NumberU64() == 0 { +- break +- } +- } +- +- checkInfoList := func(name string, list []*derive.L1BlockInfo) { +- for _, info := range list { +- if expected, ok := l1blocks[info.BlockHash]; ok { +- expected.SequenceNumber = info.SequenceNumber // the seq nr is not part of the L1 info we know in advance, so we ignore it. +- require.Equal(t, expected, info) +- } else { +- t.Fatalf("Did not find block hash for L1 Info: %v in test %s", info, name) +- } +- } +- } +- +- checkInfoList("On sequencer with tx", l1InfosFromSequencerTransactions) +- checkInfoList("On sequencer with state", l1InfosFromSequencerState) +- checkInfoList("On verifier with tx", l1InfosFromVerifierTransactions) +- checkInfoList("On verifier with state", l1InfosFromVerifierState) +-} +- +-// TestWithdrawals checks that a deposit and then withdrawal execution succeeds. It verifies the +-// balance changes on L1 and L2 and has to include gas fees in the balance checks. +-// It does not check that the withdrawal can be executed prior to the end of the finality period. +-func TestWithdrawals(t *testing.T) { +- InitParallel(t) +- +- cfg := DefaultSystemConfig(t) +- cfg.DeployConfig.FinalizationPeriodSeconds = 2 // 2s finalization period +- cfg.L1FinalizedDistance = 2 // Finalize quick, don't make the proposer wait too long +- +- sys, err := cfg.Start(t) +- require.NoError(t, err, "Error starting up system") +- +- RunWithdrawalsTest(t, sys) +-} +- +-type stateGetterAdapter struct { +- ctx context.Context +- t *testing.T +- client *ethclient.Client +- blockNum *big.Int +-} +- +-func (sga *stateGetterAdapter) GetState(addr common.Address, key common.Hash) common.Hash { +- sga.t.Helper() +- val, err := sga.client.StorageAt(sga.ctx, addr, key, sga.blockNum) +- require.NoError(sga.t, err) +- var res common.Hash +- copy(res[:], val) +- return res +-} +- +-// TestFees checks that L1/L2 fees are handled. +-func TestFees(t *testing.T) { +- t.Run("pre-regolith", func(t *testing.T) { +- InitParallel(t) +- cfg := RegolithSystemConfig(t, nil) +- cfg.DeployConfig.L1GenesisBlockBaseFeePerGas = (*hexutil.Big)(big.NewInt(7)) +- +- testFees(t, cfg) +- }) +- t.Run("regolith", func(t *testing.T) { +- InitParallel(t) +- cfg := RegolithSystemConfig(t, &genesisTime) +- cfg.DeployConfig.L1GenesisBlockBaseFeePerGas = (*hexutil.Big)(big.NewInt(7)) +- +- testFees(t, cfg) +- }) +- t.Run("ecotone", func(t *testing.T) { +- InitParallel(t) +- cfg := EcotoneSystemConfig(t, &genesisTime) +- cfg.DeployConfig.L1GenesisBlockBaseFeePerGas = (*hexutil.Big)(big.NewInt(7)) +- +- testFees(t, cfg) +- }) +- t.Run("fjord", func(t *testing.T) { +- InitParallel(t) +- cfg := DefaultSystemConfig(t) +- cfg.DeployConfig.L1GenesisBlockBaseFeePerGas = (*hexutil.Big)(big.NewInt(7)) +- +- cfg.DeployConfig.L2GenesisRegolithTimeOffset = new(hexutil.Uint64) +- cfg.DeployConfig.L2GenesisCanyonTimeOffset = new(hexutil.Uint64) +- cfg.DeployConfig.L2GenesisDeltaTimeOffset = new(hexutil.Uint64) +- cfg.DeployConfig.L2GenesisEcotoneTimeOffset = new(hexutil.Uint64) +- cfg.DeployConfig.L2GenesisFjordTimeOffset = new(hexutil.Uint64) +- testFees(t, cfg) +- }) +-} +- +-func testFees(t *testing.T, cfg SystemConfig) { +- sys, err := cfg.Start(t) +- require.Nil(t, err, "Error starting up system") +- +- l2Seq := sys.NodeClient("sequencer") +- l2Verif := sys.NodeClient("verifier") +- l1 := sys.NodeClient("l1") +- +- // Wait for first block after genesis. The genesis block has zero L1Block values and will throw off the GPO checks +- _, err = geth.WaitForBlock(big.NewInt(1), l2Verif, time.Minute) +- require.NoError(t, err) +- +- config := sys.L2Genesis().Config +- +- sga := &stateGetterAdapter{ +- ctx: context.Background(), +- t: t, +- client: l2Seq, +- } +- +- l1CostFn := types.NewL1CostFunc(config, sga) +- +- // Transactor Account +- ethPrivKey := cfg.Secrets.Alice +- fromAddr := crypto.PubkeyToAddress(ethPrivKey.PublicKey) +- +- require.NotEqual(t, cfg.DeployConfig.L2OutputOracleProposer, fromAddr) +- require.NotEqual(t, cfg.DeployConfig.BatchSenderAddress, fromAddr) +- +- // Find gaspriceoracle contract +- gpoContract, err := bindings.NewGasPriceOracle(predeploys.GasPriceOracleAddr, l2Seq) +- require.Nil(t, err) +- +- if !sys.RollupConfig.IsEcotone(sys.L2GenesisCfg.Timestamp) { +- overhead, err := gpoContract.Overhead(&bind.CallOpts{}) +- require.Nil(t, err, "reading gpo overhead") +- require.Equal(t, overhead.Uint64(), cfg.DeployConfig.GasPriceOracleOverhead, "wrong gpo overhead") +- +- scalar, err := gpoContract.Scalar(&bind.CallOpts{}) +- require.Nil(t, err, "reading gpo scalar") +- feeScalar := cfg.DeployConfig.FeeScalar() +- require.Equal(t, scalar, new(big.Int).SetBytes(feeScalar[:]), "wrong gpo scalar") +- } else { +- _, err := gpoContract.Overhead(&bind.CallOpts{}) +- require.ErrorContains(t, err, "deprecated") +- _, err = gpoContract.Scalar(&bind.CallOpts{}) +- require.ErrorContains(t, err, "deprecated") +- } +- +- decimals, err := gpoContract.Decimals(&bind.CallOpts{}) +- require.Nil(t, err, "reading gpo decimals") +- +- require.Equal(t, decimals.Uint64(), uint64(6), "wrong gpo decimals") +- +- // BaseFee Recipient +- baseFeeRecipientStartBalance, err := l2Seq.BalanceAt(context.Background(), predeploys.BaseFeeVaultAddr, big.NewInt(rpc.EarliestBlockNumber.Int64())) +- require.Nil(t, err) +- +- // L1Fee Recipient +- l1FeeRecipientStartBalance, err := l2Seq.BalanceAt(context.Background(), predeploys.L1FeeVaultAddr, big.NewInt(rpc.EarliestBlockNumber.Int64())) +- require.Nil(t, err) +- +- sequencerFeeVaultStartBalance, err := l2Seq.BalanceAt(context.Background(), predeploys.SequencerFeeVaultAddr, big.NewInt(rpc.EarliestBlockNumber.Int64())) +- require.Nil(t, err) +- +- genesisBlock, err := l2Seq.BlockByNumber(context.Background(), big.NewInt(rpc.EarliestBlockNumber.Int64())) +- require.NoError(t, err) +- +- coinbaseStartBalance, err := l2Seq.BalanceAt(context.Background(), genesisBlock.Coinbase(), big.NewInt(rpc.EarliestBlockNumber.Int64())) +- require.NoError(t, err) +- +- // Simple transfer from signer to random account +- startBalance, err := l2Seq.BalanceAt(context.Background(), fromAddr, big.NewInt(rpc.EarliestBlockNumber.Int64())) +- require.Nil(t, err) +- require.Greater(t, startBalance.Uint64(), big.NewInt(params.Ether).Uint64()) +- +- transferAmount := big.NewInt(params.Ether) +- gasTip := big.NewInt(10) +- receipt := SendL2Tx(t, cfg, l2Seq, ethPrivKey, func(opts *TxOpts) { +- opts.ToAddr = &common.Address{0xff, 0xff} +- opts.Value = transferAmount +- opts.GasTipCap = gasTip +- opts.Gas = 21000 +- opts.GasFeeCap = big.NewInt(200) +- opts.VerifyOnClients(l2Verif) +- }) +- +- require.Equal(t, receipt.Status, types.ReceiptStatusSuccessful) +- +- header, err := l2Seq.HeaderByNumber(context.Background(), receipt.BlockNumber) +- require.Nil(t, err) +- +- coinbaseEndBalance, err := l2Seq.BalanceAt(context.Background(), header.Coinbase, header.Number) +- require.Nil(t, err) +- +- endBalance, err := l2Seq.BalanceAt(context.Background(), fromAddr, header.Number) +- require.Nil(t, err) +- +- baseFeeRecipientEndBalance, err := l2Seq.BalanceAt(context.Background(), predeploys.BaseFeeVaultAddr, header.Number) +- require.Nil(t, err) +- +- l1Header, err := l1.HeaderByNumber(context.Background(), nil) +- require.Nil(t, err) +- +- l1FeeRecipientEndBalance, err := l2Seq.BalanceAt(context.Background(), predeploys.L1FeeVaultAddr, header.Number) +- require.Nil(t, err) +- +- sequencerFeeVaultEndBalance, err := l2Seq.BalanceAt(context.Background(), predeploys.SequencerFeeVaultAddr, header.Number) +- require.Nil(t, err) +- +- // Diff fee recipient + coinbase balances +- baseFeeRecipientDiff := new(big.Int).Sub(baseFeeRecipientEndBalance, baseFeeRecipientStartBalance) +- l1FeeRecipientDiff := new(big.Int).Sub(l1FeeRecipientEndBalance, l1FeeRecipientStartBalance) +- sequencerFeeVaultDiff := new(big.Int).Sub(sequencerFeeVaultEndBalance, sequencerFeeVaultStartBalance) +- coinbaseDiff := new(big.Int).Sub(coinbaseEndBalance, coinbaseStartBalance) +- +- // Tally L2 Fee +- l2Fee := gasTip.Mul(gasTip, new(big.Int).SetUint64(receipt.GasUsed)) +- require.Equal(t, sequencerFeeVaultDiff, coinbaseDiff, "coinbase is always sequencer fee vault") +- require.Equal(t, l2Fee, coinbaseDiff, "l2 fee mismatch") +- require.Equal(t, l2Fee, sequencerFeeVaultDiff) +- +- // Tally BaseFee +- baseFee := new(big.Int).Mul(header.BaseFee, new(big.Int).SetUint64(receipt.GasUsed)) +- require.Equal(t, baseFee, baseFeeRecipientDiff, "base fee mismatch") +- +- // Tally L1 Fee +- tx, _, err := l2Seq.TransactionByHash(context.Background(), receipt.TxHash) +- require.NoError(t, err, "Should be able to get transaction") +- bytes, err := tx.MarshalBinary() +- require.Nil(t, err) +- +- l1Fee := l1CostFn(tx.RollupCostData(), header.Time) +- require.Equalf(t, l1Fee, l1FeeRecipientDiff, "L1 fee mismatch: start balance %v, end balance %v", l1FeeRecipientStartBalance, l1FeeRecipientEndBalance) +- +- gpoEcotone, err := gpoContract.IsEcotone(nil) +- require.NoError(t, err) +- require.Equal(t, sys.RollupConfig.IsEcotone(header.Time), gpoEcotone, "GPO and chain must have same ecotone view") +- +- gpoFjord, err := gpoContract.IsFjord(nil) +- require.NoError(t, err) +- require.Equal(t, sys.RollupConfig.IsFjord(header.Time), gpoFjord, "GPO and chain must have same fjord view") +- +- gpoL1Fee, err := gpoContract.GetL1Fee(&bind.CallOpts{}, bytes) +- require.Nil(t, err) +- +- adjustedGPOFee := gpoL1Fee +- if sys.RollupConfig.IsFjord(header.Time) { +- // The fastlz size of the transaction is 102 bytes +- require.Equal(t, uint64(102), tx.RollupCostData().FastLzSize) +- // Which results in both the fjord cost function and GPO using the minimum value for the fastlz regression: +- // Geth Linear Regression: -42.5856 + 102 * 0.8365 = 42.7374 +- // GPO Linear Regression: -42.5856 + 170 * 0.8365 = 99.6194 +- // The additional 68 (170 vs. 102) is due to the GPO adding 68 bytes to account for the signature. +- require.Greater(t, types.MinTransactionSize.Uint64(), uint64(99)) +- // Because of this, we don't need to do any adjustment as the GPO and cost func are both bounded to the minimum value. +- // However, if the fastlz regression output is ever larger than the minimum, this will require an adjustment. +- } else if sys.RollupConfig.IsRegolith(header.Time) { +- // if post-regolith, adjust the GPO fee by removing the overhead it adds because of signature data +- artificialGPOOverhead := big.NewInt(68 * 16) // it adds 68 bytes to cover signature and RLP data +- l1BaseFee := big.NewInt(7) // we assume the L1 basefee is the minimum, 7 +- // in our case we already include that, so we subtract it, to do a 1:1 comparison +- adjustedGPOFee = new(big.Int).Sub(gpoL1Fee, new(big.Int).Mul(artificialGPOOverhead, l1BaseFee)) +- } +- require.Equal(t, l1Fee, adjustedGPOFee, "GPO reports L1 fee mismatch") +- +- require.Equal(t, receipt.L1Fee, l1Fee, "l1 fee in receipt is correct") +- if !sys.RollupConfig.IsEcotone(header.Time) { // FeeScalar receipt attribute is removed as of Ecotone +- require.Equal(t, +- new(big.Float).Mul( +- new(big.Float).SetInt(l1Header.BaseFee), +- new(big.Float).Mul(new(big.Float).SetInt(receipt.L1GasUsed), receipt.FeeScalar), +- ), +- new(big.Float).SetInt(receipt.L1Fee), "fee field in receipt matches gas used times scalar times base fee") +- } +- +- // Calculate total fee +- baseFeeRecipientDiff.Add(baseFeeRecipientDiff, coinbaseDiff) +- totalFee := new(big.Int).Add(baseFeeRecipientDiff, l1FeeRecipientDiff) +- balanceDiff := new(big.Int).Sub(startBalance, endBalance) +- balanceDiff.Sub(balanceDiff, transferAmount) +- require.Equal(t, balanceDiff, totalFee, "balances should add up") +-} +- +-func StopStartBatcher(t *testing.T, cfgMod func(*SystemConfig)) { +- InitParallel(t) +- +- cfg := DefaultSystemConfig(t) +- cfgMod(&cfg) +- sys, err := cfg.Start(t) +- require.NoError(t, err, "Error starting up system") +- +- rollupClient := sys.RollupClient("verifier") +- +- l2Seq := sys.NodeClient("sequencer") +- l2Verif := sys.NodeClient("verifier") +- +- // retrieve the initial sync status +- seqStatus, err := rollupClient.SyncStatus(context.Background()) +- require.NoError(t, err) +- +- nonce := uint64(0) +- sendTx := func() *types.Receipt { +- // Submit TX to L2 sequencer node +- receipt := SendL2Tx(t, cfg, l2Seq, cfg.Secrets.Alice, func(opts *TxOpts) { +- opts.ToAddr = &common.Address{0xff, 0xff} +- opts.Value = big.NewInt(1_000_000_000) +- opts.Nonce = nonce +- }) +- nonce++ +- return receipt +- } +- // send a transaction +- receipt := sendTx() +- +- // wait until the block the tx was first included in shows up in the safe chain on the verifier +- safeBlockInclusionDuration := time.Duration(6*cfg.DeployConfig.L1BlockTime) * time.Second +- _, err = geth.WaitForBlock(receipt.BlockNumber, l2Verif, safeBlockInclusionDuration) +- require.NoError(t, err, "Waiting for block on verifier") +- require.NoError(t, wait.ForProcessingFullBatch(context.Background(), rollupClient)) +- +- // ensure the safe chain advances +- newSeqStatus, err := rollupClient.SyncStatus(context.Background()) +- require.NoError(t, err) +- require.Greater(t, newSeqStatus.SafeL2.Number, seqStatus.SafeL2.Number, "Safe chain did not advance") +- +- driver := sys.BatchSubmitter.TestDriver() +- // stop the batch submission +- err = driver.StopBatchSubmitting(context.Background()) +- require.NoError(t, err) +- +- // wait for any old safe blocks being submitted / derived +- time.Sleep(safeBlockInclusionDuration) +- +- // get the initial sync status +- seqStatus, err = rollupClient.SyncStatus(context.Background()) +- require.NoError(t, err) +- +- // send another tx +- sendTx() +- time.Sleep(safeBlockInclusionDuration) +- +- // ensure that the safe chain does not advance while the batcher is stopped +- newSeqStatus, err = rollupClient.SyncStatus(context.Background()) +- require.NoError(t, err) +- require.Equal(t, newSeqStatus.SafeL2.Number, seqStatus.SafeL2.Number, "Safe chain advanced while batcher was stopped") +- +- // start the batch submission +- err = driver.StartBatchSubmitting() +- require.NoError(t, err) +- time.Sleep(safeBlockInclusionDuration) +- +- // send a third tx +- receipt = sendTx() +- +- // wait until the block the tx was first included in shows up in the safe chain on the verifier +- _, err = geth.WaitForBlock(receipt.BlockNumber, l2Verif, safeBlockInclusionDuration) +- require.NoError(t, err, "Waiting for block on verifier") +- require.NoError(t, wait.ForProcessingFullBatch(context.Background(), rollupClient)) +- +- // ensure that the safe chain advances after restarting the batcher +- newSeqStatus, err = rollupClient.SyncStatus(context.Background()) +- require.NoError(t, err) +- require.Greater(t, newSeqStatus.SafeL2.Number, seqStatus.SafeL2.Number, "Safe chain did not advance after batcher was restarted") +-} +- +-func TestBatcherMultiTx(t *testing.T) { +- InitParallel(t) +- +- cfg := DefaultSystemConfig(t) +- cfg.MaxPendingTransactions = 0 // no limit on parallel txs +- // ensures that batcher txs are as small as possible +- cfg.BatcherMaxL1TxSizeBytes = derive.FrameV0OverHeadSize + 1 /*version bytes*/ + 1 +- cfg.DisableBatcher = true +- sys, err := cfg.Start(t) +- require.NoError(t, err, "Error starting up system") +- +- l1Client := sys.NodeClient("l1") +- l2Seq := sys.NodeClient("sequencer") +- +- _, err = geth.WaitForBlock(big.NewInt(10), l2Seq, time.Duration(cfg.DeployConfig.L2BlockTime*15)*time.Second) +- require.NoError(t, err, "Waiting for L2 blocks") +- +- ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) +- defer cancel() +- l1Number, err := l1Client.BlockNumber(ctx) +- require.NoError(t, err) +- +- // start batch submission +- driver := sys.BatchSubmitter.TestDriver() +- err = driver.StartBatchSubmitting() +- require.NoError(t, err) +- +- totalTxCount := 0 +- // wait for up to 10 L1 blocks, usually only 3 is required, but it's +- // possible additional L1 blocks will be created before the batcher starts, +- // so we wait additional blocks. +- for i := int64(0); i < 10; i++ { +- block, err := geth.WaitForBlock(big.NewInt(int64(l1Number)+i), l1Client, time.Duration(cfg.DeployConfig.L1BlockTime*5)*time.Second) +- require.NoError(t, err, "Waiting for l1 blocks") +- totalTxCount += len(block.Transactions()) +- +- if totalTxCount >= 10 { +- return +- } +- } +- +- t.Fatal("Expected at least 10 transactions from the batcher") +-} +- +-func latestBlock(t *testing.T, client *ethclient.Client) uint64 { +- ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) +- defer cancel() +- blockAfter, err := client.BlockNumber(ctx) +- require.Nil(t, err, "Error getting latest block") +- return blockAfter +-} +- +-// TestPendingBlockIsLatest tests that we serve the latest block as pending block +-func TestPendingBlockIsLatest(t *testing.T) { +- InitParallel(t) +- +- cfg := DefaultSystemConfig(t) +- sys, err := cfg.Start(t) +- require.Nil(t, err, "Error starting up system") +- +- l2Seq := sys.NodeClient("sequencer") +- +- t.Run("block", func(t *testing.T) { +- for i := 0; i < 10; i++ { +- // TODO(CLI-4044): pending-block ID change +- pending, err := l2Seq.BlockByNumber(context.Background(), big.NewInt(-1)) +- require.NoError(t, err) +- latest, err := l2Seq.BlockByNumber(context.Background(), nil) +- require.NoError(t, err) +- if pending.NumberU64() == latest.NumberU64() { +- require.Equal(t, pending.Hash(), latest.Hash(), "pending must exactly match latest block") +- return +- } +- // re-try until we have the same number, as the requests are not an atomic bundle, and the sequencer may create a block. +- } +- t.Fatal("failed to get pending block with same number as latest block") +- }) +- t.Run("header", func(t *testing.T) { +- for i := 0; i < 10; i++ { +- // TODO(CLI-4044): pending-block ID change +- pending, err := l2Seq.HeaderByNumber(context.Background(), big.NewInt(-1)) +- require.NoError(t, err) +- latest, err := l2Seq.HeaderByNumber(context.Background(), nil) +- require.NoError(t, err) +- if pending.Number.Uint64() == latest.Number.Uint64() { +- require.Equal(t, pending.Hash(), latest.Hash(), "pending must exactly match latest header") +- return +- } +- // re-try until we have the same number, as the requests are not an atomic bundle, and the sequencer may create a block. +- } +- t.Fatal("failed to get pending header with same number as latest header") +- }) +-} +- +-func TestRuntimeConfigReload(t *testing.T) { +- InitParallel(t) +- +- cfg := DefaultSystemConfig(t) +- // to speed up the test, make it reload the config more often, and do not impose a long conf depth +- cfg.Nodes["verifier"].RuntimeConfigReloadInterval = time.Second * 5 +- cfg.Nodes["verifier"].Driver.VerifierConfDepth = 1 +- +- sys, err := cfg.Start(t) +- require.Nil(t, err, "Error starting up system") +- +- initialRuntimeConfig := sys.RollupNodes["verifier"].RuntimeConfig() +- +- // close the EL node, since we want to block derivation, to solely rely on the reloading mechanism for updates. +- sys.EthInstances["verifier"].Close() +- +- l1 := sys.NodeClient("l1") +- +- // Change the system-config via L1 +- sysCfgContract, err := bindings.NewSystemConfig(cfg.L1Deployments.SystemConfigProxy, l1) +- require.NoError(t, err) +- newUnsafeBlocksSigner := common.Address{0x12, 0x23, 0x45} +- require.NotEqual(t, initialRuntimeConfig.P2PSequencerAddress(), newUnsafeBlocksSigner, "changing to a different address") +- opts, err := bind.NewKeyedTransactorWithChainID(cfg.Secrets.SysCfgOwner, cfg.L1ChainIDBig()) +- require.Nil(t, err) +- // the unsafe signer address is part of the runtime config +- tx, err := sysCfgContract.SetUnsafeBlockSigner(opts, newUnsafeBlocksSigner) +- require.NoError(t, err) +- +- // wait for the change to confirm +- _, err = wait.ForReceiptOK(context.Background(), l1, tx.Hash()) +- require.NoError(t, err) +- +- // wait for the address to change +- _, err = retry.Do(context.Background(), 10, retry.Fixed(time.Second*10), func() (struct{}, error) { +- v := sys.RollupNodes["verifier"].RuntimeConfig().P2PSequencerAddress() +- if v == newUnsafeBlocksSigner { +- return struct{}{}, nil +- } +- return struct{}{}, fmt.Errorf("no change yet, seeing %s but looking for %s", v, newUnsafeBlocksSigner) +- }) +- require.NoError(t, err) +-} +- +-func TestRecommendedProtocolVersionChange(t *testing.T) { +- InitParallel(t) +- +- cfg := DefaultSystemConfig(t) +- require.NotEqual(t, common.Address{}, cfg.L1Deployments.ProtocolVersions, "need ProtocolVersions contract deployment") +- // to speed up the test, make it reload the config more often, and do not impose a long conf depth +- cfg.Nodes["verifier"].RuntimeConfigReloadInterval = time.Second * 5 +- cfg.Nodes["verifier"].Driver.VerifierConfDepth = 1 +- +- sys, err := cfg.Start(t) +- require.Nil(t, err, "Error starting up system") +- +- runtimeConfig := sys.RollupNodes["verifier"].RuntimeConfig() +- +- // Change the superchain-config via L1 +- l1 := sys.NodeClient("l1") +- +- _, build, major, minor, patch, preRelease := params.OPStackSupport.Parse() +- newRecommendedProtocolVersion := params.ProtocolVersionV0{Build: build, Major: major + 1, Minor: minor, Patch: patch, PreRelease: preRelease}.Encode() +- require.NotEqual(t, runtimeConfig.RecommendedProtocolVersion(), newRecommendedProtocolVersion, "changing to a different protocol version") +- +- protVersions, err := bindings.NewProtocolVersions(cfg.L1Deployments.ProtocolVersionsProxy, l1) +- require.NoError(t, err) +- +- // ProtocolVersions contract is owned by same key as SystemConfig in devnet +- opts, err := bind.NewKeyedTransactorWithChainID(cfg.Secrets.SysCfgOwner, cfg.L1ChainIDBig()) +- require.NoError(t, err) +- +- // Change recommended protocol version +- tx, err := protVersions.SetRecommended(opts, new(big.Int).SetBytes(newRecommendedProtocolVersion[:])) +- require.NoError(t, err) +- +- // wait for the change to confirm +- _, err = wait.ForReceiptOK(context.Background(), l1, tx.Hash()) +- require.NoError(t, err) +- +- // wait for the recommended protocol version to change +- _, err = retry.Do(context.Background(), 10, retry.Fixed(time.Second*10), func() (struct{}, error) { +- v := sys.RollupNodes["verifier"].RuntimeConfig().RecommendedProtocolVersion() +- if v == newRecommendedProtocolVersion { +- return struct{}{}, nil +- } +- return struct{}{}, fmt.Errorf("no change yet, seeing %s but looking for %s", v, newRecommendedProtocolVersion) +- }) +- require.NoError(t, err) +-} +- +-func TestRequiredProtocolVersionChangeAndHalt(t *testing.T) { +- InitParallel(t) +- +- cfg := DefaultSystemConfig(t) +- // to speed up the test, make it reload the config more often, and do not impose a long conf depth +- cfg.Nodes["verifier"].RuntimeConfigReloadInterval = time.Second * 5 +- cfg.Nodes["verifier"].Driver.VerifierConfDepth = 1 +- // configure halt in verifier op-node +- cfg.Nodes["verifier"].RollupHalt = "major" +- // configure halt in verifier op-geth node +- cfg.GethOptions["verifier"] = append(cfg.GethOptions["verifier"], []geth.GethOption{ +- func(ethCfg *ethconfig.Config, nodeCfg *node.Config) error { +- ethCfg.RollupHaltOnIncompatibleProtocolVersion = "major" +- return nil +- }, +- }...) +- +- sys, err := cfg.Start(t) +- require.Nil(t, err, "Error starting up system") +- +- runtimeConfig := sys.RollupNodes["verifier"].RuntimeConfig() +- +- // Change the superchain-config via L1 +- l1 := sys.NodeClient("l1") +- +- _, build, major, minor, patch, preRelease := params.OPStackSupport.Parse() +- newRequiredProtocolVersion := params.ProtocolVersionV0{Build: build, Major: major + 1, Minor: minor, Patch: patch, PreRelease: preRelease}.Encode() +- require.NotEqual(t, runtimeConfig.RequiredProtocolVersion(), newRequiredProtocolVersion, "changing to a different protocol version") +- +- protVersions, err := bindings.NewProtocolVersions(cfg.L1Deployments.ProtocolVersionsProxy, l1) +- require.NoError(t, err) +- +- // ProtocolVersions contract is owned by same key as SystemConfig in devnet +- opts, err := bind.NewKeyedTransactorWithChainID(cfg.Secrets.SysCfgOwner, cfg.L1ChainIDBig()) +- require.NoError(t, err) +- +- // Change required protocol version +- tx, err := protVersions.SetRequired(opts, new(big.Int).SetBytes(newRequiredProtocolVersion[:])) +- require.NoError(t, err) +- +- // wait for the change to confirm +- _, err = wait.ForReceiptOK(context.Background(), l1, tx.Hash()) +- require.NoError(t, err) +- +- // wait for the required protocol version to take effect by halting the verifier that opted in, and halting the op-geth node that opted in. +- _, err = retry.Do(context.Background(), 10, retry.Fixed(time.Second*10), func() (struct{}, error) { +- if !sys.RollupNodes["verifier"].Stopped() { +- return struct{}{}, errors.New("verifier rollup node is not closed yet") +- } +- return struct{}{}, nil +- }) +- require.NoError(t, err) +- t.Log("verified that op-node closed!") +- // Checking if the engine is down is not trivial in op-e2e. +- // In op-geth we have halting tests covering the Engine API, in op-e2e we instead check if the API stops. +- _, err = retry.Do(context.Background(), 10, retry.Fixed(time.Second*10), func() (struct{}, error) { +- ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) +- defer cancel() +- available := client.IsURLAvailable(ctx, sys.NodeEndpoint("verifier").(endpoint.HttpRPC).HttpRPC()) +- if !available && ctx.Err() == nil { // waiting for client to stop responding to RPC requests (slow dials with timeout don't count) +- return struct{}{}, nil +- } +- return struct{}{}, errors.New("verifier EL node is not closed yet") +- }) +- require.NoError(t, err) +- t.Log("verified that op-geth closed!") +-}
+
+ + + +
+
+ +
+
+
+ + +
+ +
+
+
+ + +
+
+ +
+
+
+ + +
+ +
+
+
+ +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+4
+
-3
+ +
+ +
+
+
diff --git OP/op-node/benchmarks/batchbuilding_test.go CELO/op-node/benchmarks/batchbuilding_test.go +index 54690eabb152d90f32385ff23f63fe8eab5f05d2..57a5382d749b4f2a167021aa68c83030b2040339 100644 +--- OP/op-node/benchmarks/batchbuilding_test.go ++++ CELO/op-node/benchmarks/batchbuilding_test.go +@@ -87,15 +87,16 @@ ) +  + // channelOutByType returns a channel out of the given type as a helper for the benchmarks + func channelOutByType(b *testing.B, batchType uint, cd compressorDetails) (derive.ChannelOut, error) { +- chainID := big.NewInt(333) +- rollupConfig := new(rollup.Config) ++ rollupConfig := &rollup.Config{ ++ L2ChainID: big.NewInt(333), ++ } + if batchType == derive.SingularBatchType { + compressor, err := cd.Compressor() + require.NoError(b, err) + return derive.NewSingularChannelOut(compressor, rollup.NewChainSpec(rollupConfig)) + } + if batchType == derive.SpanBatchType { +- return derive.NewSpanChannelOut(0, chainID, cd.config.TargetOutputSize, cd.config.CompressionAlgo, rollup.NewChainSpec(rollupConfig)) ++ return derive.NewSpanChannelOut(cd.config.TargetOutputSize, cd.config.CompressionAlgo, rollup.NewChainSpec(rollupConfig)) + } + return nil, fmt.Errorf("unsupported batch type: %d", batchType) + }
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+6
+
-5
+ +
+ +
+
+
diff --git OP/op-node/cmd/genesis/cmd.go CELO/op-node/cmd/genesis/cmd.go +index 6d11fd8e7f5ee45952dddf1360179343d2e5a1c4..054f29310619d326e1599363924287ff625cdf41 100644 +--- OP/op-node/cmd/genesis/cmd.go ++++ CELO/op-node/cmd/genesis/cmd.go +@@ -5,6 +5,7 @@ "errors" + "fmt" + "time" +  ++ "github.com/ethereum-optimism/optimism/op-service/ioutil" + "github.com/ethereum-optimism/optimism/op-service/retry" + "github.com/ethereum-optimism/optimism/op-service/sources/batching" + "github.com/urfave/cli/v2" +@@ -120,7 +121,7 @@ if err != nil { + return err + } +  +- return jsonutil.WriteJSON(ctx.String(outfileL1Flag.Name), l1Genesis, 0o666) ++ return jsonutil.WriteJSON(l1Genesis, ioutil.ToStdOutOrFileOrNoop(ctx.String(outfileL1Flag.Name), 0o666)) + }, + }, + { +@@ -190,13 +191,13 @@ return err + } +  + // Build the L2 genesis block +- l2Genesis, err := genesis.BuildL2Genesis(config, l2Allocs, l1StartBlock) ++ l2Genesis, err := genesis.BuildL2Genesis(config, l2Allocs, l1StartBlock.Header()) + if err != nil { + return fmt.Errorf("error creating l2 genesis: %w", err) + } +  + l2GenesisBlock := l2Genesis.ToBlock() +- rollupConfig, err := config.RollupConfig(l1StartBlock, l2GenesisBlock.Hash(), l2GenesisBlock.Number().Uint64()) ++ rollupConfig, err := config.RollupConfig(l1StartBlock.Header(), l2GenesisBlock.Hash(), l2GenesisBlock.Number().Uint64()) + if err != nil { + return err + } +@@ -204,10 +205,10 @@ if err := rollupConfig.Check(); err != nil { + return fmt.Errorf("generated rollup config does not pass validation: %w", err) + } +  +- if err := jsonutil.WriteJSON(ctx.String(outfileL2Flag.Name), l2Genesis, 0o666); err != nil { ++ if err := jsonutil.WriteJSON(l2Genesis, ioutil.ToAtomicFile(ctx.String(outfileL2Flag.Name), 0o666)); err != nil { + return err + } +- return jsonutil.WriteJSON(ctx.String(outfileRollupFlag.Name), rollupConfig, 0o666) ++ return jsonutil.WriteJSON(rollupConfig, ioutil.ToAtomicFile(ctx.String(outfileRollupFlag.Name), 0o666)) + }, + }, + }
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+17
+
-1
+ +
+ +
+
+
diff --git OP/op-node/flags/flags.go CELO/op-node/flags/flags.go +index b3af25d661433b5078d02861be604c1953dc4c67..6df7fea61db902e53f8fce8d4e1b0ec339b7546b 100644 +--- OP/op-node/flags/flags.go ++++ CELO/op-node/flags/flags.go +@@ -73,6 +73,13 @@ Required: false, + EnvVars: prefixEnvVars("L1_BEACON"), + Category: RollupCategory, + } ++ SupervisorAddr = &cli.StringFlag{ ++ Name: "supervisor", ++ Usage: "RPC address of interop supervisor service for cross-chain safety verification." + ++ "Applies only to Interop-enabled networks.", ++ Hidden: true, // hidden for now during early testing. ++ EnvVars: prefixEnvVars("SUPERVISOR"), ++ } + /* Optional Flags */ + BeaconHeader = &cli.StringFlag{ + Name: "l1.beacon-header", +@@ -229,6 +236,13 @@ EnvVars: prefixEnvVars("SEQUENCER_L1_CONFS"), + Value: 4, + Category: SequencerCategory, + } ++ SequencerUseFinalizedL1Flag = &cli.BoolFlag{ ++ Name: "sequencer.use-finalized", ++ Usage: "Enable use of only finalized L1 blocks as L1 origin. Overwrites the value of 'sequencer.l1-confs'.", ++ EnvVars: prefixEnvVars("SEQUENCER_USE_FINALIZED"), ++ Value: false, ++ Category: SequencerCategory, ++ } + L1EpochPollIntervalFlag = &cli.DurationFlag{ + Name: "l1.epoch-poll-interval", + Usage: "Poll interval for retrieving new L1 epoch updates such as safe and finalized block changes. Disabled if 0 or negative.", +@@ -252,7 +266,7 @@ } + MetricsAddrFlag = &cli.StringFlag{ + Name: "metrics.addr", + Usage: "Metrics listening address", +- Value: "0.0.0.0", // TODO(CLI-4159): Switch to 127.0.0.1 ++ Value: "0.0.0.0", // TODO: Switch to 127.0.0.1 + EnvVars: prefixEnvVars("METRICS_ADDR"), + Category: OperationsCategory, + } +@@ -374,6 +388,7 @@ L2EngineJWTSecret, + } +  + var optionalFlags = []cli.Flag{ ++ SupervisorAddr, + BeaconAddr, + BeaconHeader, + BeaconFallbackAddrs, +@@ -388,6 +403,7 @@ L1RPCRateLimit, + L1RPCMaxBatchSize, + L1RPCMaxConcurrency, + L1HTTPPollInterval, ++ SequencerUseFinalizedL1Flag, + VerifierL1Confs, + SequencerEnabledFlag, + SequencerStoppedFlag,
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+26
+
-0
+ +
+ +
+
+
diff --git OP/op-node/node/client.go CELO/op-node/node/client.go +index a1c4754616c53cbb18d7b0b85bebe00f29451879..a561a7678d24d0e8e64d99c5d25852481df84687 100644 +--- OP/op-node/node/client.go ++++ CELO/op-node/node/client.go +@@ -230,3 +230,29 @@ } + h.Add(s[0], s[1]) + return h, nil + } ++ ++type SupervisorEndpointSetup interface { ++ SupervisorClient(ctx context.Context, log log.Logger) (*sources.SupervisorClient, error) ++ Check() error ++} ++ ++type SupervisorEndpointConfig struct { ++ SupervisorAddr string ++} ++ ++var _ SupervisorEndpointSetup = (*SupervisorEndpointConfig)(nil) ++ ++func (cfg *SupervisorEndpointConfig) Check() error { ++ if cfg.SupervisorAddr == "" { ++ return errors.New("supervisor RPC address is not set") ++ } ++ return nil ++} ++ ++func (cfg *SupervisorEndpointConfig) SupervisorClient(ctx context.Context, log log.Logger) (*sources.SupervisorClient, error) { ++ cl, err := client.NewRPC(ctx, log, cfg.SupervisorAddr, client.WithLazyDial()) ++ if err != nil { ++ return nil, fmt.Errorf("failed to create supervisor RPC: %w", err) ++ } ++ return sources.NewSupervisorClient(cl), nil ++}
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+11
+
-1
+ +
+ +
+
+
diff --git OP/op-node/node/config.go CELO/op-node/node/config.go +index d52da967f14abf159df45674113df218aabc6e4c..a78b55853aa2586c040b84b01b93117c3767e10a 100644 +--- OP/op-node/node/config.go ++++ CELO/op-node/node/config.go +@@ -23,6 +23,8 @@ L2 L2EndpointSetup +  + Beacon L1BeaconEndpointSetup +  ++ Supervisor SupervisorEndpointSetup ++ + Driver driver.Config +  + Rollup rollup.Config +@@ -130,10 +132,18 @@ return fmt.Errorf("l2 endpoint config error: %w", err) + } + if cfg.Rollup.EcotoneTime != nil { + if cfg.Beacon == nil { +- return fmt.Errorf("the Ecotone upgrade is scheduled but no L1 Beacon API endpoint is configured") ++ return fmt.Errorf("the Ecotone upgrade is scheduled (timestamp = %d) but no L1 Beacon API endpoint is configured", *cfg.Rollup.EcotoneTime) + } + if err := cfg.Beacon.Check(); err != nil { + return fmt.Errorf("misconfigured L1 Beacon API endpoint: %w", err) ++ } ++ } ++ if cfg.Rollup.InteropTime != nil { ++ if cfg.Supervisor == nil { ++ return fmt.Errorf("the Interop upgrade is scheduled (timestamp = %d) but no supervisor RPC endpoint is configured", *cfg.Rollup.InteropTime) ++ } ++ if err := cfg.Supervisor.Check(); err != nil { ++ return fmt.Errorf("misconfigured supervisor RPC endpoint: %w", err) + } + } + if err := cfg.Rollup.Check(); err != nil {
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+54
+
-6
+ +
+ +
+
+
diff --git OP/op-node/node/node.go CELO/op-node/node/node.go +index c60121f7d16827477a3c1dec7b491341a95083cf..9d9f6a4343ac266930474f4761394016843f83b3 100644 +--- OP/op-node/node/node.go ++++ CELO/op-node/node/node.go +@@ -8,13 +8,11 @@ "io" + "sync/atomic" + "time" +  +- "github.com/ethereum-optimism/optimism/op-node/rollup/sequencing" +- + "github.com/hashicorp/go-multierror" + "github.com/libp2p/go-libp2p/core/peer" +  + "github.com/ethereum/go-ethereum" +- "github.com/ethereum/go-ethereum/event" ++ gethevent "github.com/ethereum/go-ethereum/event" + "github.com/ethereum/go-ethereum/log" +  + altda "github.com/ethereum-optimism/optimism/op-alt-da" +@@ -24,6 +22,8 @@ "github.com/ethereum-optimism/optimism/op-node/p2p" + "github.com/ethereum-optimism/optimism/op-node/rollup" + "github.com/ethereum-optimism/optimism/op-node/rollup/conductor" + "github.com/ethereum-optimism/optimism/op-node/rollup/driver" ++ "github.com/ethereum-optimism/optimism/op-node/rollup/event" ++ "github.com/ethereum-optimism/optimism/op-node/rollup/sequencing" + "github.com/ethereum-optimism/optimism/op-node/rollup/sync" + "github.com/ethereum-optimism/optimism/op-service/client" + "github.com/ethereum-optimism/optimism/op-service/eth" +@@ -52,6 +52,9 @@ l1HeadsSub ethereum.Subscription // Subscription to get L1 heads (automatically re-subscribes on error) + l1SafeSub ethereum.Subscription // Subscription to get L1 safe blocks, a.k.a. justified data (polling) + l1FinalizedSub ethereum.Subscription // Subscription to get L1 safe blocks, a.k.a. justified data (polling) +  ++ eventSys event.System ++ eventDrain event.Drainer ++ + l1Source *sources.L1Client // L1 Client to fetch data from + l2Driver *driver.Driver // L2 Engine to Sync + l2Source *sources.EngineClient // L2 Execution Engine RPC bindings +@@ -69,6 +72,8 @@ pprofService *oppprof.Service + metricsSrv *httputil.HTTPServer +  + beacon *sources.L1BeaconClient ++ ++ supervisor *sources.SupervisorClient +  + // some resources cannot be stopped directly, like the p2p gossipsub router (not our design), + // and depend on this ctx to be closed. +@@ -124,6 +129,7 @@ n.log.Info("Initializing rollup node", "version", n.appVersion) + if err := n.initTracer(ctx, cfg); err != nil { + return fmt.Errorf("failed to init the trace: %w", err) + } ++ n.initEventSystem() + if err := n.initL1(ctx, cfg); err != nil { + return fmt.Errorf("failed to init L1: %w", err) + } +@@ -157,6 +163,16 @@ } + return nil + } +  ++func (n *OpNode) initEventSystem() { ++ // This executor will be configurable in the future, for parallel event processing ++ executor := event.NewGlobalSynchronous(n.resourcesCtx) ++ sys := event.NewSystem(n.log, executor) ++ sys.AddTracer(event.NewMetricsTracer(n.metrics)) ++ sys.Register("node", event.DeriverFunc(n.onEvent), event.DefaultRegisterOpts()) ++ n.eventSys = sys ++ n.eventDrain = executor ++} ++ + func (n *OpNode) initTracer(ctx context.Context, cfg *Config) error { + if cfg.Tracer != nil { + n.tracer = cfg.Tracer +@@ -183,7 +199,7 @@ return fmt.Errorf("failed to validate the L1 config: %w", err) + } +  + // Keep subscribed to the L1 heads, which keeps the L1 maintainer pointing to the best headers to sync +- n.l1HeadsSub = event.ResubscribeErr(time.Second*10, func(ctx context.Context, err error) (event.Subscription, error) { ++ n.l1HeadsSub = gethevent.ResubscribeErr(time.Second*10, func(ctx context.Context, err error) (gethevent.Subscription, error) { + if err != nil { + n.log.Warn("resubscribing after failed L1 subscription", "err", err) + } +@@ -379,6 +395,14 @@ if err := cfg.Rollup.ValidateL2Config(ctx, n.l2Source, cfg.Sync.SyncMode == sync.ELSync); err != nil { + return err + } +  ++ if cfg.Rollup.InteropTime != nil { ++ cl, err := cfg.Supervisor.SupervisorClient(ctx, n.log) ++ if err != nil { ++ return fmt.Errorf("failed to setup supervisor RPC client: %w", err) ++ } ++ n.supervisor = cl ++ } ++ + var sequencerConductor conductor.SequencerConductor = &conductor.NoOpConductor{} + if cfg.ConductorEnabled { + sequencerConductor = NewConductorClient(cfg, n.log, n.metrics) +@@ -400,7 +424,8 @@ n.safeDB = safeDB + } else { + n.safeDB = safedb.Disabled + } +- n.l2Driver = driver.NewDriver(&cfg.Driver, &cfg.Rollup, n.l2Source, n.l1Source, n.beacon, n, n, n.log, n.metrics, cfg.ConfigPersistence, n.safeDB, &cfg.Sync, sequencerConductor, altDA) ++ n.l2Driver = driver.NewDriver(n.eventSys, n.eventDrain, &cfg.Driver, &cfg.Rollup, n.l2Source, n.l1Source, ++ n.supervisor, n.beacon, n, n, n.log, n.metrics, cfg.ConfigPersistence, n.safeDB, &cfg.Sync, sequencerConductor, altDA) + return nil + } +  +@@ -465,7 +490,7 @@ if n.p2pNode != nil { + panic("p2p node already initialized") + } + if n.p2pEnabled() { +- // TODO(protocol-quest/97): Use EL Sync instead of CL Alt sync for fetching missing blocks in the payload queue. ++ // TODO(protocol-quest#97): Use EL Sync instead of CL Alt sync for fetching missing blocks in the payload queue. + n.p2pNode, err = p2p.NewNodeP2P(n.resourcesCtx, &cfg.Rollup, n.log, cfg.P2P, n, n.l2Source, n.runCfg, n.metrics, false) + if err != nil { + return +@@ -496,6 +521,20 @@ return err + } + log.Info("Rollup node started") + return nil ++} ++ ++// onEvent handles broadcast events. ++// The OpNode itself is a deriver to catch system-critical events. ++// Other event-handling should be encapsulated into standalone derivers. ++func (n *OpNode) onEvent(ev event.Event) bool { ++ switch x := ev.(type) { ++ case rollup.CriticalErrorEvent: ++ n.log.Error("Critical error", "err", x.Err) ++ n.cancel(fmt.Errorf("critical error: %w", x.Err)) ++ return true ++ default: ++ return false ++ } + } +  + func (n *OpNode) OnNewL1Head(ctx context.Context, sig eth.L1BlockRef) { +@@ -668,6 +707,10 @@ result = multierror.Append(result, fmt.Errorf("failed to close L2 engine driver cleanly: %w", err)) + } + } +  ++ if n.eventSys != nil { ++ n.eventSys.Stop() ++ } ++ + if n.safeDB != nil { + if err := n.safeDB.Close(); err != nil { + result = multierror.Append(result, fmt.Errorf("failed to close safe head db: %w", err)) +@@ -682,6 +725,11 @@ + // close L2 engine RPC client + if n.l2Source != nil { + n.l2Source.Close() ++ } ++ ++ // close the supervisor RPC client ++ if n.supervisor != nil { ++ n.supervisor.Close() + } +  + // close L1 data source
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+1
+
-1
+ +
+ +
+
+
diff --git OP/op-node/p2p/node.go CELO/op-node/p2p/node.go +index 70f7dbc67c0bb939688be2ee989515d5c39ead3b..85da1686acd71b4098c7ccec33776d8091bbf935 100644 +--- OP/op-node/p2p/node.go ++++ CELO/op-node/p2p/node.go +@@ -79,7 +79,7 @@ return nil, err + } + if n.host == nil { + // See prior comment about n.host optionality: +- // TODO(CLI-4016): host is not optional, NodeP2P as a whole is. ++ // TODO: host is not optional, NodeP2P as a whole is. + panic("host is not optional if p2p is enabled") + } + return &n, nil
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+2
+
-2
+ +
+ +
+
+
diff --git OP/op-node/p2p/sync.go CELO/op-node/p2p/sync.go +index b838d000caf4066f69b319bacad431c991284634..c8777fe51f9287f3ab3e809579a1692582e7dc92 100644 +--- OP/op-node/p2p/sync.go ++++ CELO/op-node/p2p/sync.go +@@ -57,7 +57,7 @@ peerServerBlocksBurst = 15 + // If the client hits a request error, it counts as a lot of rate-limit tokens for syncing from that peer: + // we rather sync from other servers. We'll try again later, + // and eventually kick the peer based on degraded scoring if it's really not serving us well. +- // TODO(CLI-4009): Use a backoff rather than this mechanism. ++ // TODO: Use a backoff rather than this mechanism. + clientErrRateCost = peerServerBlocksBurst + ) +  +@@ -310,7 +310,7 @@ c.syncOnlyReqToStatic = true + } +  + // never errors with positive LRU cache size +- // TODO(CLI-3733): if we had an LRU based on on total payloads size, instead of payload count, ++ // TODO: if we had an LRU based on on total payloads size, instead of payload count, + // we can safely buffer more data in the happy case. + q, _ := simplelru.NewLRU[common.Hash, syncResult](100, c.onQuarantineEvict) + c.quarantine = q
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+23
+
-1
+ +
+ +
+
+
diff --git OP/op-node/rollup/chain_spec.go CELO/op-node/rollup/chain_spec.go +index 95d9c3b1979832a8800bb9c1266c90a97881cb14..74e32dad17cca58c12c9740e40aeed2dcfc68d5e 100644 +--- OP/op-node/rollup/chain_spec.go ++++ CELO/op-node/rollup/chain_spec.go +@@ -1,6 +1,8 @@ + package rollup +  + import ( ++ "math/big" ++ + "github.com/ethereum-optimism/optimism/op-node/params" + "github.com/ethereum-optimism/optimism/op-service/eth" + "github.com/ethereum/go-ethereum/log" +@@ -26,6 +28,12 @@ // the rollup config. + // From Fjord, the max sequencer drift for a given block timestamp should be learned via the + // ChainSpec instead of reading the rollup configuration field directly. + const maxSequencerDriftFjord = 1800 ++ ++// Normal OP chains wait for five confirmations while Celo waits for finalization, which can take ++// up to 3 * 32 blocks. So we should allow for more drift to compensate. ++// 3 * 32 - 5 = 91 blocks ++// 91 * 12s block time = 1092 ++const maxSequencerDriftCelo = maxSequencerDriftFjord + 1092 +  + type ForkName string +  +@@ -63,6 +71,16 @@ func NewChainSpec(config *Config) *ChainSpec { + return &ChainSpec{config: config} + } +  ++// L2ChainID returns the chain ID of the L2 chain. ++func (s *ChainSpec) L2ChainID() *big.Int { ++ return s.config.L2ChainID ++} ++ ++// L2GenesisTime returns the genesis time of the L2 chain. ++func (s *ChainSpec) L2GenesisTime() uint64 { ++ return s.config.Genesis.L2Time ++} ++ + // IsCanyon returns true if t >= canyon_time + func (s *ChainSpec) IsCanyon(t uint64) bool { + return s.config.IsCanyon(t) +@@ -105,7 +123,11 @@ // this was a rollup configuration parameter. Since Fjord, it is a constant, so its effective value + // should always be queried via the ChainSpec. + func (s *ChainSpec) MaxSequencerDrift(t uint64) uint64 { + if s.IsFeatMaxSequencerDriftConstant(t) { +- return maxSequencerDriftFjord ++ if s.config.IsCel2(t) { ++ return maxSequencerDriftCelo ++ } else { ++ return maxSequencerDriftFjord ++ } + } + return s.config.MaxSequencerDrift + }
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+11
+
-1
+ +
+ +
+
+
diff --git OP/op-node/rollup/derive/attributes.go CELO/op-node/rollup/derive/attributes.go +index c65198bcec733d87c2854e97f608d5af62057d0c..cc38a31b9c54fca6ba1c8c68715378fe47a13947 100644 +--- OP/op-node/rollup/derive/attributes.go ++++ CELO/op-node/rollup/derive/attributes.go +@@ -121,9 +121,19 @@ if err != nil { + return nil, NewCriticalError(fmt.Errorf("failed to create l1InfoTx: %w", err)) + } +  +- txs := make([]hexutil.Bytes, 0, 1+len(depositTxs)+len(upgradeTxs)) ++ var afterForceIncludeTxs []hexutil.Bytes ++ if ba.rollupCfg.IsInterop(nextL2Time) { ++ depositsCompleteTx, err := DepositsCompleteBytes(seqNumber, l1Info) ++ if err != nil { ++ return nil, NewCriticalError(fmt.Errorf("failed to create depositsCompleteTx: %w", err)) ++ } ++ afterForceIncludeTxs = append(afterForceIncludeTxs, depositsCompleteTx) ++ } ++ ++ txs := make([]hexutil.Bytes, 0, 1+len(depositTxs)+len(afterForceIncludeTxs)+len(upgradeTxs)) + txs = append(txs, l1InfoTx) + txs = append(txs, depositTxs...) ++ txs = append(txs, afterForceIncludeTxs...) + txs = append(txs, upgradeTxs...) +  + var withdrawals *types.Withdrawals
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+92
+
-0
+ +
+ +
+
+
diff --git OP/op-node/rollup/derive/attributes_test.go CELO/op-node/rollup/derive/attributes_test.go +index 68c7c71aa1e1330295babdae0816acb91d2dfec5..64fcec556343c15d3cf5e995a68b3a4a22bb612a 100644 +--- OP/op-node/rollup/derive/attributes_test.go ++++ CELO/op-node/rollup/derive/attributes_test.go +@@ -195,6 +195,98 @@ require.Equal(t, 1, len(attrs.Transactions)) + require.Equal(t, l1InfoTx, []byte(attrs.Transactions[0])) + require.True(t, attrs.NoTxPool) + }) ++ t.Run("new origin with deposits on post-Isthmus", func(t *testing.T) { ++ rng := rand.New(rand.NewSource(1234)) ++ l1Fetcher := &testutils.MockL1Source{} ++ defer l1Fetcher.AssertExpectations(t) ++ l2Parent := testutils.RandomL2BlockRef(rng) ++ l1CfgFetcher := &testutils.MockL2Client{} ++ l1CfgFetcher.ExpectSystemConfigByL2Hash(l2Parent.Hash, testSysCfg, nil) ++ defer l1CfgFetcher.AssertExpectations(t) ++ ++ l1Info := testutils.RandomBlockInfo(rng) ++ l1Info.InfoParentHash = l2Parent.L1Origin.Hash ++ l1Info.InfoNum = l2Parent.L1Origin.Number + 1 // next origin, where deposits may be ++ ++ receipts, depositTxs, err := makeReceipts(rng, l1Info.InfoHash, cfg.DepositContractAddress, []receiptData{ ++ {goodReceipt: true, DepositLogs: []bool{true, false}}, ++ {goodReceipt: true, DepositLogs: []bool{true}}, ++ {goodReceipt: false, DepositLogs: []bool{true}}, ++ {goodReceipt: false, DepositLogs: []bool{false}}, ++ }) ++ require.NoError(t, err) ++ userDepositTxs, err := encodeDeposits(depositTxs) ++ require.NoError(t, err) ++ ++ // sets config to post-interop ++ cfg.ActivateAtGenesis(rollup.Interop) ++ ++ seqNumber := uint64(0) ++ epoch := l1Info.ID() ++ l1InfoTx, err := L1InfoDepositBytes(cfg, testSysCfg, seqNumber, l1Info, 0) ++ require.NoError(t, err) ++ depositsComplete, err := DepositsCompleteBytes(seqNumber, l1Info) ++ require.NoError(t, err) ++ ++ var l2Txs []eth.Data ++ l2Txs = append(l2Txs, l1InfoTx) ++ l2Txs = append(l2Txs, userDepositTxs...) ++ l2Txs = append(l2Txs, depositsComplete) ++ ++ l1Fetcher.ExpectFetchReceipts(epoch.Hash, l1Info, receipts, nil) ++ attrBuilder := NewFetchingAttributesBuilder(cfg, l1Fetcher, l1CfgFetcher) ++ attrs, err := attrBuilder.PreparePayloadAttributes(context.Background(), l2Parent, epoch) ++ require.NoError(t, err) ++ require.NotNil(t, attrs) ++ require.Equal(t, l2Parent.Time+cfg.BlockTime, uint64(attrs.Timestamp)) ++ require.Equal(t, eth.Bytes32(l1Info.InfoMixDigest), attrs.PrevRandao) ++ require.Equal(t, predeploys.SequencerFeeVaultAddr, attrs.SuggestedFeeRecipient) ++ require.Equal(t, len(l2Txs), len(attrs.Transactions), "Expected txs to equal l1 info tx + user deposit txs + DepositsComplete") ++ require.Equal(t, eth.Data(depositsComplete).String(), attrs.Transactions[len(l2Txs)-1].String()) ++ require.Equal(t, l2Txs, attrs.Transactions) ++ require.True(t, attrs.NoTxPool) ++ }) ++ ++ t.Run("same origin without deposits on post-Isthmus", func(t *testing.T) { ++ rng := rand.New(rand.NewSource(1234)) ++ l1Fetcher := &testutils.MockL1Source{} ++ defer l1Fetcher.AssertExpectations(t) ++ l2Parent := testutils.RandomL2BlockRef(rng) ++ l1CfgFetcher := &testutils.MockL2Client{} ++ l1CfgFetcher.ExpectSystemConfigByL2Hash(l2Parent.Hash, testSysCfg, nil) ++ defer l1CfgFetcher.AssertExpectations(t) ++ l1Info := testutils.RandomBlockInfo(rng) ++ l1Info.InfoHash = l2Parent.L1Origin.Hash ++ l1Info.InfoNum = l2Parent.L1Origin.Number // same origin again, so the sequence number is not reset ++ ++ // sets config to post-interop ++ cfg.ActivateAtGenesis(rollup.Interop) ++ ++ seqNumber := l2Parent.SequenceNumber + 1 ++ epoch := l1Info.ID() ++ l1InfoTx, err := L1InfoDepositBytes(cfg, testSysCfg, seqNumber, l1Info, 0) ++ require.NoError(t, err) ++ depositsComplete, err := DepositsCompleteBytes(seqNumber, l1Info) ++ require.NoError(t, err) ++ ++ var l2Txs []eth.Data ++ l2Txs = append(l2Txs, l1InfoTx) ++ l2Txs = append(l2Txs, depositsComplete) ++ ++ l1Fetcher.ExpectInfoByHash(epoch.Hash, l1Info, nil) ++ attrBuilder := NewFetchingAttributesBuilder(cfg, l1Fetcher, l1CfgFetcher) ++ attrs, err := attrBuilder.PreparePayloadAttributes(context.Background(), l2Parent, epoch) ++ require.NoError(t, err) ++ require.NotNil(t, attrs) ++ require.Equal(t, l2Parent.Time+cfg.BlockTime, uint64(attrs.Timestamp)) ++ require.Equal(t, eth.Bytes32(l1Info.InfoMixDigest), attrs.PrevRandao) ++ require.Equal(t, predeploys.SequencerFeeVaultAddr, attrs.SuggestedFeeRecipient) ++ require.Equal(t, len(l2Txs), len(attrs.Transactions), "Expected txs to equal l1 info tx + user deposit txs + DepositsComplete") ++ require.Equal(t, eth.Data(depositsComplete).String(), attrs.Transactions[len(l2Txs)-1].String()) ++ require.Equal(t, l2Txs, attrs.Transactions) ++ require.True(t, attrs.NoTxPool) ++ }) ++ + // Test that the payload attributes builder changes the deposit format based on L2-time-based regolith activation + t.Run("regolith", func(t *testing.T) { + testCases := []struct {
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+3
+
-3
+ +
+ +
+
+
diff --git OP/op-node/rollup/derive/blob_data_source.go CELO/op-node/rollup/derive/blob_data_source.go +index 7780b6065063efae6fadb5d49401c71d68bf1464..2c4626941b8b51cb9477c9c08dd9f6e3fb01208a 100644 +--- OP/op-node/rollup/derive/blob_data_source.go ++++ CELO/op-node/rollup/derive/blob_data_source.go +@@ -86,7 +86,7 @@ } + return nil, NewTemporaryError(fmt.Errorf("failed to open blob data source: %w", err)) + } +  +- data, hashes := dataAndHashesFromTxs(txs, &ds.dsCfg, ds.batcherAddr) ++ data, hashes := dataAndHashesFromTxs(txs, &ds.dsCfg, ds.batcherAddr, ds.log) +  + if len(hashes) == 0 { + // there are no blobs to fetch so we can return immediately +@@ -115,13 +115,13 @@ + // dataAndHashesFromTxs extracts calldata and datahashes from the input transactions and returns them. It + // creates a placeholder blobOrCalldata element for each returned blob hash that must be populated + // by fillBlobPointers after blob bodies are retrieved. +-func dataAndHashesFromTxs(txs types.Transactions, config *DataSourceConfig, batcherAddr common.Address) ([]blobOrCalldata, []eth.IndexedBlobHash) { ++func dataAndHashesFromTxs(txs types.Transactions, config *DataSourceConfig, batcherAddr common.Address, logger log.Logger) ([]blobOrCalldata, []eth.IndexedBlobHash) { + data := []blobOrCalldata{} + var hashes []eth.IndexedBlobHash + blobIndex := 0 // index of each blob in the block's blob sidecar + for _, tx := range txs { + // skip any non-batcher transactions +- if !isValidBatchTx(tx, config.l1Signer, config.batchInboxAddress, batcherAddr) { ++ if !isValidBatchTx(tx, config.l1Signer, config.batchInboxAddress, batcherAddr, logger) { + blobIndex += len(tx.BlobHashes()) + continue + }
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+8
+
-5
+ +
+ +
+
+
diff --git OP/op-node/rollup/derive/blob_data_source_test.go CELO/op-node/rollup/derive/blob_data_source_test.go +index aa9ef82cb991a79f67cc81bde46cdfe1b6db11ff..e5e31dc957b90178963a5d1b0d2d41f9e3d0fd7a 100644 +--- OP/op-node/rollup/derive/blob_data_source_test.go ++++ CELO/op-node/rollup/derive/blob_data_source_test.go +@@ -13,7 +13,9 @@ "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" +  + "github.com/ethereum-optimism/optimism/op-service/eth" ++ "github.com/ethereum-optimism/optimism/op-service/testlog" + "github.com/ethereum-optimism/optimism/op-service/testutils" ++ "github.com/ethereum/go-ethereum/log" + ) +  + func TestDataAndHashesFromTxs(t *testing.T) { +@@ -23,6 +25,7 @@ privateKey := testutils.InsecureRandomKey(rng) + publicKey, _ := privateKey.Public().(*ecdsa.PublicKey) + batcherAddr := crypto.PubkeyToAddress(*publicKey) + batchInboxAddr := testutils.RandomAddress(rng) ++ logger := testlog.Logger(t, log.LvlInfo) +  + chainId := new(big.Int).SetUint64(rng.Uint64()) + signer := types.NewCancunSigner(chainId) +@@ -42,7 +45,7 @@ Data: testutils.RandomData(rng, rng.Intn(1000)), + } + calldataTx, _ := types.SignNewTx(privateKey, signer, txData) + txs := types.Transactions{calldataTx} +- data, blobHashes := dataAndHashesFromTxs(txs, &config, batcherAddr) ++ data, blobHashes := dataAndHashesFromTxs(txs, &config, batcherAddr, logger) + require.Equal(t, 1, len(data)) + require.Equal(t, 0, len(blobHashes)) +  +@@ -57,14 +60,14 @@ BlobHashes: []common.Hash{blobHash}, + } + blobTx, _ := types.SignNewTx(privateKey, signer, blobTxData) + txs = types.Transactions{blobTx} +- data, blobHashes = dataAndHashesFromTxs(txs, &config, batcherAddr) ++ data, blobHashes = dataAndHashesFromTxs(txs, &config, batcherAddr, logger) + require.Equal(t, 1, len(data)) + require.Equal(t, 1, len(blobHashes)) + require.Nil(t, data[0].calldata) +  + // try again with both the blob & calldata transactions and make sure both are picked up + txs = types.Transactions{blobTx, calldataTx} +- data, blobHashes = dataAndHashesFromTxs(txs, &config, batcherAddr) ++ data, blobHashes = dataAndHashesFromTxs(txs, &config, batcherAddr, logger) + require.Equal(t, 2, len(data)) + require.Equal(t, 1, len(blobHashes)) + require.NotNil(t, data[1].calldata) +@@ -72,7 +75,7 @@ + // make sure blob tx to the batch inbox is ignored if not signed by the batcher + blobTx, _ = types.SignNewTx(testutils.RandomKey(), signer, blobTxData) + txs = types.Transactions{blobTx} +- data, blobHashes = dataAndHashesFromTxs(txs, &config, batcherAddr) ++ data, blobHashes = dataAndHashesFromTxs(txs, &config, batcherAddr, logger) + require.Equal(t, 0, len(data)) + require.Equal(t, 0, len(blobHashes)) +  +@@ -81,7 +84,7 @@ // signature is valid. + blobTxData.To = testutils.RandomAddress(rng) + blobTx, _ = types.SignNewTx(privateKey, signer, blobTxData) + txs = types.Transactions{blobTx} +- data, blobHashes = dataAndHashesFromTxs(txs, &config, batcherAddr) ++ data, blobHashes = dataAndHashesFromTxs(txs, &config, batcherAddr, logger) + require.Equal(t, 0, len(data)) + require.Equal(t, 0, len(blobHashes)) + }
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+1
+
-1
+ +
+ +
+
+
diff --git OP/op-node/rollup/derive/calldata_source.go CELO/op-node/rollup/derive/calldata_source.go +index 0a5d7915770d6ae9872146670c56b6e68b49b0aa..0e8147261e93e4235c33b93f1d56be2285d96297 100644 +--- OP/op-node/rollup/derive/calldata_source.go ++++ CELO/op-node/rollup/derive/calldata_source.go +@@ -79,7 +79,7 @@ // This will return an empty array if no valid transactions are found. + func DataFromEVMTransactions(dsCfg DataSourceConfig, batcherAddr common.Address, txs types.Transactions, log log.Logger) []eth.Data { + out := []eth.Data{} + for _, tx := range txs { +- if isValidBatchTx(tx, dsCfg.l1Signer, dsCfg.batchInboxAddress, batcherAddr) { ++ if isValidBatchTx(tx, dsCfg.l1Signer, dsCfg.batchInboxAddress, batcherAddr, log) { + out = append(out, tx.Data()) + } + }
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+2
+
-4
+ +
+ +
+
+
diff --git OP/op-node/rollup/derive/channel_bank.go CELO/op-node/rollup/derive/channel_bank.go +index b2efb0d3ce169fa6af1f60e33daa4012fbbfc683..8dd689dfadaaebed671ce3eb3a2b4c84ee8abd43 100644 +--- OP/op-node/rollup/derive/channel_bank.go ++++ CELO/op-node/rollup/derive/channel_bank.go +@@ -37,14 +37,13 @@ + channels map[ChannelID]*Channel // channels by ID + channelQueue []ChannelID // channels in FIFO order +  +- prev NextFrameProvider +- fetcher L1Fetcher ++ prev NextFrameProvider + } +  + var _ ResettableStage = (*ChannelBank)(nil) +  + // NewChannelBank creates a ChannelBank, which should be Reset(origin) before use. +-func NewChannelBank(log log.Logger, cfg *rollup.Config, prev NextFrameProvider, fetcher L1Fetcher, m Metrics) *ChannelBank { ++func NewChannelBank(log log.Logger, cfg *rollup.Config, prev NextFrameProvider, m Metrics) *ChannelBank { + return &ChannelBank{ + log: log, + spec: rollup.NewChainSpec(cfg), +@@ -52,7 +51,6 @@ metrics: m, + channels: make(map[ChannelID]*Channel), + channelQueue: make([]ChannelID, 0, 10), + prev: prev, +- fetcher: fetcher, + } + } +
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+4
+
-4
+ +
+ +
+
+
diff --git OP/op-node/rollup/derive/channel_bank_test.go CELO/op-node/rollup/derive/channel_bank_test.go +index 59c82c308f01ca8925eb8410aa22964c7c914f30..33763c23c5e01316dc161e59aa586552ea5a898b 100644 +--- OP/op-node/rollup/derive/channel_bank_test.go ++++ CELO/op-node/rollup/derive/channel_bank_test.go +@@ -102,7 +102,7 @@ input.AddFrame(Frame{}, io.EOF) +  + cfg := &rollup.Config{ChannelTimeoutBedrock: 10} +  +- cb := NewChannelBank(testlog.Logger(t, log.LevelCrit), cfg, input, nil, metrics.NoopMetrics) ++ cb := NewChannelBank(testlog.Logger(t, log.LevelCrit), cfg, input, metrics.NoopMetrics) +  + // Load the first frame + out, err := cb.NextData(context.Background()) +@@ -146,7 +146,7 @@ input.AddFrame(Frame{}, io.EOF) +  + cfg := &rollup.Config{ChannelTimeoutBedrock: 10, CanyonTime: nil} +  +- cb := NewChannelBank(testlog.Logger(t, log.LevelCrit), cfg, input, nil, metrics.NoopMetrics) ++ cb := NewChannelBank(testlog.Logger(t, log.LevelCrit), cfg, input, metrics.NoopMetrics) +  + // Load a:0 + out, err := cb.NextData(context.Background()) +@@ -211,7 +211,7 @@ + ct := uint64(0) + cfg := &rollup.Config{ChannelTimeoutBedrock: 10, CanyonTime: &ct} +  +- cb := NewChannelBank(testlog.Logger(t, log.LevelCrit), cfg, input, nil, metrics.NoopMetrics) ++ cb := NewChannelBank(testlog.Logger(t, log.LevelCrit), cfg, input, metrics.NoopMetrics) +  + // Load a:0 + out, err := cb.NextData(context.Background()) +@@ -271,7 +271,7 @@ input.AddFrame(Frame{}, io.EOF) +  + cfg := &rollup.Config{ChannelTimeoutBedrock: 10} +  +- cb := NewChannelBank(testlog.Logger(t, log.LevelCrit), cfg, input, nil, metrics.NoopMetrics) ++ cb := NewChannelBank(testlog.Logger(t, log.LevelCrit), cfg, input, metrics.NoopMetrics) +  + // Load the first frame + out, err := cb.NextData(context.Background())
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+3
+
-4
+ +
+ +
+
+
diff --git OP/op-node/rollup/derive/channel_out_test.go CELO/op-node/rollup/derive/channel_out_test.go +index 53fedef03e6454b8ec78fc52fa7d4c442982f8cb..34aa58400fdd051897fe176456270e0a725516b3 100644 +--- OP/op-node/rollup/derive/channel_out_test.go ++++ CELO/op-node/rollup/derive/channel_out_test.go +@@ -61,7 +61,7 @@ }, + { + Name: "Span", + ChannelOut: func(t *testing.T, rcfg *rollup.Config) ChannelOut { +- cout, err := NewSpanChannelOut(0, big.NewInt(0), 128_000, Zlib, rollup.NewChainSpec(rcfg)) ++ cout, err := NewSpanChannelOut(128_000, Zlib, rollup.NewChainSpec(rcfg)) + require.NoError(t, err) + return cout + }, +@@ -111,9 +111,8 @@ t.Run(tcase.Name, func(t *testing.T) { + cout := tcase.ChannelOut(t, &rollupCfg) +  + rng := rand.New(rand.NewSource(0x543331)) +- chainID := big.NewInt(0) + txCount := 1 +- singularBatch := RandomSingularBatch(rng, txCount, chainID) ++ singularBatch := RandomSingularBatch(rng, txCount, rollupCfg.L2ChainID) +  + err := cout.AddSingularBatch(singularBatch, 0) + var written uint64 +@@ -236,7 +235,7 @@ rng := rand.New(rand.NewSource(0x543331)) + chainID := rollupCfg.L2ChainID + txCount := 1 + genesisTime := rollupCfg.Genesis.L2Time +- cout, err := NewSpanChannelOut(genesisTime, chainID, targetOutputSize, algo, rollup.NewChainSpec(&rollupCfg), opts...) ++ cout, err := NewSpanChannelOut(targetOutputSize, algo, rollup.NewChainSpec(&rollupCfg), opts...) + require.NoError(t, err) + batches := make([]*SingularBatch, 0, numBatches) + // adding the first batch should not cause an error
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+3
+
-3
+ +
+ +
+
+
diff --git OP/op-node/rollup/derive/data_source.go CELO/op-node/rollup/derive/data_source.go +index b4ab76dc64bc4d6bd34fb15323e9145ed0b6fd90..8d064a7cdb8caf5cf91bedd6de090307cff0a6e9 100644 +--- OP/op-node/rollup/derive/data_source.go ++++ CELO/op-node/rollup/derive/data_source.go +@@ -93,19 +93,19 @@ + // isValidBatchTx returns true if: + // 1. the transaction has a To() address that matches the batch inbox address, and + // 2. the transaction has a valid signature from the batcher address +-func isValidBatchTx(tx *types.Transaction, l1Signer types.Signer, batchInboxAddr, batcherAddr common.Address) bool { ++func isValidBatchTx(tx *types.Transaction, l1Signer types.Signer, batchInboxAddr, batcherAddr common.Address, logger log.Logger) bool { + to := tx.To() + if to == nil || *to != batchInboxAddr { + return false + } + seqDataSubmitter, err := l1Signer.Sender(tx) // optimization: only derive sender if To is correct + if err != nil { +- log.Warn("tx in inbox with invalid signature", "hash", tx.Hash(), "err", err) ++ logger.Warn("tx in inbox with invalid signature", "hash", tx.Hash(), "err", err) + return false + } + // some random L1 user might have sent a transaction to our batch inbox, ignore them + if seqDataSubmitter != batcherAddr { +- log.Warn("tx in inbox with unauthorized submitter", "addr", seqDataSubmitter, "hash", tx.Hash(), "err", err) ++ logger.Warn("tx in inbox with unauthorized submitter", "addr", seqDataSubmitter, "hash", tx.Hash(), "err", err) + return false + } + return true
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+22
+
-3
+ +
+ +
+
+
diff --git OP/op-node/rollup/derive/deposit_source.go CELO/op-node/rollup/derive/deposit_source.go +index f7a9730ad026c0f49ea67529e09fc4de5cea4f36..8b4e49590e3c53be32e4ffda968122a7b6447610 100644 +--- OP/op-node/rollup/derive/deposit_source.go ++++ CELO/op-node/rollup/derive/deposit_source.go +@@ -13,9 +13,10 @@ LogIndex uint64 + } +  + const ( +- UserDepositSourceDomain = 0 +- L1InfoDepositSourceDomain = 1 +- UpgradeDepositSourceDomain = 2 ++ UserDepositSourceDomain = 0 ++ L1InfoDepositSourceDomain = 1 ++ UpgradeDepositSourceDomain = 2 ++ AfterForceIncludeSourceDomain = 3 + ) +  + func (dep *UserDepositSource) SourceHash() common.Hash { +@@ -63,3 +64,21 @@ binary.BigEndian.PutUint64(domainInput[32-8:32], UpgradeDepositSourceDomain) + copy(domainInput[32:], intentHash[:]) + return crypto.Keccak256Hash(domainInput[:]) + } ++ ++// AfterForceIncludeSource identifies the DepositsComplete post-user-deposits deposit-transaction. ++type AfterForceIncludeSource struct { ++ L1BlockHash common.Hash ++ SeqNumber uint64 // without this the Deposit tx would have the same tx hash for every time the L1 info repeats. ++} ++ ++func (dep *AfterForceIncludeSource) SourceHash() common.Hash { ++ var input [32 * 2]byte ++ copy(input[:32], dep.L1BlockHash[:]) ++ binary.BigEndian.PutUint64(input[32*2-8:], dep.SeqNumber) ++ depositIDHash := crypto.Keccak256Hash(input[:]) ++ ++ var domainInput [32 * 2]byte ++ binary.BigEndian.PutUint64(domainInput[32-8:32], AfterForceIncludeSourceDomain) ++ copy(domainInput[32:], depositIDHash[:]) ++ return crypto.Keccak256Hash(domainInput[:]) ++}
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+31
+
-0
+ +
+ +
+
+
diff --git OP/op-node/rollup/derive/deposit_source_test.go CELO/op-node/rollup/derive/deposit_source_test.go +index 10fb7048a2a26243289ccbf58ace1a478a1da0aa..fb30e8918829185fc629626b42b5c4a18de0ad45 100644 +--- OP/op-node/rollup/derive/deposit_source_test.go ++++ CELO/op-node/rollup/derive/deposit_source_test.go +@@ -3,6 +3,7 @@ + import ( + "testing" +  ++ "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/assert" + ) +  +@@ -34,3 +35,33 @@ expected := "0x69b763c48478b9dc2f65ada09b3d92133ec592ea715ec65ad6e7f3dc519dc00c" +  + assert.Equal(t, expected, actual.Hex()) + } ++ ++// TestL1InfoDepositSource ++// cast keccak $(cast concat-hex 0x0000000000000000000000000000000000000000000000000000000000000001 $(cast keccak $(cast concat-hex 0xc00e5d67c2755389aded7d8b151cbd5bcdf7ed275ad5e028b664880fc7581c77 0x0000000000000000000000000000000000000000000000000000000000000004))) ++// # 0x0586c503340591999b8b38bc9834bb16aec7d5bc00eb5587ab139c9ddab81977 ++func TestL1InfoDepositSource(t *testing.T) { ++ source := L1InfoDepositSource{ ++ L1BlockHash: common.HexToHash("0xc00e5d67c2755389aded7d8b151cbd5bcdf7ed275ad5e028b664880fc7581c77"), ++ SeqNumber: 4, ++ } ++ ++ actual := source.SourceHash() ++ expected := "0x0586c503340591999b8b38bc9834bb16aec7d5bc00eb5587ab139c9ddab81977" ++ ++ assert.Equal(t, expected, actual.Hex()) ++} ++ ++// TestAfterForceIncludeSourceHash ++// cast keccak $(cast concat-hex 0x0000000000000000000000000000000000000000000000000000000000000003 $(cast keccak $(cast concat-hex 0xc00e5d67c2755389aded7d8b151cbd5bcdf7ed275ad5e028b664880fc7581c77 0x0000000000000000000000000000000000000000000000000000000000000004))) ++// # 0x0d165c391384b29c29f655e3f32315755b8c1e4c1147d1824d1243420dda5ec3 ++func TestAfterForceIncludeSource(t *testing.T) { ++ source := AfterForceIncludeSource{ ++ L1BlockHash: common.HexToHash("0xc00e5d67c2755389aded7d8b151cbd5bcdf7ed275ad5e028b664880fc7581c77"), ++ SeqNumber: 4, ++ } ++ ++ actual := source.SourceHash() ++ expected := "0x0d165c391384b29c29f655e3f32315755b8c1e4c1147d1824d1243420dda5ec3" ++ ++ assert.Equal(t, expected, actual.Hex()) ++}
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+3
+
-3
+ +
+ +
+
+
diff --git OP/op-node/rollup/derive/frame.go CELO/op-node/rollup/derive/frame.go +index 0baa1e120a14e3439b6b185fe97da5845424eeac..7547aca7531d95b2d212e069a24150a689715303 100644 +--- OP/op-node/rollup/derive/frame.go ++++ CELO/op-node/rollup/derive/frame.go +@@ -8,10 +8,10 @@ "fmt" + "io" + ) +  +-// Frames cannot be larger than 1 MB. + // Data transactions that carry frames are generally not larger than 128 KB due to L1 network conditions, + // but we leave space to grow larger anyway (gas limit allows for more data). +-const MaxFrameLen = 1_000_000 ++// For AltDA, frames size can be larger. Setting to 16 MB as current blob limit for EigenDA. ++const MaxFrameLen = 16_000_000 +  + // Data Format + // +@@ -85,7 +85,7 @@ if err := binary.Read(r, binary.BigEndian, &frameLength); err != nil { + return fmt.Errorf("reading frame_data_length: %w", eofAsUnexpectedMissing(err)) + } +  +- // Cap frame length to MaxFrameLen (currently 1MB) ++ // Cap frame length to MaxFrameLen + if frameLength > MaxFrameLen { + return fmt.Errorf("frame_data_length is too large: %d", frameLength) + }
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+14
+
-3
+ +
+ +
+
+
diff --git OP/op-node/rollup/derive/fuzz_parsers_test.go CELO/op-node/rollup/derive/fuzz_parsers_test.go +index 95ce94bc7cc85d358870712839d156f7d62ce3c2..4f76c4ac7420a452c43555aeafed36c7e20604b6 100644 +--- OP/op-node/rollup/derive/fuzz_parsers_test.go ++++ CELO/op-node/rollup/derive/fuzz_parsers_test.go +@@ -83,15 +83,26 @@ BlobBaseFeeScalar: blobBaseFeeScalar, + } + enc, err := in.marshalBinaryEcotone() + if err != nil { +- t.Fatalf("Failed to marshal binary: %v", err) ++ t.Fatalf("Failed to marshal Ecotone binary: %v", err) + } + var out L1BlockInfo + err = out.unmarshalBinaryEcotone(enc) + if err != nil { +- t.Fatalf("Failed to unmarshal binary: %v", err) ++ t.Fatalf("Failed to unmarshal Ecotone binary: %v", err) ++ } ++ if !cmp.Equal(in, out, cmp.Comparer(testutils.BigEqual)) { ++ t.Fatalf("The Ecotone data did not round trip correctly. in: %v. out: %v", in, out) ++ } ++ enc, err = in.marshalBinaryIsthmus() ++ if err != nil { ++ t.Fatalf("Failed to marshal Isthmus binary: %v", err) ++ } ++ err = out.unmarshalBinaryIsthmus(enc) ++ if err != nil { ++ t.Fatalf("Failed to unmarshal Isthmus binary: %v", err) + } + if !cmp.Equal(in, out, cmp.Comparer(testutils.BigEqual)) { +- t.Fatalf("The data did not round trip correctly. in: %v. out: %v", in, out) ++ t.Fatalf("The Isthmus data did not round trip correctly. in: %v. out: %v", in, out) + } +  + })
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+104
+
-16
+ +
+ +
+
+
diff --git OP/op-node/rollup/derive/l1_block_info.go CELO/op-node/rollup/derive/l1_block_info.go +index 26f3f6711f55749d0060a23cda3f666775866a20..43ea9b29bedc4de41b64946cfb037f1ff463f25f 100644 +--- OP/op-node/rollup/derive/l1_block_info.go ++++ CELO/op-node/rollup/derive/l1_block_info.go +@@ -20,14 +20,25 @@ + const ( + L1InfoFuncBedrockSignature = "setL1BlockValues(uint64,uint64,uint256,bytes32,uint64,bytes32,uint256,uint256)" + L1InfoFuncEcotoneSignature = "setL1BlockValuesEcotone()" ++ L1InfoFuncIsthmusSignature = "setL1BlockValuesIsthmus()" ++ DepositsCompleteSignature = "depositsComplete()" + L1InfoArguments = 8 + L1InfoBedrockLen = 4 + 32*L1InfoArguments + L1InfoEcotoneLen = 4 + 32*5 // after Ecotone upgrade, args are packed into 5 32-byte slots ++ DepositsCompleteLen = 4 // only the selector ++ // DepositsCompleteGas allocates 21k gas for intrinsic tx costs, and ++ // an additional 15k to ensure that the DepositsComplete call does not run out of gas. ++ // GasBenchMark_L1BlockIsthmus_DepositsComplete:test_depositsComplete_benchmark() (gas: 7768) ++ // GasBenchMark_L1BlockIsthmus_DepositsComplete_Warm:test_depositsComplete_benchmark() (gas: 5768) ++ // see `test_depositsComplete_benchmark` at: `/packages/contracts-bedrock/test/BenchmarkTest.t.sol` ++ DepositsCompleteGas = uint64(21_000 + 15_000) + ) +  + var ( + L1InfoFuncBedrockBytes4 = crypto.Keccak256([]byte(L1InfoFuncBedrockSignature))[:4] + L1InfoFuncEcotoneBytes4 = crypto.Keccak256([]byte(L1InfoFuncEcotoneSignature))[:4] ++ L1InfoFuncIsthmusBytes4 = crypto.Keccak256([]byte(L1InfoFuncIsthmusSignature))[:4] ++ DepositsCompleteBytes4 = crypto.Keccak256([]byte(DepositsCompleteSignature))[:4] + L1InfoDepositerAddress = common.HexToAddress("0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001") + L1BlockAddress = predeploys.L1BlockAddr + ErrInvalidFormat = errors.New("invalid ecotone l1 block info format") +@@ -144,7 +155,7 @@ } + return nil + } +  +-// Ecotone Binary Format ++// Isthmus & Ecotone Binary Format + // +---------+--------------------------+ + // | Bytes | Field | + // +---------+--------------------------+ +@@ -161,8 +172,24 @@ // | 32 | BatcherHash | + // +---------+--------------------------+ +  + func (info *L1BlockInfo) marshalBinaryEcotone() ([]byte, error) { +- w := bytes.NewBuffer(make([]byte, 0, L1InfoEcotoneLen)) +- if err := solabi.WriteSignature(w, L1InfoFuncEcotoneBytes4); err != nil { ++ out, err := marshalBinaryWithSignature(info, L1InfoFuncEcotoneBytes4) ++ if err != nil { ++ return nil, fmt.Errorf("failed to marshal Ecotone l1 block info: %w", err) ++ } ++ return out, nil ++} ++ ++func (info *L1BlockInfo) marshalBinaryIsthmus() ([]byte, error) { ++ out, err := marshalBinaryWithSignature(info, L1InfoFuncIsthmusBytes4) ++ if err != nil { ++ return nil, fmt.Errorf("failed to marshal Isthmus l1 block info: %w", err) ++ } ++ return out, nil ++} ++ ++func marshalBinaryWithSignature(info *L1BlockInfo, signature []byte) ([]byte, error) { ++ w := bytes.NewBuffer(make([]byte, 0, L1InfoEcotoneLen)) // Ecotone and Isthmus have the same length ++ if err := solabi.WriteSignature(w, signature); err != nil { + return nil, err + } + if err := binary.Write(w, binary.BigEndian, info.BaseFeeScalar); err != nil { +@@ -201,13 +228,21 @@ return w.Bytes(), nil + } +  + func (info *L1BlockInfo) unmarshalBinaryEcotone(data []byte) error { ++ return unmarshalBinaryWithSignatureAndData(info, L1InfoFuncEcotoneBytes4, data) ++} ++ ++func (info *L1BlockInfo) unmarshalBinaryIsthmus(data []byte) error { ++ return unmarshalBinaryWithSignatureAndData(info, L1InfoFuncIsthmusBytes4, data) ++} ++ ++func unmarshalBinaryWithSignatureAndData(info *L1BlockInfo, signature []byte, data []byte) error { + if len(data) != L1InfoEcotoneLen { + return fmt.Errorf("data is unexpected length: %d", len(data)) + } + r := bytes.NewReader(data) +  + var err error +- if _, err := solabi.ReadAndValidateSignature(r, L1InfoFuncEcotoneBytes4); err != nil { ++ if _, err := solabi.ReadAndValidateSignature(r, signature); err != nil { + return err + } + if err := binary.Read(r, binary.BigEndian, &info.BaseFeeScalar); err != nil { +@@ -245,14 +280,28 @@ return nil + } +  + // isEcotoneButNotFirstBlock returns whether the specified block is subject to the Ecotone upgrade, +-// but is not the actiation block itself. +-func isEcotoneButNotFirstBlock(rollupCfg *rollup.Config, l2BlockTime uint64) bool { +- return rollupCfg.IsEcotone(l2BlockTime) && !rollupCfg.IsEcotoneActivationBlock(l2BlockTime) ++// but is not the activation block itself. ++func isEcotoneButNotFirstBlock(rollupCfg *rollup.Config, l2Timestamp uint64) bool { ++ return rollupCfg.IsEcotone(l2Timestamp) && !rollupCfg.IsEcotoneActivationBlock(l2Timestamp) ++} ++ ++// isInteropButNotFirstBlock returns whether the specified block is subject to the Isthmus upgrade, ++// but is not the activation block itself. ++func isInteropButNotFirstBlock(rollupCfg *rollup.Config, l2Timestamp uint64) bool { ++ // Since we use the pre-interop L1 tx one last time during the upgrade block, ++ // we must disallow the deposit-txs from using the CrossL2Inbox during this block. ++ // If the CrossL2Inbox does not exist yet, then it is safe, ++ // but we have to ensure that the spec and code puts any Interop upgrade-txs after the user deposits. ++ return rollupCfg.IsInterop(l2Timestamp) && !rollupCfg.IsInteropActivationBlock(l2Timestamp) + } +  + // L1BlockInfoFromBytes is the inverse of L1InfoDeposit, to see where the L2 chain is derived from + func L1BlockInfoFromBytes(rollupCfg *rollup.Config, l2BlockTime uint64, data []byte) (*L1BlockInfo, error) { + var info L1BlockInfo ++ // Important, this should be ordered from most recent to oldest ++ if isInteropButNotFirstBlock(rollupCfg, l2BlockTime) { ++ return &info, info.unmarshalBinaryIsthmus(data) ++ } + if isEcotoneButNotFirstBlock(rollupCfg, l2BlockTime) { + return &info, info.unmarshalBinaryEcotone(data) + } +@@ -261,7 +310,7 @@ } +  + // L1InfoDeposit creates a L1 Info deposit transaction based on the L1 block, + // and the L2 block-height difference with the start of the epoch. +-func L1InfoDeposit(rollupCfg *rollup.Config, sysCfg eth.SystemConfig, seqNumber uint64, block eth.BlockInfo, l2BlockTime uint64) (*types.DepositTx, error) { ++func L1InfoDeposit(rollupCfg *rollup.Config, sysCfg eth.SystemConfig, seqNumber uint64, block eth.BlockInfo, l2Timestamp uint64) (*types.DepositTx, error) { + l1BlockInfo := L1BlockInfo{ + Number: block.NumberU64(), + Time: block.Time(), +@@ -271,7 +320,7 @@ SequenceNumber: seqNumber, + BatcherAddr: sysCfg.BatcherAddr, + } + var data []byte +- if isEcotoneButNotFirstBlock(rollupCfg, l2BlockTime) { ++ if isEcotoneButNotFirstBlock(rollupCfg, l2Timestamp) { + l1BlockInfo.BlobBaseFee = block.BlobBaseFee() + if l1BlockInfo.BlobBaseFee == nil { + // The L2 spec states to use the MIN_BLOB_GASPRICE from EIP-4844 if not yet active on L1. +@@ -283,11 +332,19 @@ return nil, err + } + l1BlockInfo.BlobBaseFeeScalar = scalars.BlobBaseFeeScalar + l1BlockInfo.BaseFeeScalar = scalars.BaseFeeScalar +- out, err := l1BlockInfo.marshalBinaryEcotone() +- if err != nil { +- return nil, fmt.Errorf("failed to marshal Ecotone l1 block info: %w", err) ++ if isInteropButNotFirstBlock(rollupCfg, l2Timestamp) { ++ out, err := l1BlockInfo.marshalBinaryIsthmus() ++ if err != nil { ++ return nil, fmt.Errorf("failed to marshal Isthmus l1 block info: %w", err) ++ } ++ data = out ++ } else { ++ out, err := l1BlockInfo.marshalBinaryEcotone() ++ if err != nil { ++ return nil, fmt.Errorf("failed to marshal Ecotone l1 block info: %w", err) ++ } ++ data = out + } +- data = out + } else { + l1BlockInfo.L1FeeOverhead = sysCfg.Overhead + l1BlockInfo.L1FeeScalar = sysCfg.Scalar +@@ -315,7 +372,7 @@ IsSystemTransaction: true, + Data: data, + } + // With the regolith fork we disable the IsSystemTx functionality, and allocate real gas +- if rollupCfg.IsRegolith(l2BlockTime) { ++ if rollupCfg.IsRegolith(l2Timestamp) { + out.IsSystemTransaction = false + out.Gas = RegolithSystemTxGas + } +@@ -323,8 +380,8 @@ return out, nil + } +  + // L1InfoDepositBytes returns a serialized L1-info attributes transaction. +-func L1InfoDepositBytes(rollupCfg *rollup.Config, sysCfg eth.SystemConfig, seqNumber uint64, l1Info eth.BlockInfo, l2BlockTime uint64) ([]byte, error) { +- dep, err := L1InfoDeposit(rollupCfg, sysCfg, seqNumber, l1Info, l2BlockTime) ++func L1InfoDepositBytes(rollupCfg *rollup.Config, sysCfg eth.SystemConfig, seqNumber uint64, l1Info eth.BlockInfo, l2Timestamp uint64) ([]byte, error) { ++ dep, err := L1InfoDeposit(rollupCfg, sysCfg, seqNumber, l1Info, l2Timestamp) + if err != nil { + return nil, fmt.Errorf("failed to create L1 info tx: %w", err) + } +@@ -335,3 +392,34 @@ return nil, fmt.Errorf("failed to encode L1 info tx: %w", err) + } + return opaqueL1Tx, nil + } ++ ++func DepositsCompleteDeposit(seqNumber uint64, block eth.BlockInfo) (*types.DepositTx, error) { ++ source := AfterForceIncludeSource{ ++ L1BlockHash: block.Hash(), ++ SeqNumber: seqNumber, ++ } ++ out := &types.DepositTx{ ++ SourceHash: source.SourceHash(), ++ From: L1InfoDepositerAddress, ++ To: &L1BlockAddress, ++ Mint: nil, ++ Value: big.NewInt(0), ++ Gas: DepositsCompleteGas, ++ IsSystemTransaction: false, ++ Data: DepositsCompleteBytes4, ++ } ++ return out, nil ++} ++ ++func DepositsCompleteBytes(seqNumber uint64, l1Info eth.BlockInfo) ([]byte, error) { ++ dep, err := DepositsCompleteDeposit(seqNumber, l1Info) ++ if err != nil { ++ return nil, fmt.Errorf("failed to create DepositsComplete tx: %w", err) ++ } ++ depositsCompleteTx := types.NewTx(dep) ++ opaqueDepositsCompleteTx, err := depositsCompleteTx.MarshalBinary() ++ if err != nil { ++ return nil, fmt.Errorf("failed to encode DepositsComplete tx: %w", err) ++ } ++ return opaqueDepositsCompleteTx, nil ++}
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+93
+
-25
+ +
+ +
+
+
diff --git OP/op-node/rollup/derive/l1_block_info_test.go CELO/op-node/rollup/derive/l1_block_info_test.go +index e5c9253ce1c6567ad14fec3c2936610d3e47bc31..b98e8a7d4c6354acccdfb14a6bafb8ca8a1ce3c0 100644 +--- OP/op-node/rollup/derive/l1_block_info_test.go ++++ CELO/op-node/rollup/derive/l1_block_info_test.go +@@ -10,6 +10,7 @@ "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +  + "github.com/ethereum/go-ethereum/common" ++ "github.com/ethereum/go-ethereum/core/types" +  + "github.com/ethereum-optimism/optimism/op-node/rollup" + "github.com/ethereum-optimism/optimism/op-service/eth" +@@ -109,10 +110,8 @@ }) + t.Run("regolith", func(t *testing.T) { + rng := rand.New(rand.NewSource(1234)) + info := testutils.MakeBlockInfo(nil)(rng) +- zero := uint64(0) +- rollupCfg := rollup.Config{ +- RegolithTime: &zero, +- } ++ rollupCfg := rollup.Config{} ++ rollupCfg.ActivateAtGenesis(rollup.Regolith) + depTx, err := L1InfoDeposit(&rollupCfg, randomL1Cfg(rng, info), randomSeqNr(rng), info, 0) + require.NoError(t, err) + require.False(t, depTx.IsSystemTransaction) +@@ -121,27 +120,24 @@ }) + t.Run("ecotone", func(t *testing.T) { + rng := rand.New(rand.NewSource(1234)) + info := testutils.MakeBlockInfo(nil)(rng) +- zero := uint64(0) +- rollupCfg := rollup.Config{ +- RegolithTime: &zero, +- EcotoneTime: &zero, +- } +- depTx, err := L1InfoDeposit(&rollupCfg, randomL1Cfg(rng, info), randomSeqNr(rng), info, 1) ++ rollupCfg := rollup.Config{BlockTime: 2, Genesis: rollup.Genesis{L2Time: 1000}} ++ rollupCfg.ActivateAtGenesis(rollup.Ecotone) ++ // run 1 block after ecotone transition ++ timestamp := rollupCfg.Genesis.L2Time + rollupCfg.BlockTime ++ depTx, err := L1InfoDeposit(&rollupCfg, randomL1Cfg(rng, info), randomSeqNr(rng), info, timestamp) + require.NoError(t, err) + require.False(t, depTx.IsSystemTransaction) + require.Equal(t, depTx.Gas, uint64(RegolithSystemTxGas)) + require.Equal(t, L1InfoEcotoneLen, len(depTx.Data)) + }) +- t.Run("first-block ecotone", func(t *testing.T) { ++ t.Run("activation-block ecotone", func(t *testing.T) { + rng := rand.New(rand.NewSource(1234)) + info := testutils.MakeBlockInfo(nil)(rng) +- zero := uint64(2) +- rollupCfg := rollup.Config{ +- RegolithTime: &zero, +- EcotoneTime: &zero, +- BlockTime: 2, +- } +- depTx, err := L1InfoDeposit(&rollupCfg, randomL1Cfg(rng, info), randomSeqNr(rng), info, 2) ++ rollupCfg := rollup.Config{BlockTime: 2, Genesis: rollup.Genesis{L2Time: 1000}} ++ rollupCfg.ActivateAtGenesis(rollup.Delta) ++ ecotoneTime := rollupCfg.Genesis.L2Time + rollupCfg.BlockTime // activate ecotone just after genesis ++ rollupCfg.EcotoneTime = &ecotoneTime ++ depTx, err := L1InfoDeposit(&rollupCfg, randomL1Cfg(rng, info), randomSeqNr(rng), info, ecotoneTime) + require.NoError(t, err) + require.False(t, depTx.IsSystemTransaction) + require.Equal(t, depTx.Gas, uint64(RegolithSystemTxGas)) +@@ -150,16 +146,88 @@ }) + t.Run("genesis-block ecotone", func(t *testing.T) { + rng := rand.New(rand.NewSource(1234)) + info := testutils.MakeBlockInfo(nil)(rng) +- zero := uint64(0) +- rollupCfg := rollup.Config{ +- RegolithTime: &zero, +- EcotoneTime: &zero, +- BlockTime: 2, +- } +- depTx, err := L1InfoDeposit(&rollupCfg, randomL1Cfg(rng, info), randomSeqNr(rng), info, 0) ++ rollupCfg := rollup.Config{BlockTime: 2, Genesis: rollup.Genesis{L2Time: 1000}} ++ rollupCfg.ActivateAtGenesis(rollup.Ecotone) ++ depTx, err := L1InfoDeposit(&rollupCfg, randomL1Cfg(rng, info), randomSeqNr(rng), info, rollupCfg.Genesis.L2Time) + require.NoError(t, err) + require.False(t, depTx.IsSystemTransaction) + require.Equal(t, depTx.Gas, uint64(RegolithSystemTxGas)) + require.Equal(t, L1InfoEcotoneLen, len(depTx.Data)) ++ }) ++ t.Run("isthmus", func(t *testing.T) { ++ rng := rand.New(rand.NewSource(1234)) ++ info := testutils.MakeBlockInfo(nil)(rng) ++ rollupCfg := rollup.Config{BlockTime: 2, Genesis: rollup.Genesis{L2Time: 1000}} ++ rollupCfg.ActivateAtGenesis(rollup.Interop) ++ // run 1 block after interop transition ++ timestamp := rollupCfg.Genesis.L2Time + rollupCfg.BlockTime ++ depTx, err := L1InfoDeposit(&rollupCfg, randomL1Cfg(rng, info), randomSeqNr(rng), info, timestamp) ++ require.NoError(t, err) ++ require.False(t, depTx.IsSystemTransaction) ++ require.Equal(t, depTx.Gas, uint64(RegolithSystemTxGas)) ++ require.Equal(t, L1InfoEcotoneLen, len(depTx.Data), "the length is same in isthmus") ++ require.Equal(t, L1InfoFuncIsthmusBytes4, depTx.Data[:4], "upgrade is active, need isthmus signature") ++ }) ++ t.Run("activation-block isthmus", func(t *testing.T) { ++ rng := rand.New(rand.NewSource(1234)) ++ info := testutils.MakeBlockInfo(nil)(rng) ++ rollupCfg := rollup.Config{BlockTime: 2, Genesis: rollup.Genesis{L2Time: 1000}} ++ rollupCfg.ActivateAtGenesis(rollup.Fjord) ++ isthmusTime := rollupCfg.Genesis.L2Time + rollupCfg.BlockTime // activate isthmus just after genesis ++ rollupCfg.InteropTime = &isthmusTime ++ depTx, err := L1InfoDeposit(&rollupCfg, randomL1Cfg(rng, info), randomSeqNr(rng), info, isthmusTime) ++ require.NoError(t, err) ++ require.False(t, depTx.IsSystemTransaction) ++ require.Equal(t, depTx.Gas, uint64(RegolithSystemTxGas)) ++ // Isthmus activates, but ecotone L1 info is still used at this upgrade block ++ require.Equal(t, L1InfoEcotoneLen, len(depTx.Data)) ++ require.Equal(t, L1InfoFuncEcotoneBytes4, depTx.Data[:4]) ++ }) ++ t.Run("genesis-block isthmus", func(t *testing.T) { ++ rng := rand.New(rand.NewSource(1234)) ++ info := testutils.MakeBlockInfo(nil)(rng) ++ rollupCfg := rollup.Config{BlockTime: 2, Genesis: rollup.Genesis{L2Time: 1000}} ++ rollupCfg.ActivateAtGenesis(rollup.Interop) ++ depTx, err := L1InfoDeposit(&rollupCfg, randomL1Cfg(rng, info), randomSeqNr(rng), info, rollupCfg.Genesis.L2Time) ++ require.NoError(t, err) ++ require.False(t, depTx.IsSystemTransaction) ++ require.Equal(t, depTx.Gas, uint64(RegolithSystemTxGas)) ++ require.Equal(t, L1InfoEcotoneLen, len(depTx.Data)) ++ }) ++} ++ ++func TestDepositsCompleteBytes(t *testing.T) { ++ randomSeqNr := func(rng *rand.Rand) uint64 { ++ return rng.Uint64() ++ } ++ t.Run("valid return bytes", func(t *testing.T) { ++ rng := rand.New(rand.NewSource(1234)) ++ info := testutils.MakeBlockInfo(nil)(rng) ++ depTxByes, err := DepositsCompleteBytes(randomSeqNr(rng), info) ++ require.NoError(t, err) ++ var depTx types.Transaction ++ require.NoError(t, depTx.UnmarshalBinary(depTxByes)) ++ require.Equal(t, uint8(types.DepositTxType), depTx.Type()) ++ require.Equal(t, depTx.Data(), DepositsCompleteBytes4) ++ require.Equal(t, DepositsCompleteLen, len(depTx.Data())) ++ require.Equal(t, DepositsCompleteGas, depTx.Gas()) ++ require.False(t, depTx.IsSystemTx()) ++ require.Equal(t, depTx.Value(), big.NewInt(0)) ++ signer := types.LatestSignerForChainID(depTx.ChainId()) ++ sender, err := signer.Sender(&depTx) ++ require.NoError(t, err) ++ require.Equal(t, L1InfoDepositerAddress, sender) ++ }) ++ t.Run("valid return Transaction", func(t *testing.T) { ++ rng := rand.New(rand.NewSource(1234)) ++ info := testutils.MakeBlockInfo(nil)(rng) ++ depTx, err := DepositsCompleteDeposit(randomSeqNr(rng), info) ++ require.NoError(t, err) ++ require.Equal(t, depTx.Data, DepositsCompleteBytes4) ++ require.Equal(t, DepositsCompleteLen, len(depTx.Data)) ++ require.Equal(t, DepositsCompleteGas, depTx.Gas) ++ require.False(t, depTx.IsSystemTransaction) ++ require.Equal(t, depTx.Value, big.NewInt(0)) ++ require.Equal(t, L1InfoDepositerAddress, depTx.From) + }) + }
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+1
+
-1
+ +
+ +
+
+
diff --git OP/op-node/rollup/derive/pipeline.go CELO/op-node/rollup/derive/pipeline.go +index e4eae7e20303a4436808177432fe724157c2ba49..a06640086fdefd42226459b83f610d18af4ef37f 100644 +--- OP/op-node/rollup/derive/pipeline.go ++++ CELO/op-node/rollup/derive/pipeline.go +@@ -84,7 +84,7 @@ l1Traversal := NewL1Traversal(log, rollupCfg, l1Fetcher) + dataSrc := NewDataSourceFactory(log, rollupCfg, l1Fetcher, l1Blobs, altDA) // auxiliary stage for L1Retrieval + l1Src := NewL1Retrieval(log, dataSrc, l1Traversal) + frameQueue := NewFrameQueue(log, l1Src) +- bank := NewChannelBank(log, rollupCfg, frameQueue, l1Fetcher, metrics) ++ bank := NewChannelBank(log, rollupCfg, frameQueue, metrics) + chInReader := NewChannelInReader(rollupCfg, log, bank, metrics) + batchQueue := NewBatchQueue(log, rollupCfg, chInReader, l2Source) + attrBuilder := NewFetchingAttributesBuilder(rollupCfg, l1Fetcher, l2Source)
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+2
+
-3
+ +
+ +
+
+
diff --git OP/op-node/rollup/derive/span_channel_out.go CELO/op-node/rollup/derive/span_channel_out.go +index aa2eae04b2d197f24bc14ff0fde0895fcfbc99fc..9950fe29c413bf14a9951394b41825b5340b8c14 100644 +--- OP/op-node/rollup/derive/span_channel_out.go ++++ CELO/op-node/rollup/derive/span_channel_out.go +@@ -5,7 +5,6 @@ "bytes" + "crypto/rand" + "fmt" + "io" +- "math/big" +  + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/rlp" +@@ -65,11 +64,11 @@ co.maxBlocksPerSpanBatch = maxBlock + } + } +  +-func NewSpanChannelOut(genesisTimestamp uint64, chainID *big.Int, targetOutputSize uint64, compressionAlgo CompressionAlgo, chainSpec *rollup.ChainSpec, opts ...SpanChannelOutOption) (*SpanChannelOut, error) { ++func NewSpanChannelOut(targetOutputSize uint64, compressionAlgo CompressionAlgo, chainSpec *rollup.ChainSpec, opts ...SpanChannelOutOption) (*SpanChannelOut, error) { + c := &SpanChannelOut{ + id: ChannelID{}, + frame: 0, +- spanBatch: NewSpanBatch(genesisTimestamp, chainID), ++ spanBatch: NewSpanBatch(chainSpec.L2GenesisTime(), chainSpec.L2ChainID()), + rlp: [2]*bytes.Buffer{{}, {}}, + target: targetOutputSize, + chainSpec: chainSpec,
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+4
+
-0
+ +
+ +
+
+
diff --git OP/op-node/rollup/driver/config.go CELO/op-node/rollup/driver/config.go +index f4013b95e1de67a3c00c6d01d2886d2dc065e56e..3353db1eabe4dfc34880c1b03bf0c3d11d824ccc 100644 +--- OP/op-node/rollup/driver/config.go ++++ CELO/op-node/rollup/driver/config.go +@@ -20,4 +20,8 @@ + // SequencerMaxSafeLag is the maximum number of L2 blocks for restricting the distance between L2 safe and unsafe. + // Disabled if 0. + SequencerMaxSafeLag uint64 `json:"sequencer_max_safe_lag"` ++ ++ // SequencerUseFinalized is true when sequencer should use only finalized L1 blocks as origin. ++ // If this is set to true, the value of `SequencerConfDepth` is ignored. ++ SequencerUseFinalized bool `json:"sequencer_use_finalized"` + }
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+27
+
-16
+ +
+ +
+
+
diff --git OP/op-node/rollup/driver/driver.go CELO/op-node/rollup/driver/driver.go +index 3a3272387821babf62f5b7d69f871f98d3fa8825..c66dc9b46999c4973027e323f951abc5a0e52bd7 100644 +--- OP/op-node/rollup/driver/driver.go ++++ CELO/op-node/rollup/driver/driver.go +@@ -17,6 +17,8 @@ "github.com/ethereum-optimism/optimism/op-node/rollup/derive" + "github.com/ethereum-optimism/optimism/op-node/rollup/engine" + "github.com/ethereum-optimism/optimism/op-node/rollup/event" + "github.com/ethereum-optimism/optimism/op-node/rollup/finality" ++ "github.com/ethereum-optimism/optimism/op-node/rollup/finalized" ++ "github.com/ethereum-optimism/optimism/op-node/rollup/interop" + "github.com/ethereum-optimism/optimism/op-node/rollup/sequencing" + "github.com/ethereum-optimism/optimism/op-node/rollup/status" + "github.com/ethereum-optimism/optimism/op-node/rollup/sync" +@@ -149,12 +151,19 @@ SequencerStarted() error + SequencerStopped() error + } +  ++type Drain interface { ++ Drain() error ++} ++ + // NewDriver composes an events handler that tracks L1 state, triggers L2 Derivation, and optionally sequences new L2 blocks. + func NewDriver( ++ sys event.Registry, ++ drain Drain, + driverCfg *Config, + cfg *rollup.Config, + l2 L2Chain, + l1 L1Chain, ++ supervisor interop.InteropBackend, // may be nil pre-interop. + l1Blobs derive.L1BlobsFetcher, + altSync AltSync, + network Network, +@@ -168,18 +177,15 @@ altDA AltDAIface, + ) *Driver { + driverCtx, driverCancel := context.WithCancel(context.Background()) +  +- var executor event.Executor +- var drain func() error +- // This instantiation will be one of more options: soon there will be a parallel events executor +- { +- s := event.NewGlobalSynchronous(driverCtx) +- executor = s +- drain = s.Drain ++ opts := event.DefaultRegisterOpts() ++ ++ // If interop is scheduled we start the driver. ++ // It will then be ready to pick up verification work ++ // as soon as we reach the upgrade time (if the upgrade is not already active). ++ if cfg.InteropTime != nil { ++ interopDeriver := interop.NewInteropDeriver(log, cfg, driverCtx, supervisor, l2) ++ sys.Register("interop", interopDeriver, opts) + } +- sys := event.NewSystem(log, executor) +- sys.AddTracer(event.NewMetricsTracer(metrics)) +- +- opts := event.DefaultRegisterOpts() +  + statusTracker := status.NewStatusTracker(log, metrics) + sys.Register("status", statusTracker, opts) +@@ -226,7 +232,7 @@ L1: l1, + L2: l2, + Log: log, + Ctx: driverCtx, +- Drain: drain, ++ Drain: drain.Drain, + } + sys.Register("sync", syncDeriver, opts) +  +@@ -239,8 +245,14 @@ var sequencer sequencing.SequencerIface + if driverCfg.SequencerEnabled { + asyncGossiper := async.NewAsyncGossiper(driverCtx, network, log, metrics) + attrBuilder := derive.NewFetchingAttributesBuilder(cfg, l1, l2) +- sequencerConfDepth := confdepth.NewConfDepth(driverCfg.SequencerConfDepth, statusTracker.L1Head, l1) +- findL1Origin := sequencing.NewL1OriginSelector(log, cfg, sequencerConfDepth) ++ ++ var seqL1Blocks sequencing.L1Blocks ++ if driverCfg.SequencerUseFinalized { ++ seqL1Blocks = finalized.NewFinalized(statusTracker.L1Finalized, l1) ++ } else { ++ seqL1Blocks = confdepth.NewConfDepth(driverCfg.SequencerConfDepth, statusTracker.L1Head, l1) ++ } ++ findL1Origin := sequencing.NewL1OriginSelector(log, cfg, seqL1Blocks) + sequencer = sequencing.NewSequencer(driverCtx, log, cfg, attrBuilder, findL1Origin, + sequencerStateListener, sequencerConductor, asyncGossiper, metrics) + sys.Register("sequencer", sequencer, opts) +@@ -250,12 +262,11 @@ } +  + driverEmitter := sys.Register("driver", nil, opts) + driver := &Driver{ +- eventSys: sys, + statusTracker: statusTracker, + SyncDeriver: syncDeriver, + sched: schedDeriv, + emitter: driverEmitter, +- drain: drain, ++ drain: drain.Drain, + stateReq: make(chan chan struct{}), + forceReset: make(chan chan struct{}, 10), + driverConfig: driverCfg,
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+6
+
-24
+ +
+ +
+
+
diff --git OP/op-node/rollup/driver/state.go CELO/op-node/rollup/driver/state.go +index f851291bcb9cfbdcca2a7e3bd3f044a265060a9f..2840cedcf423c7daa8217750255cf5c6dbd7cd13 100644 +--- OP/op-node/rollup/driver/state.go ++++ CELO/op-node/rollup/driver/state.go +@@ -26,8 +26,6 @@ // Deprecated: use eth.SyncStatus instead. + type SyncStatus = eth.SyncStatus +  + type Driver struct { +- eventSys event.System +- + statusTracker SyncStatusTracker +  + *SyncDeriver +@@ -100,7 +98,6 @@ + func (s *Driver) Close() error { + s.driverCancel() + s.wg.Wait() +- s.eventSys.Stop() + s.sequencer.Close() + return nil + } +@@ -282,27 +279,6 @@ } + } + } +  +-// OnEvent handles broadcasted events. +-// The Driver itself is a deriver to catch system-critical events. +-// Other event-handling should be encapsulated into standalone derivers. +-func (s *Driver) OnEvent(ev event.Event) bool { +- switch x := ev.(type) { +- case rollup.CriticalErrorEvent: +- s.Log.Error("Derivation process critical error", "err", x.Err) +- // we need to unblock event-processing to be able to close +- go func() { +- logger := s.Log +- err := s.Close() +- if err != nil { +- logger.Error("Failed to shutdown driver on critical error", "err", err) +- } +- }() +- return true +- default: +- return false +- } +-} +- + type SyncDeriver struct { + // The derivation pipeline is reset whenever we reorg. + // The derivation pipeline determines the new l2Safe. +@@ -465,6 +441,12 @@ // Instead, we request the engine to repeat where its pending-safe head is at. + // Upon the pending-safe signal the attributes deriver can then ask the pipeline + // to generate new attributes, if no attributes are known already. + s.Emitter.Emit(engine.PendingSafeRequestEvent{}) ++ ++ // If interop is configured, we have to run the engine events, ++ // to ensure cross-L2 safety is continuously verified against the interop-backend. ++ if s.Config.InteropTime != nil { ++ s.Emitter.Emit(engine.CrossUpdateRequestEvent{}) ++ } + } +  + // ResetDerivationPipeline forces a reset of the derivation pipeline.
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+5
+
-0
+ +
+ +
+
+
diff --git OP/op-node/rollup/engine/build_start.go CELO/op-node/rollup/engine/build_start.go +index c1f9df5a98d6c82c93cd92ccb6f36721bbcfd31e..22c178d36cd0faad5364cd279c9eb4689fc4f9e5 100644 +--- OP/op-node/rollup/engine/build_start.go ++++ CELO/op-node/rollup/engine/build_start.go +@@ -34,6 +34,11 @@ UnsafeL2Head: ev.Attributes.Parent, + SafeL2Head: eq.ec.safeHead, + FinalizedL2Head: eq.ec.finalizedHead, + } ++ if fcEvent.UnsafeL2Head.Number < fcEvent.FinalizedL2Head.Number { ++ err := fmt.Errorf("invalid block-building pre-state, unsafe head %s is behind finalized head %s", fcEvent.UnsafeL2Head, fcEvent.FinalizedL2Head) ++ eq.emitter.Emit(rollup.CriticalErrorEvent{Err: err}) // make the node exit, things are very wrong. ++ return ++ } + fc := eth.ForkchoiceState{ + HeadBlockHash: fcEvent.UnsafeL2Head.Hash, + SafeBlockHash: fcEvent.SafeL2Head.Hash,
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+53
+
-8
+ +
+ +
+
+
diff --git OP/op-node/rollup/engine/engine_controller.go CELO/op-node/rollup/engine/engine_controller.go +index d8db9cad949c639c198e4df8414152bf23192f72..4ac8b88a50cf4352d9cb72509e3accaebb88ae2a 100644 +--- OP/op-node/rollup/engine/engine_controller.go ++++ CELO/op-node/rollup/engine/engine_controller.go +@@ -25,7 +25,7 @@ syncStatusCL syncStatusEnum = iota + // We transition between the 4 EL states linearly. We spend the majority of the time in the second & fourth. + // We only want to EL sync if there is no finalized block & once we finish EL sync we need to mark the last block + // as finalized so we can switch to consolidation +- // TODO(protocol-quest/91): We can restart EL sync & still consolidate if there finalized blocks on the execution client if the ++ // TODO(protocol-quest#91): We can restart EL sync & still consolidate if there finalized blocks on the execution client if the + // execution client is running in archive mode. In some cases we may want to switch back from CL to EL sync, but that is complicated. + syncStatusWillStartEL // First if we are directed to EL sync, check that nothing has been finalized yet + syncStatusStartedEL // Perform our EL sync +@@ -56,12 +56,27 @@ + emitter event.Emitter +  + // Block Head State +- unsafeHead eth.L2BlockRef +- pendingSafeHead eth.L2BlockRef // L2 block processed from the middle of a span batch, but not marked as the safe block yet. +- safeHead eth.L2BlockRef +- finalizedHead eth.L2BlockRef ++ unsafeHead eth.L2BlockRef ++ // Cross-verified unsafeHead, always equal to unsafeHead pre-interop ++ crossUnsafeHead eth.L2BlockRef ++ // Pending localSafeHead ++ // L2 block processed from the middle of a span batch, ++ // but not marked as the safe block yet. ++ pendingSafeHead eth.L2BlockRef ++ // Derived from L1, and known to be a completed span-batch, ++ // but not cross-verified yet. ++ localSafeHead eth.L2BlockRef ++ // Derived from L1 and cross-verified to have cross-safe dependencies. ++ safeHead eth.L2BlockRef ++ // Derived from finalized L1 data, ++ // and cross-verified to only have finalized dependencies. ++ finalizedHead eth.L2BlockRef ++ // The unsafe head to roll back to, ++ // after the pendingSafeHead fails to become safe. ++ // This is changing in the Holocene fork. + backupUnsafeHead eth.L2BlockRef +- needFCUCall bool ++ ++ needFCUCall bool + // Track when the rollup node changes the forkchoice to restore previous + // known unsafe chain. e.g. Unsafe Reorg caused by Invalid span batch. + // This update does not retry except engine returns non-input error +@@ -94,12 +109,20 @@ // State Getters +  + func (e *EngineController) UnsafeL2Head() eth.L2BlockRef { + return e.unsafeHead ++} ++ ++func (e *EngineController) CrossUnsafeL2Head() eth.L2BlockRef { ++ return e.crossUnsafeHead + } +  + func (e *EngineController) PendingSafeL2Head() eth.L2BlockRef { + return e.pendingSafeHead + } +  ++func (e *EngineController) LocalSafeL2Head() eth.L2BlockRef { ++ return e.localSafeHead ++} ++ + func (e *EngineController) SafeL2Head() eth.L2BlockRef { + return e.safeHead + } +@@ -131,14 +154,20 @@ e.metrics.RecordL2Ref("l2_pending_safe", r) + e.pendingSafeHead = r + } +  +-// SetSafeHead implements LocalEngineControl. ++// SetLocalSafeHead sets the local-safe head. ++func (e *EngineController) SetLocalSafeHead(r eth.L2BlockRef) { ++ e.metrics.RecordL2Ref("l2_local_safe", r) ++ e.localSafeHead = r ++} ++ ++// SetSafeHead sets the cross-safe head. + func (e *EngineController) SetSafeHead(r eth.L2BlockRef) { + e.metrics.RecordL2Ref("l2_safe", r) + e.safeHead = r + e.needFCUCall = true + } +  +-// SetUnsafeHead implements LocalEngineControl. ++// SetUnsafeHead sets the local-unsafe head. + func (e *EngineController) SetUnsafeHead(r eth.L2BlockRef) { + e.metrics.RecordL2Ref("l2_unsafe", r) + e.unsafeHead = r +@@ -146,6 +175,12 @@ e.needFCUCall = true + e.chainSpec.CheckForkActivation(e.log, r) + } +  ++// SetCrossUnsafeHead the cross-unsafe head. ++func (e *EngineController) SetCrossUnsafeHead(r eth.L2BlockRef) { ++ e.metrics.RecordL2Ref("l2_cross_unsafe", r) ++ e.crossUnsafeHead = r ++} ++ + // SetBackupUnsafeL2Head implements LocalEngineControl. + func (e *EngineController) SetBackupUnsafeL2Head(r eth.L2BlockRef, triggerReorg bool) { + e.metrics.RecordL2Ref("l2_backup_unsafe", r) +@@ -234,6 +269,11 @@ } + if e.IsEngineSyncing() { + e.log.Warn("Attempting to update forkchoice state while EL syncing") + } ++ if e.unsafeHead.Number < e.finalizedHead.Number { ++ err := fmt.Errorf("invalid forkchoice state, unsafe head %s is behind finalized head %s", e.unsafeHead, e.finalizedHead) ++ e.emitter.Emit(rollup.CriticalErrorEvent{Err: err}) // make the node exit, things are very wrong. ++ return err ++ } + fc := eth.ForkchoiceState{ + HeadBlockHash: e.unsafeHead.Hash, + SafeBlockHash: e.safeHead.Hash, +@@ -310,7 +350,11 @@ } + if e.syncStatus == syncStatusFinishedELButNotFinalized { + fc.SafeBlockHash = envelope.ExecutionPayload.BlockHash + fc.FinalizedBlockHash = envelope.ExecutionPayload.BlockHash ++ e.SetUnsafeHead(ref) // ensure that the unsafe head stays ahead of safe/finalized labels. ++ e.emitter.Emit(UnsafeUpdateEvent{Ref: ref}) ++ e.SetLocalSafeHead(ref) + e.SetSafeHead(ref) ++ e.emitter.Emit(CrossSafeUpdateEvent{LocalSafe: ref, CrossSafe: ref}) + e.SetFinalizedHead(ref) + } + logFn := e.logSyncProgressMaybe() +@@ -336,6 +380,7 @@ payload.ID(), payload.ParentID(), eth.ForkchoiceUpdateErr(fcRes.PayloadStatus))) + } + e.SetUnsafeHead(ref) + e.needFCUCall = false ++ e.emitter.Emit(UnsafeUpdateEvent{Ref: ref}) +  + if e.syncStatus == syncStatusFinishedELButNotFinalized { + e.log.Info("Finished EL sync", "sync_duration", e.clock.Since(e.elStart), "finalized_block", ref.ID().String())
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+1
+
-1
+ +
+ +
+
+
diff --git OP/op-node/rollup/engine/engine_update.go CELO/op-node/rollup/engine/engine_update.go +index 8f100709bcc16e75d6e52711b65816c15e4f2015..c79dbdcd0f4d0041a9eda2213841018bf75dd588 100644 +--- OP/op-node/rollup/engine/engine_update.go ++++ CELO/op-node/rollup/engine/engine_update.go +@@ -104,7 +104,7 @@ } + } +  + switch fcRes.PayloadStatus.Status { +- // TODO(proto): snap sync - specify explicit different error type if node is syncing ++ // TODO: snap sync - specify explicit different error type if node is syncing + case eth.ExecutionInvalid, eth.ExecutionInvalidBlockHash: + return eth.PayloadID{}, BlockInsertPayloadErr, eth.ForkchoiceUpdateErr(fcRes.PayloadStatus) + case eth.ExecutionValid:
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+178
+
-7
+ +
+ +
+
+
diff --git OP/op-node/rollup/engine/events.go CELO/op-node/rollup/engine/events.go +index 325118825fcee27fff5947714101da39d96a2757..b5e010280ebc9a1a25a0654e784a70785034b4a7 100644 +--- OP/op-node/rollup/engine/events.go ++++ CELO/op-node/rollup/engine/events.go +@@ -40,6 +40,55 @@ func (ev ForkchoiceUpdateEvent) String() string { + return "forkchoice-update" + } +  ++// PromoteUnsafeEvent signals that the given block may now become a canonical unsafe block. ++// This is pre-forkchoice update; the change may not be reflected yet in the EL. ++// Note that the legacy pre-event-refactor code-path (processing P2P blocks) does fire this, ++// but manually, duplicate with the newer events processing code-path. ++// See EngineController.InsertUnsafePayload. ++type PromoteUnsafeEvent struct { ++ Ref eth.L2BlockRef ++} ++ ++func (ev PromoteUnsafeEvent) String() string { ++ return "promote-unsafe" ++} ++ ++// RequestCrossUnsafeEvent signals that a CrossUnsafeUpdateEvent is needed. ++type RequestCrossUnsafeEvent struct{} ++ ++func (ev RequestCrossUnsafeEvent) String() string { ++ return "request-cross-unsafe" ++} ++ ++// UnsafeUpdateEvent signals that the given block is now considered safe. ++// This is pre-forkchoice update; the change may not be reflected yet in the EL. ++type UnsafeUpdateEvent struct { ++ Ref eth.L2BlockRef ++} ++ ++func (ev UnsafeUpdateEvent) String() string { ++ return "unsafe-update" ++} ++ ++// PromoteCrossUnsafeEvent signals that the given block may be promoted to cross-unsafe. ++type PromoteCrossUnsafeEvent struct { ++ Ref eth.L2BlockRef ++} ++ ++func (ev PromoteCrossUnsafeEvent) String() string { ++ return "promote-cross-unsafe" ++} ++ ++// CrossUnsafeUpdateEvent signals that the given block is now considered cross-unsafe. ++type CrossUnsafeUpdateEvent struct { ++ CrossUnsafe eth.L2BlockRef ++ LocalUnsafe eth.L2BlockRef ++} ++ ++func (ev CrossUnsafeUpdateEvent) String() string { ++ return "cross-unsafe-update" ++} ++ + type PendingSafeUpdateEvent struct { + PendingSafe eth.L2BlockRef + Unsafe eth.L2BlockRef // tip, added to the signal, to determine if there are existing blocks to consolidate +@@ -60,7 +109,54 @@ func (ev PromotePendingSafeEvent) String() string { + return "promote-pending-safe" + } +  +-// SafeDerivedEvent signals that a block was determined to be safe, and derived from the given L1 block ++// PromoteLocalSafeEvent signals that a block can be promoted to local-safe. ++type PromoteLocalSafeEvent struct { ++ Ref eth.L2BlockRef ++ DerivedFrom eth.L1BlockRef ++} ++ ++func (ev PromoteLocalSafeEvent) String() string { ++ return "promote-local-safe" ++} ++ ++// RequestCrossSafeEvent signals that a CrossSafeUpdate is needed. ++type RequestCrossSafeEvent struct{} ++ ++func (ev RequestCrossSafeEvent) String() string { ++ return "request-cross-safe-update" ++} ++ ++type CrossSafeUpdateEvent struct { ++ CrossSafe eth.L2BlockRef ++ LocalSafe eth.L2BlockRef ++} ++ ++func (ev CrossSafeUpdateEvent) String() string { ++ return "cross-safe-update" ++} ++ ++// LocalSafeUpdateEvent signals that a block is now considered to be local-safe. ++type LocalSafeUpdateEvent struct { ++ Ref eth.L2BlockRef ++ DerivedFrom eth.L1BlockRef ++} ++ ++func (ev LocalSafeUpdateEvent) String() string { ++ return "local-safe-update" ++} ++ ++// PromoteSafeEvent signals that a block can be promoted to cross-safe. ++type PromoteSafeEvent struct { ++ Ref eth.L2BlockRef ++ DerivedFrom eth.L1BlockRef ++} ++ ++func (ev PromoteSafeEvent) String() string { ++ return "promote-safe" ++} ++ ++// SafeDerivedEvent signals that a block was determined to be safe, and derived from the given L1 block. ++// This is signaled upon successful processing of PromoteSafeEvent. + type SafeDerivedEvent struct { + Safe eth.L2BlockRef + DerivedFrom eth.L1BlockRef +@@ -131,6 +227,16 @@ } +  + func (ev PromoteFinalizedEvent) String() string { + return "promote-finalized" ++} ++ ++// CrossUpdateRequestEvent triggers update events to be emitted, repeating the current state. ++type CrossUpdateRequestEvent struct { ++ CrossUnsafe bool ++ CrossSafe bool ++} ++ ++func (ev CrossUpdateRequestEvent) String() string { ++ return "cross-update-request" + } +  + type EngDeriver struct { +@@ -234,6 +340,36 @@ log.Debug("Reset of Engine is completed", + "safeHead", x.Safe, "unsafe", x.Unsafe, "safe_timestamp", x.Safe.Time, + "unsafe_timestamp", x.Unsafe.Time) + d.emitter.Emit(EngineResetConfirmedEvent(x)) ++ case PromoteUnsafeEvent: ++ // Backup unsafeHead when new block is not built on original unsafe head. ++ if d.ec.unsafeHead.Number >= x.Ref.Number { ++ d.ec.SetBackupUnsafeL2Head(d.ec.unsafeHead, false) ++ } ++ d.ec.SetUnsafeHead(x.Ref) ++ d.emitter.Emit(UnsafeUpdateEvent(x)) ++ case UnsafeUpdateEvent: ++ // pre-interop everything that is local-unsafe is also immediately cross-unsafe. ++ if !d.cfg.IsInterop(x.Ref.Time) { ++ d.emitter.Emit(PromoteCrossUnsafeEvent(x)) ++ } ++ // Try to apply the forkchoice changes ++ d.emitter.Emit(TryUpdateEngineEvent{}) ++ case PromoteCrossUnsafeEvent: ++ d.ec.SetCrossUnsafeHead(x.Ref) ++ d.emitter.Emit(CrossUnsafeUpdateEvent{ ++ CrossUnsafe: x.Ref, ++ LocalUnsafe: d.ec.UnsafeL2Head(), ++ }) ++ case RequestCrossUnsafeEvent: ++ d.emitter.Emit(CrossUnsafeUpdateEvent{ ++ CrossUnsafe: d.ec.CrossUnsafeL2Head(), ++ LocalUnsafe: d.ec.UnsafeL2Head(), ++ }) ++ case RequestCrossSafeEvent: ++ d.emitter.Emit(CrossSafeUpdateEvent{ ++ CrossSafe: d.ec.SafeL2Head(), ++ LocalSafe: d.ec.LocalSafeL2Head(), ++ }) + case PendingSafeRequestEvent: + d.emitter.Emit(PendingSafeUpdateEvent{ + PendingSafe: d.ec.PendingSafeL2Head(), +@@ -249,12 +385,30 @@ PendingSafe: d.ec.PendingSafeL2Head(), + Unsafe: d.ec.UnsafeL2Head(), + }) + } +- if x.Safe && x.Ref.Number > d.ec.SafeL2Head().Number { +- d.ec.SetSafeHead(x.Ref) +- d.emitter.Emit(SafeDerivedEvent{Safe: x.Ref, DerivedFrom: x.DerivedFrom}) +- // Try to apply the forkchoice changes +- d.emitter.Emit(TryUpdateEngineEvent{}) ++ if x.Safe && x.Ref.Number > d.ec.LocalSafeL2Head().Number { ++ d.emitter.Emit(PromoteLocalSafeEvent{ ++ Ref: x.Ref, ++ DerivedFrom: x.DerivedFrom, ++ }) ++ } ++ case PromoteLocalSafeEvent: ++ d.ec.SetLocalSafeHead(x.Ref) ++ d.emitter.Emit(LocalSafeUpdateEvent(x)) ++ case LocalSafeUpdateEvent: ++ // pre-interop everything that is local-safe is also immediately cross-safe. ++ if !d.cfg.IsInterop(x.Ref.Time) { ++ d.emitter.Emit(PromoteSafeEvent(x)) + } ++ case PromoteSafeEvent: ++ d.ec.SetSafeHead(x.Ref) ++ // Finalizer can pick up this safe cross-block now ++ d.emitter.Emit(SafeDerivedEvent{Safe: x.Ref, DerivedFrom: x.DerivedFrom}) ++ d.emitter.Emit(CrossSafeUpdateEvent{ ++ CrossSafe: d.ec.SafeL2Head(), ++ LocalSafe: d.ec.LocalSafeL2Head(), ++ }) ++ // Try to apply the forkchoice changes ++ d.emitter.Emit(TryUpdateEngineEvent{}) + case PromoteFinalizedEvent: + if x.Ref.Number < d.ec.Finalized().Number { + d.log.Error("Cannot rewind finality,", "ref", x.Ref, "finalized", d.ec.Finalized()) +@@ -267,6 +421,19 @@ } + d.ec.SetFinalizedHead(x.Ref) + // Try to apply the forkchoice changes + d.emitter.Emit(TryUpdateEngineEvent{}) ++ case CrossUpdateRequestEvent: ++ if x.CrossUnsafe { ++ d.emitter.Emit(CrossUnsafeUpdateEvent{ ++ CrossUnsafe: d.ec.CrossUnsafeL2Head(), ++ LocalUnsafe: d.ec.UnsafeL2Head(), ++ }) ++ } ++ if x.CrossSafe { ++ d.emitter.Emit(CrossSafeUpdateEvent{ ++ CrossSafe: d.ec.SafeL2Head(), ++ LocalSafe: d.ec.LocalSafeL2Head(), ++ }) ++ } + case BuildStartEvent: + d.onBuildStart(x) + case BuildStartedEvent: +@@ -295,6 +462,8 @@ type ResetEngineControl interface { + SetUnsafeHead(eth.L2BlockRef) + SetSafeHead(eth.L2BlockRef) + SetFinalizedHead(eth.L2BlockRef) ++ SetLocalSafeHead(ref eth.L2BlockRef) ++ SetCrossUnsafeHead(ref eth.L2BlockRef) + SetBackupUnsafeL2Head(block eth.L2BlockRef, triggerReorg bool) + SetPendingSafeL2Head(eth.L2BlockRef) + } +@@ -302,8 +471,10 @@ + // ForceEngineReset is not to be used. The op-program needs it for now, until event processing is adopted there. + func ForceEngineReset(ec ResetEngineControl, x ForceEngineResetEvent) { + ec.SetUnsafeHead(x.Unsafe) +- ec.SetSafeHead(x.Safe) ++ ec.SetLocalSafeHead(x.Safe) + ec.SetPendingSafeL2Head(x.Safe) + ec.SetFinalizedHead(x.Finalized) ++ ec.SetSafeHead(x.Safe) ++ ec.SetCrossUnsafeHead(x.Safe) + ec.SetBackupUnsafeL2Head(eth.L2BlockRef{}, false) + }
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+5
+
-14
+ +
+ +
+
+
diff --git OP/op-node/rollup/engine/payload_success.go CELO/op-node/rollup/engine/payload_success.go +index cdd2ee2d030b36224e7521d42c0b14bcc510ddcd..7bb4a38307e13eb2c8a687cb5f601d7ea1f0961c 100644 +--- OP/op-node/rollup/engine/payload_success.go ++++ CELO/op-node/rollup/engine/payload_success.go +@@ -19,23 +19,14 @@ return "payload-success" + } +  + func (eq *EngDeriver) onPayloadSuccess(ev PayloadSuccessEvent) { +- +- // Backup unsafeHead when new block is not built on original unsafe head. +- if eq.ec.unsafeHead.Number >= ev.Ref.Number { +- eq.ec.SetBackupUnsafeL2Head(eq.ec.unsafeHead, false) +- } +- eq.ec.SetUnsafeHead(ev.Ref) ++ eq.emitter.Emit(PromoteUnsafeEvent{Ref: ev.Ref}) +  + // If derived from L1, then it can be considered (pending) safe + if ev.DerivedFrom != (eth.L1BlockRef{}) { +- if ev.IsLastInSpan { +- eq.ec.SetSafeHead(ev.Ref) +- eq.emitter.Emit(SafeDerivedEvent{Safe: ev.Ref, DerivedFrom: ev.DerivedFrom}) +- } +- eq.ec.SetPendingSafeL2Head(ev.Ref) +- eq.emitter.Emit(PendingSafeUpdateEvent{ +- PendingSafe: eq.ec.PendingSafeL2Head(), +- Unsafe: eq.ec.UnsafeL2Head(), ++ eq.emitter.Emit(PromotePendingSafeEvent{ ++ Ref: ev.Ref, ++ Safe: ev.IsLastInSpan, ++ DerivedFrom: ev.DerivedFrom, + }) + } +
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+2
+
-9
+ +
+ +
+
+
diff --git OP/op-node/rollup/event.go CELO/op-node/rollup/event.go +index bcab847451d8d8f68877100481a0dc0ff857cf77..3d12c34a9f6b4f66376a6a8fc76a6f25f58e0c03 100644 +--- OP/op-node/rollup/event.go ++++ CELO/op-node/rollup/event.go +@@ -37,12 +37,5 @@ func (ev ResetEvent) String() string { + return "reset-event" + } +  +-type CriticalErrorEvent struct { +- Err error +-} +- +-var _ event.Event = CriticalErrorEvent{} +- +-func (ev CriticalErrorEvent) String() string { +- return "critical-error" +-} ++// CriticalErrorEvent is an alias for event.CriticalErrorEvent ++type CriticalErrorEvent = event.CriticalErrorEvent
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+10
+
-0
+ +
+ +
+
+
diff --git OP/op-node/rollup/event/events.go CELO/op-node/rollup/event/events.go +index ac550e203e5518d8377993b2dcd8dae558919ae0..6fed3859a64eea074bcf72e8f921deae7bdeaf82 100644 +--- OP/op-node/rollup/event/events.go ++++ CELO/op-node/rollup/event/events.go +@@ -75,3 +75,13 @@ + type NoopEmitter struct{} +  + func (e NoopEmitter) Emit(ev Event) {} ++ ++type CriticalErrorEvent struct { ++ Err error ++} ++ ++var _ Event = CriticalErrorEvent{} ++ ++func (ev CriticalErrorEvent) String() string { ++ return "critical-error" ++}
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+18
+
-1
+ +
+ +
+
+
diff --git OP/op-node/rollup/event/system.go CELO/op-node/rollup/event/system.go +index 3b59b89651b3ecf0ab72c959409c15148e49bf94..566f28fdbe4021dc94b0fd5b7bbbec93337dec48 100644 +--- OP/op-node/rollup/event/system.go ++++ CELO/op-node/rollup/event/system.go +@@ -11,7 +11,7 @@ + "github.com/ethereum/go-ethereum/log" + ) +  +-type System interface { ++type Registry interface { + // Register registers a named event-emitter, optionally processing events itself: + // deriver may be nil, not all registrants have to process events. + // A non-nil deriver may implement AttachEmitter to automatically attach the Emitter to it, +@@ -20,6 +20,10 @@ Register(name string, deriver Deriver, opts *RegisterOpts) Emitter + // Unregister removes a named emitter, + // also removing it from the set of events-receiving derivers (if registered with non-nil deriver). + Unregister(name string) (old Emitter) ++} ++ ++type System interface { ++ Registry + // AddTracer registers a tracer to capture all event deriver/emitter work. It runs until RemoveTracer is called. + // Duplicate tracers are allowed. + AddTracer(t Tracer) +@@ -73,6 +77,10 @@ } + if r.ctx.Err() != nil { + return + } ++ if r.sys.abort.Load() && !Is[CriticalErrorEvent](ev.Event) { ++ // if aborting, and not the CriticalErrorEvent itself, then do not process the event ++ return ++ } +  + prev := r.currentEvent + start := time.Now() +@@ -99,6 +107,9 @@ emitContext atomic.Uint64 +  + tracers []Tracer + tracersLock sync.RWMutex ++ ++ // if true, no events may be processed, except CriticalError itself ++ abort atomic.Bool + } +  + func NewSystem(log log.Logger, ex Executor) *Sys { +@@ -239,6 +250,12 @@ // The name of the emitter is provided to further contextualize the event. + func (s *Sys) emit(name string, derivContext uint64, ev Event) { + emitContext := s.emitContext.Add(1) + annotated := AnnotatedEvent{Event: ev, EmitContext: emitContext} ++ ++ // As soon as anything emits a critical event, ++ // make the system aware, before the executor event schedules it for processing. ++ if Is[CriticalErrorEvent](ev) { ++ s.abort.Store(true) ++ } +  + emitTime := time.Now() + s.recordEmit(name, annotated, derivContext, emitTime)
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+44
+
-0
+ +
+ +
+
+
diff --git OP/op-node/rollup/event/system_test.go CELO/op-node/rollup/event/system_test.go +index 9feef96285319b406970fa06ca26f82e1ffc6ecd..749eb681a75c43cbef22f874690de09b702b4b3b 100644 +--- OP/op-node/rollup/event/system_test.go ++++ CELO/op-node/rollup/event/system_test.go +@@ -2,6 +2,7 @@ package event +  + import ( + "context" ++ "errors" + "testing" +  + "github.com/stretchr/testify/require" +@@ -104,3 +105,46 @@ require.NoError(t, ex.Drain()) + require.Equal(t, 3, fooCount) + require.Equal(t, 3, barCount) + } ++ ++func TestCriticalError(t *testing.T) { ++ logger := testlog.Logger(t, log.LevelError) ++ count := 0 ++ seenCrit := 0 ++ deriverFn := DeriverFunc(func(ev Event) bool { ++ switch ev.(type) { ++ case CriticalErrorEvent: ++ seenCrit += 1 ++ default: ++ count += 1 ++ } ++ return true ++ }) ++ exec := NewGlobalSynchronous(context.Background()) ++ sys := NewSystem(logger, exec) ++ emitterA := sys.Register("a", deriverFn, DefaultRegisterOpts()) ++ emitterB := sys.Register("b", deriverFn, DefaultRegisterOpts()) ++ ++ require.NoError(t, exec.Drain(), "can drain, even if empty") ++ emitterA.Emit(TestEvent{}) ++ require.Equal(t, 0, count, "no processing yet, queued event") ++ require.NoError(t, exec.Drain()) ++ require.Equal(t, 2, count, "both A and B processed the event") ++ ++ emitterA.Emit(TestEvent{}) ++ emitterB.Emit(TestEvent{}) ++ testErr := errors.New("test crit error") ++ emitterB.Emit(CriticalErrorEvent{Err: testErr}) ++ require.Equal(t, 2, count, "no processing yet, queued events") ++ require.Equal(t, 0, seenCrit, "critical error events are still scheduled like normal") ++ require.True(t, sys.abort.Load(), "we are aware of the crit") ++ require.NoError(t, exec.Drain()) ++ require.Equal(t, 2, count, "still no processing, since we hit a crit error, the events are ignored") ++ require.Equal(t, 2, seenCrit, "but everyone has seen the crit now") ++ ++ // We are able to stop the processing now ++ sys.Stop() ++ ++ emitterA.Emit(TestEvent{}) ++ require.NoError(t, exec.Drain(), "system is closed, no further event processing") ++ require.Equal(t, 2, count) ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+29
+
-0
+ +
+ +
+
+
diff --git OP/op-node/rollup/finalized/finalized.go CELO/op-node/rollup/finalized/finalized.go +new file mode 100644 +index 0000000000000000000000000000000000000000..47fbcc077e4f3726ce6ae66ad678ee3f5d21e149 +--- /dev/null ++++ CELO/op-node/rollup/finalized/finalized.go +@@ -0,0 +1,29 @@ ++package finalized ++ ++import ( ++ "context" ++ ++ "github.com/ethereum/go-ethereum" ++ ++ "github.com/ethereum-optimism/optimism/op-node/rollup/derive" ++ "github.com/ethereum-optimism/optimism/op-service/eth" ++) ++ ++type finalized struct { ++ derive.L1Fetcher ++ l1Finalized func() eth.L1BlockRef ++} ++ ++func NewFinalized(l1Finalized func() eth.L1BlockRef, fetcher derive.L1Fetcher) *finalized { ++ return &finalized{L1Fetcher: fetcher, l1Finalized: l1Finalized} ++} ++ ++func (f *finalized) L1BlockRefByNumber(ctx context.Context, num uint64) (eth.L1BlockRef, error) { ++ l1Finalized := f.l1Finalized() ++ if num == 0 || num <= l1Finalized.Number { ++ return f.L1Fetcher.L1BlockRefByNumber(ctx, num) ++ } ++ return eth.L1BlockRef{}, ethereum.NotFound ++} ++ ++var _ derive.L1Fetcher = (*finalized)(nil)
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+58
+
-0
+ +
+ +
+
+
diff --git OP/op-node/rollup/finalized/finalized_test.go CELO/op-node/rollup/finalized/finalized_test.go +new file mode 100644 +index 0000000000000000000000000000000000000000..8fa397bf076ce5bbe754438d56d0dd13664c0be7 +--- /dev/null ++++ CELO/op-node/rollup/finalized/finalized_test.go +@@ -0,0 +1,58 @@ ++package finalized ++ ++import ( ++ "context" ++ "testing" ++ ++ "github.com/ethereum/go-ethereum" ++ "github.com/ethereum/go-ethereum/common" ++ "github.com/stretchr/testify/require" ++ ++ "github.com/ethereum-optimism/optimism/op-service/eth" ++ "github.com/ethereum-optimism/optimism/op-service/testutils" ++) ++ ++var testFinalHash = common.Hash{0x01} ++ ++type finalizedTest struct { ++ name string ++ final uint64 ++ hash common.Hash // hash of finalized block ++ req uint64 ++ pass bool ++} ++ ++func (ft *finalizedTest) Run(t *testing.T) { ++ l1Fetcher := &testutils.MockL1Source{} ++ l1Finalized := eth.L1BlockRef{Number: ft.final, Hash: ft.hash} ++ l1FinalizedGetter := func() eth.L1BlockRef { return l1Finalized } ++ ++ f := NewFinalized(l1FinalizedGetter, l1Fetcher) ++ ++ if ft.pass { ++ // no calls to the l1Fetcher are made if the block number is not finalized yet ++ l1Fetcher.ExpectL1BlockRefByNumber(ft.req, eth.L1BlockRef{Number: ft.req}, nil) ++ } ++ ++ out, err := f.L1BlockRefByNumber(context.Background(), ft.req) ++ l1Fetcher.AssertExpectations(t) ++ ++ if ft.pass { ++ require.NoError(t, err) ++ require.Equal(t, out, eth.L1BlockRef{Number: ft.req}) ++ } else { ++ require.Equal(t, ethereum.NotFound, err) ++ } ++} ++ ++func TestFinalized(t *testing.T) { ++ testCases := []finalizedTest{ ++ {name: "finalized", final: 10, hash: testFinalHash, req: 10, pass: true}, ++ {name: "finalized past", final: 10, hash: testFinalHash, req: 8, pass: true}, ++ {name: "not finalized", final: 10, hash: testFinalHash, req: 11, pass: false}, ++ {name: "no L1 state", req: 10, pass: false}, ++ } ++ for _, tc := range testCases { ++ t.Run(tc.name, tc.Run) ++ } ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+161
+
-0
+ +
+ +
+
+
diff --git OP/op-node/rollup/interop/interop.go CELO/op-node/rollup/interop/interop.go +new file mode 100644 +index 0000000000000000000000000000000000000000..c6c170478f21e0a2614a49a89f074933c7309b0b +--- /dev/null ++++ CELO/op-node/rollup/interop/interop.go +@@ -0,0 +1,161 @@ ++package interop ++ ++import ( ++ "context" ++ "sync" ++ "time" ++ ++ "github.com/ethereum/go-ethereum/common" ++ "github.com/ethereum/go-ethereum/log" ++ ++ "github.com/ethereum-optimism/optimism/op-node/rollup" ++ "github.com/ethereum-optimism/optimism/op-node/rollup/engine" ++ "github.com/ethereum-optimism/optimism/op-node/rollup/event" ++ "github.com/ethereum-optimism/optimism/op-service/eth" ++ "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" ++) ++ ++const checkBlockTimeout = time.Second * 10 ++ ++type InteropBackend interface { ++ CheckBlock(ctx context.Context, ++ chainID types.ChainID, blockHash common.Hash, blockNumber uint64) (types.SafetyLevel, error) ++} ++ ++type L2Source interface { ++ L2BlockRefByNumber(context.Context, uint64) (eth.L2BlockRef, error) ++} ++ ++// InteropDeriver watches for update events (either real changes to block safety, ++// or updates published upon request), checks if there is some local data to cross-verify, ++// and then checks with the interop-backend, to try to promote to cross-verified safety. ++type InteropDeriver struct { ++ log log.Logger ++ cfg *rollup.Config ++ ++ // we cache the chainID, ++ // to not continuously convert from the type in the rollup-config to this type. ++ chainID types.ChainID ++ ++ driverCtx context.Context ++ ++ // L2 blockhash -> derived from L1 block ref. ++ // Added to when a block is local-safe. ++ // Removed from when it is promoted to cross-safe. ++ derivedFrom map[common.Hash]eth.L1BlockRef ++ ++ backend InteropBackend ++ l2 L2Source ++ ++ emitter event.Emitter ++ ++ mu sync.Mutex ++} ++ ++var _ event.Deriver = (*InteropDeriver)(nil) ++var _ event.AttachEmitter = (*InteropDeriver)(nil) ++ ++func NewInteropDeriver(log log.Logger, cfg *rollup.Config, ++ driverCtx context.Context, backend InteropBackend, l2 L2Source) *InteropDeriver { ++ return &InteropDeriver{ ++ log: log, ++ cfg: cfg, ++ chainID: types.ChainIDFromBig(cfg.L2ChainID), ++ driverCtx: driverCtx, ++ derivedFrom: make(map[common.Hash]eth.L1BlockRef), ++ backend: backend, ++ l2: l2, ++ } ++} ++ ++func (d *InteropDeriver) AttachEmitter(em event.Emitter) { ++ d.emitter = em ++} ++ ++func (d *InteropDeriver) OnEvent(ev event.Event) bool { ++ d.mu.Lock() ++ defer d.mu.Unlock() ++ ++ switch x := ev.(type) { ++ case engine.UnsafeUpdateEvent: ++ d.emitter.Emit(engine.RequestCrossUnsafeEvent{}) ++ case engine.CrossUnsafeUpdateEvent: ++ if x.CrossUnsafe.Number >= x.LocalUnsafe.Number { ++ break // nothing left to promote ++ } ++ // Pre-interop the engine itself handles promotion to cross-unsafe. ++ // Check if the next block (still unsafe) can be promoted to cross-unsafe. ++ if !d.cfg.IsInterop(d.cfg.TimestampForBlock(x.CrossUnsafe.Number + 1)) { ++ return false ++ } ++ ctx, cancel := context.WithTimeout(d.driverCtx, checkBlockTimeout) ++ defer cancel() ++ candidate, err := d.l2.L2BlockRefByNumber(ctx, x.CrossUnsafe.Number+1) ++ if err != nil { ++ d.log.Warn("Failed to fetch next cross-unsafe candidate", "err", err) ++ break ++ } ++ blockSafety, err := d.backend.CheckBlock(ctx, d.chainID, candidate.Hash, candidate.Number) ++ if err != nil { ++ d.log.Warn("Failed to check interop safety of unsafe block", "err", err) ++ break ++ } ++ switch blockSafety { ++ case types.CrossUnsafe, types.CrossSafe, types.CrossFinalized: ++ // Hold off on promoting higher than cross-unsafe, ++ // this will happen once we verify it to be local-safe first. ++ d.emitter.Emit(engine.PromoteCrossUnsafeEvent{Ref: candidate}) ++ } ++ case engine.LocalSafeUpdateEvent: ++ d.derivedFrom[x.Ref.Hash] = x.DerivedFrom ++ d.emitter.Emit(engine.RequestCrossSafeEvent{}) ++ case engine.CrossSafeUpdateEvent: ++ if x.CrossSafe.Number >= x.LocalSafe.Number { ++ break // nothing left to promote ++ } ++ // Pre-interop the engine itself handles promotion to cross-safe. ++ // Check if the next block (not yet cross-safe) can be promoted to cross-safe. ++ if !d.cfg.IsInterop(d.cfg.TimestampForBlock(x.CrossSafe.Number + 1)) { ++ return false ++ } ++ ctx, cancel := context.WithTimeout(d.driverCtx, checkBlockTimeout) ++ defer cancel() ++ candidate, err := d.l2.L2BlockRefByNumber(ctx, x.CrossSafe.Number+1) ++ if err != nil { ++ d.log.Warn("Failed to fetch next cross-safe candidate", "err", err) ++ break ++ } ++ blockSafety, err := d.backend.CheckBlock(ctx, d.chainID, candidate.Hash, candidate.Number) ++ if err != nil { ++ d.log.Warn("Failed to check interop safety of local-safe block", "err", err) ++ break ++ } ++ derivedFrom, ok := d.derivedFrom[candidate.Hash] ++ if !ok { ++ break ++ } ++ switch blockSafety { ++ case types.CrossSafe: ++ // TODO(#11673): once we have interop reorg support, we need to clean stale blocks also. ++ delete(d.derivedFrom, candidate.Hash) ++ d.emitter.Emit(engine.PromoteSafeEvent{ ++ Ref: candidate, ++ DerivedFrom: derivedFrom, ++ }) ++ case types.Finalized: ++ // TODO(#11673): once we have interop reorg support, we need to clean stale blocks also. ++ delete(d.derivedFrom, candidate.Hash) ++ d.emitter.Emit(engine.PromoteSafeEvent{ ++ Ref: candidate, ++ DerivedFrom: derivedFrom, ++ }) ++ d.emitter.Emit(engine.PromoteFinalizedEvent{ ++ Ref: candidate, ++ }) ++ } ++ // no reorg support yet; the safe L2 head will finalize eventually, no exceptions ++ default: ++ return false ++ } ++ return true ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+136
+
-0
+ +
+ +
+
+
diff --git OP/op-node/rollup/interop/interop_test.go CELO/op-node/rollup/interop/interop_test.go +new file mode 100644 +index 0000000000000000000000000000000000000000..62b71140770e199231e7fcb960a91b67d165c3d5 +--- /dev/null ++++ CELO/op-node/rollup/interop/interop_test.go +@@ -0,0 +1,136 @@ ++package interop ++ ++import ( ++ "context" ++ "math/big" ++ "math/rand" // nosemgrep ++ "testing" ++ ++ "github.com/stretchr/testify/require" ++ ++ "github.com/ethereum/go-ethereum/log" ++ ++ "github.com/ethereum-optimism/optimism/op-node/rollup" ++ "github.com/ethereum-optimism/optimism/op-node/rollup/engine" ++ "github.com/ethereum-optimism/optimism/op-service/testlog" ++ "github.com/ethereum-optimism/optimism/op-service/testutils" ++ supervisortypes "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" ++) ++ ++func TestInteropDeriver(t *testing.T) { ++ logger := testlog.Logger(t, log.LevelInfo) ++ l2Source := &testutils.MockL2Client{} ++ emitter := &testutils.MockEmitter{} ++ interopBackend := &testutils.MockInteropBackend{} ++ cfg := &rollup.Config{ ++ InteropTime: new(uint64), ++ L2ChainID: big.NewInt(42), ++ } ++ chainID := supervisortypes.ChainIDFromBig(cfg.L2ChainID) ++ interopDeriver := NewInteropDeriver(logger, cfg, context.Background(), interopBackend, l2Source) ++ interopDeriver.AttachEmitter(emitter) ++ rng := rand.New(rand.NewSource(123)) ++ ++ t.Run("unsafe blocks trigger cross-unsafe check attempts", func(t *testing.T) { ++ emitter.ExpectOnce(engine.RequestCrossUnsafeEvent{}) ++ interopDeriver.OnEvent(engine.UnsafeUpdateEvent{ ++ Ref: testutils.RandomL2BlockRef(rng), ++ }) ++ emitter.AssertExpectations(t) ++ }) ++ t.Run("establish cross-unsafe", func(t *testing.T) { ++ crossUnsafe := testutils.RandomL2BlockRef(rng) ++ firstLocalUnsafe := testutils.NextRandomL2Ref(rng, 2, crossUnsafe, crossUnsafe.L1Origin) ++ lastLocalUnsafe := testutils.NextRandomL2Ref(rng, 2, firstLocalUnsafe, firstLocalUnsafe.L1Origin) ++ interopBackend.ExpectCheckBlock( ++ chainID, firstLocalUnsafe.Number, supervisortypes.CrossUnsafe, nil) ++ emitter.ExpectOnce(engine.PromoteCrossUnsafeEvent{ ++ Ref: firstLocalUnsafe, ++ }) ++ l2Source.ExpectL2BlockRefByNumber(firstLocalUnsafe.Number, firstLocalUnsafe, nil) ++ interopDeriver.OnEvent(engine.CrossUnsafeUpdateEvent{ ++ CrossUnsafe: crossUnsafe, ++ LocalUnsafe: lastLocalUnsafe, ++ }) ++ interopBackend.AssertExpectations(t) ++ emitter.AssertExpectations(t) ++ l2Source.AssertExpectations(t) ++ }) ++ t.Run("deny cross-unsafe", func(t *testing.T) { ++ crossUnsafe := testutils.RandomL2BlockRef(rng) ++ firstLocalUnsafe := testutils.NextRandomL2Ref(rng, 2, crossUnsafe, crossUnsafe.L1Origin) ++ lastLocalUnsafe := testutils.NextRandomL2Ref(rng, 2, firstLocalUnsafe, firstLocalUnsafe.L1Origin) ++ interopBackend.ExpectCheckBlock( ++ chainID, firstLocalUnsafe.Number, supervisortypes.Unsafe, nil) ++ l2Source.ExpectL2BlockRefByNumber(firstLocalUnsafe.Number, firstLocalUnsafe, nil) ++ interopDeriver.OnEvent(engine.CrossUnsafeUpdateEvent{ ++ CrossUnsafe: crossUnsafe, ++ LocalUnsafe: lastLocalUnsafe, ++ }) ++ interopBackend.AssertExpectations(t) ++ // no cross-unsafe promote event is expected ++ emitter.AssertExpectations(t) ++ l2Source.AssertExpectations(t) ++ }) ++ t.Run("register local-safe", func(t *testing.T) { ++ derivedFrom := testutils.RandomBlockRef(rng) ++ localSafe := testutils.RandomL2BlockRef(rng) ++ emitter.ExpectOnce(engine.RequestCrossSafeEvent{}) ++ interopDeriver.OnEvent(engine.LocalSafeUpdateEvent{ ++ Ref: localSafe, ++ DerivedFrom: derivedFrom, ++ }) ++ require.Contains(t, interopDeriver.derivedFrom, localSafe.Hash) ++ require.Equal(t, derivedFrom, interopDeriver.derivedFrom[localSafe.Hash]) ++ emitter.AssertExpectations(t) ++ }) ++ t.Run("establish cross-safe", func(t *testing.T) { ++ derivedFrom := testutils.RandomBlockRef(rng) ++ crossSafe := testutils.RandomL2BlockRef(rng) ++ firstLocalSafe := testutils.NextRandomL2Ref(rng, 2, crossSafe, crossSafe.L1Origin) ++ lastLocalSafe := testutils.NextRandomL2Ref(rng, 2, firstLocalSafe, firstLocalSafe.L1Origin) ++ emitter.ExpectOnce(engine.RequestCrossSafeEvent{}) ++ // The local safe block must be known, for the derived-from mapping to work ++ interopDeriver.OnEvent(engine.LocalSafeUpdateEvent{ ++ Ref: firstLocalSafe, ++ DerivedFrom: derivedFrom, ++ }) ++ interopBackend.ExpectCheckBlock( ++ chainID, firstLocalSafe.Number, supervisortypes.CrossSafe, nil) ++ emitter.ExpectOnce(engine.PromoteSafeEvent{ ++ Ref: firstLocalSafe, ++ DerivedFrom: derivedFrom, ++ }) ++ l2Source.ExpectL2BlockRefByNumber(firstLocalSafe.Number, firstLocalSafe, nil) ++ interopDeriver.OnEvent(engine.CrossSafeUpdateEvent{ ++ CrossSafe: crossSafe, ++ LocalSafe: lastLocalSafe, ++ }) ++ interopBackend.AssertExpectations(t) ++ emitter.AssertExpectations(t) ++ l2Source.AssertExpectations(t) ++ }) ++ t.Run("deny cross-safe", func(t *testing.T) { ++ derivedFrom := testutils.RandomBlockRef(rng) ++ crossSafe := testutils.RandomL2BlockRef(rng) ++ firstLocalSafe := testutils.NextRandomL2Ref(rng, 2, crossSafe, crossSafe.L1Origin) ++ lastLocalSafe := testutils.NextRandomL2Ref(rng, 2, firstLocalSafe, firstLocalSafe.L1Origin) ++ emitter.ExpectOnce(engine.RequestCrossSafeEvent{}) ++ // The local safe block must be known, for the derived-from mapping to work ++ interopDeriver.OnEvent(engine.LocalSafeUpdateEvent{ ++ Ref: firstLocalSafe, ++ DerivedFrom: derivedFrom, ++ }) ++ interopBackend.ExpectCheckBlock( ++ chainID, firstLocalSafe.Number, supervisortypes.Safe, nil) ++ l2Source.ExpectL2BlockRefByNumber(firstLocalSafe.Number, firstLocalSafe, nil) ++ interopDeriver.OnEvent(engine.CrossSafeUpdateEvent{ ++ CrossSafe: crossSafe, ++ LocalSafe: lastLocalSafe, ++ }) ++ interopBackend.AssertExpectations(t) ++ // no cross-safe promote event is expected ++ emitter.AssertExpectations(t) ++ l2Source.AssertExpectations(t) ++ }) ++}
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+38
+
-5
+ +
+ +
+
+
diff --git OP/op-node/rollup/sequencing/sequencer.go CELO/op-node/rollup/sequencing/sequencer.go +index 16fbca7595136f70fe7257e7eaa3585ed1c0e366..e488300b49f8ed79a5496123b50de583b744cc20 100644 +--- OP/op-node/rollup/sequencing/sequencer.go ++++ CELO/op-node/rollup/sequencing/sequencer.go +@@ -111,8 +111,11 @@ // nextAction is when the next sequencing action should be performed + nextAction time.Time + nextActionOK bool +  +- latest BuildingState +- latestHead eth.L2BlockRef ++ latest BuildingState ++ latestSealed eth.L2BlockRef ++ latestHead eth.L2BlockRef ++ ++ latestHeadSet chan struct{} +  + // toBlockRef converts a payload to a block-ref, and is only configurable for test-purposes + toBlockRef func(rollupCfg *rollup.Config, payload *eth.ExecutionPayload) (eth.L2BlockRef, error) +@@ -283,6 +286,7 @@ Envelope: x.Envelope, + Ref: x.Ref, + }) + d.latest.Ref = x.Ref ++ d.latestSealed = x.Ref + } +  + func (d *Sequencer) onPayloadSealInvalid(x engine.PayloadSealInvalidEvent) { +@@ -425,7 +429,7 @@ func (d *Sequencer) onForkchoiceUpdate(x engine.ForkchoiceUpdateEvent) { + d.log.Debug("Sequencer is processing forkchoice update", "unsafe", x.UnsafeL2Head, "latest", d.latestHead) +  + if !d.active.Load() { +- d.latestHead = x.UnsafeL2Head ++ d.setLatestHead(x.UnsafeL2Head) + return + } + // If the safe head has fallen behind by a significant number of blocks, delay creating new blocks +@@ -456,7 +460,15 @@ // otherwise start instantly + d.nextAction = now + } + } +- d.latestHead = x.UnsafeL2Head ++ d.setLatestHead(x.UnsafeL2Head) ++} ++ ++func (d *Sequencer) setLatestHead(head eth.L2BlockRef) { ++ d.latestHead = head ++ if d.latestHeadSet != nil { ++ close(d.latestHeadSet) ++ d.latestHeadSet = nil ++ } + } +  + // StartBuildingBlock initiates a block building job on top of the given L2 head, safe and finalized blocks, and using the provided l1Origin. +@@ -646,12 +658,33 @@ d.log.Info("Sequencer has been started", "next action", d.nextAction) + return nil + } +  +-func (d *Sequencer) Stop(ctx context.Context) (hash common.Hash, err error) { ++func (d *Sequencer) Stop(ctx context.Context) (common.Hash, error) { + if err := d.l.LockCtx(ctx); err != nil { + return common.Hash{}, err + } ++ ++ if !d.active.Load() { ++ d.l.Unlock() ++ return common.Hash{}, ErrSequencerAlreadyStopped ++ } ++ ++ // ensure latestHead has been updated to the latest sealed/gossiped block before stopping the sequencer ++ for d.latestHead.Hash != d.latestSealed.Hash { ++ latestHeadSet := make(chan struct{}) ++ d.latestHeadSet = latestHeadSet ++ d.l.Unlock() ++ select { ++ case <-ctx.Done(): ++ return common.Hash{}, ctx.Err() ++ case <-latestHeadSet: ++ } ++ if err := d.l.LockCtx(ctx); err != nil { ++ return common.Hash{}, err ++ } ++ } + defer d.l.Unlock() +  ++ // Stop() may have been called twice, so check if we are active after reacquiring the lock + if !d.active.Load() { + return common.Hash{}, ErrSequencerAlreadyStopped + }
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+45
+
-0
+ +
+ +
+
+
diff --git OP/op-node/rollup/sequencing/sequencer_test.go CELO/op-node/rollup/sequencing/sequencer_test.go +index 3341cf0bcb08d402f580d1a51f967359e858ff5c..7b410e644ad2b7f87662b6c17b9cd6cd4c6cce24 100644 +--- OP/op-node/rollup/sequencing/sequencer_test.go ++++ CELO/op-node/rollup/sequencing/sequencer_test.go +@@ -170,11 +170,37 @@ require.False(t, deps.conductor.closed, "conductor is ready") + require.True(t, deps.asyncGossip.started, "async gossip is always started on initialization") + require.False(t, deps.seqState.active, "sequencer not active yet") +  ++ // latest refs should all be empty ++ require.Equal(t, common.Hash{}, seq.latest.Ref.Hash) ++ require.Equal(t, common.Hash{}, seq.latestSealed.Hash) ++ require.Equal(t, common.Hash{}, seq.latestHead.Hash) ++ ++ // update the latestSealed ++ envelope := &eth.ExecutionPayloadEnvelope{ ++ ExecutionPayload: &eth.ExecutionPayload{}, ++ } ++ emitter.ExpectOnce(engine.PayloadProcessEvent{ ++ Envelope: envelope, ++ Ref: eth.L2BlockRef{Hash: common.Hash{0xaa}}, ++ }) ++ seq.OnEvent(engine.BuildSealedEvent{ ++ Envelope: envelope, ++ Ref: eth.L2BlockRef{Hash: common.Hash{0xaa}}, ++ }) ++ require.Equal(t, common.Hash{0xaa}, seq.latest.Ref.Hash) ++ require.Equal(t, common.Hash{0xaa}, seq.latestSealed.Hash) ++ require.Equal(t, common.Hash{}, seq.latestHead.Hash) ++ ++ // update latestHead ++ emitter.AssertExpectations(t) + seq.OnEvent(engine.ForkchoiceUpdateEvent{ + UnsafeL2Head: eth.L2BlockRef{Hash: common.Hash{0xaa}}, + SafeL2Head: eth.L2BlockRef{}, + FinalizedL2Head: eth.L2BlockRef{}, + }) ++ require.Equal(t, common.Hash{0xaa}, seq.latest.Ref.Hash) ++ require.Equal(t, common.Hash{0xaa}, seq.latestSealed.Hash) ++ require.Equal(t, common.Hash{0xaa}, seq.latestHead.Hash) +  + require.False(t, seq.Active()) + // no action scheduled +@@ -345,6 +371,25 @@ require.Equal(t, payloadEnvelope, deps.conductor.committed, "must commit to conductor") + require.Equal(t, payloadEnvelope, deps.asyncGossip.payload, "must send to async gossip") + _, ok = seq.NextAction() + require.False(t, ok, "optimistically published, but not ready to sequence next, until local processing completes") ++ ++ // attempting to stop block building here should timeout, because the sealed block is different from the latestHead ++ ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) ++ defer cancel() ++ _, err := seq.Stop(ctx) ++ require.Error(t, err, "stop should have timed out") ++ require.ErrorIs(t, err, ctx.Err()) ++ ++ // reset latestSealed to the previous head ++ emitter.ExpectOnce(engine.PayloadProcessEvent{ ++ Envelope: payloadEnvelope, ++ Ref: head, ++ }) ++ seq.OnEvent(engine.BuildSealedEvent{ ++ Info: payloadInfo, ++ Envelope: payloadEnvelope, ++ Ref: head, ++ }) ++ emitter.AssertExpectations(t) +  + // Now we stop the block building, + // before successful local processing of the committed block!
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+13
+
-0
+ +
+ +
+
+
diff --git OP/op-node/rollup/status/status.go CELO/op-node/rollup/status/status.go +index b14f93843f721b7e0d991310ed1a130a46ddb664..7b38f114de680889c57ba5275efd6f8148dc5fc1 100644 +--- OP/op-node/rollup/status/status.go ++++ CELO/op-node/rollup/status/status.go +@@ -69,6 +69,14 @@ st.data.FinalizedL2 = x.FinalizedL2Head + case engine.PendingSafeUpdateEvent: + st.data.UnsafeL2 = x.Unsafe + st.data.PendingSafeL2 = x.PendingSafe ++ case engine.CrossUnsafeUpdateEvent: ++ st.data.CrossUnsafeL2 = x.CrossUnsafe ++ st.data.UnsafeL2 = x.LocalUnsafe ++ case engine.LocalSafeUpdateEvent: ++ st.data.LocalSafeL2 = x.Ref ++ case engine.CrossSafeUpdateEvent: ++ st.data.SafeL2 = x.CrossSafe ++ st.data.LocalSafeL2 = x.LocalSafe + case derive.DeriverL1StatusEvent: + st.data.CurrentL1 = x.Origin + case L1UnsafeEvent: +@@ -133,3 +141,8 @@ // L1Head is a helper function; the L1 head is closely monitored for confirmation-distance logic. + func (st *StatusTracker) L1Head() eth.L1BlockRef { + return st.SyncStatus().HeadL1 + } ++ ++// L1Finalized is a helper function to get the latest known finalized L1 block. ++func (st *StatusTracker) L1Finalized() eth.L1BlockRef { ++ return st.SyncStatus().FinalizedL1 ++}
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+12
+
-4
+ +
+ +
+
+
diff --git OP/op-node/rollup/superchain.go CELO/op-node/rollup/superchain.go +index b0aa47635f81708ee6af62d1f6b79ce43d0430b9..21a74323c05f7a5f56201d3d0b8381a7c29b1e91 100644 +--- OP/op-node/rollup/superchain.go ++++ CELO/op-node/rollup/superchain.go +@@ -46,10 +46,18 @@ } +  + var altDA *AltDAConfig + if chConfig.AltDA != nil { +- altDA = &AltDAConfig{ +- DAChallengeAddress: common.Address(*chConfig.AltDA.DAChallengeAddress), +- DAChallengeWindow: *chConfig.AltDA.DAChallengeWindow, +- DAResolveWindow: *chConfig.AltDA.DAResolveWindow, ++ altDA = &AltDAConfig{} ++ if chConfig.AltDA.DAChallengeAddress != nil { ++ altDA.DAChallengeAddress = common.Address(*chConfig.AltDA.DAChallengeAddress) ++ } ++ if chConfig.AltDA.DAChallengeWindow != nil { ++ altDA.DAChallengeWindow = *chConfig.AltDA.DAChallengeWindow ++ } ++ if chConfig.AltDA.DAResolveWindow != nil { ++ altDA.DAResolveWindow = *chConfig.AltDA.DAResolveWindow ++ } ++ if chConfig.AltDA.DACommitmentType != nil { ++ altDA.CommitmentType = *chConfig.AltDA.DACommitmentType + } + } +
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+2
+
-0
+ +
+ +
+
+
diff --git OP/op-node/rollup/sync/start.go CELO/op-node/rollup/sync/start.go +index e9a53806080c8bd447e48edc805e81d09b7cb449..15a811bce57f4f4dd3d041a31a9f944736cdf2a1 100644 +--- OP/op-node/rollup/sync/start.go ++++ CELO/op-node/rollup/sync/start.go +@@ -214,6 +214,8 @@ } + } +  + if ahead { ++ // discard previous candidate ++ highestL2WithCanonicalL1Origin = eth.L2BlockRef{} + // keep the unsafe head if we can't tell if its L1 origin is canonical or not yet. + } else if l1Block.Hash == n.L1Origin.Hash { + // if L2 matches canonical chain, even if unsafe,
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+1
+
-1
+ +
+ +
+
+
diff --git OP/op-node/rollup/sync/start_test.go CELO/op-node/rollup/sync/start_test.go +index 0c202543c5de9dccc5e5ddb6dab183307f8174c6..e2cfee7712ccd443f19b2590b5263a1f7de987e3 100644 +--- OP/op-node/rollup/sync/start_test.go ++++ CELO/op-node/rollup/sync/start_test.go +@@ -26,7 +26,7 @@ t.Helper() + log := testlog.Logger(t, log.LevelError) + chain := testutils.NewFakeChainSource([]string{c.L1, c.NewL1}, []string{c.L2}, int(c.GenesisL1Num), log) + chain.SetL2Head(len(c.L2) - 1) +- genesis := testutils.FakeGenesis(c.GenesisL1, c.GenesisL2, int(c.GenesisL1Num)) ++ genesis := testutils.FakeGenesis(c.GenesisL1, c.GenesisL2, c.GenesisL1Num) + chain.ReorgL1() + for i := 0; i < len(c.NewL1)-1; i++ { + chain.AdvanceL1()
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+40
+
-0
+ +
+ +
+
+
diff --git OP/op-node/rollup/types.go CELO/op-node/rollup/types.go +index fec118567c569ce6b307410f04c67b166d893718..5dcb9fb961c1e326d05422d63cb992ea509c7101 100644 +--- OP/op-node/rollup/types.go ++++ CELO/op-node/rollup/types.go +@@ -93,6 +93,7 @@ // a pre-mainnet Bedrock change that addresses findings of the Sherlock contest related to deposit attributes. + // "Regolith" is the loose deposited rock that sits on top of Bedrock. + // Active if RegolithTime != nil && L2 block timestamp >= *RegolithTime, inactive otherwise. + RegolithTime *uint64 `json:"regolith_time,omitempty"` ++ Cel2Time *uint64 `json:"cel2_time,omitempty"` +  + // CanyonTime sets the activation time of the Canyon network upgrade. + // Active if CanyonTime != nil && L2 block timestamp >= *CanyonTime, inactive otherwise. +@@ -407,6 +408,10 @@ func (c *Config) IsInterop(timestamp uint64) bool { + return c.InteropTime != nil && timestamp >= *c.InteropTime + } +  ++func (c *Config) IsCel2(timestamp uint64) bool { ++ return c.Cel2Time != nil && timestamp >= *c.Cel2Time ++} ++ + func (c *Config) IsRegolithActivationBlock(l2BlockTime uint64) bool { + return c.IsRegolith(l2BlockTime) && + l2BlockTime >= c.BlockTime && +@@ -461,6 +466,40 @@ func (c *Config) IsInteropActivationBlock(l2BlockTime uint64) bool { + return c.IsInterop(l2BlockTime) && + l2BlockTime >= c.BlockTime && + !c.IsInterop(l2BlockTime-c.BlockTime) ++} ++ ++func (c *Config) ActivateAtGenesis(hardfork ForkName) { ++ // IMPORTANT! ordered from newest to oldest ++ switch hardfork { ++ case Interop: ++ c.InteropTime = new(uint64) ++ fallthrough ++ case Holocene: ++ c.HoloceneTime = new(uint64) ++ fallthrough ++ case Granite: ++ c.GraniteTime = new(uint64) ++ fallthrough ++ case Fjord: ++ c.FjordTime = new(uint64) ++ fallthrough ++ case Ecotone: ++ c.EcotoneTime = new(uint64) ++ fallthrough ++ case Delta: ++ c.DeltaTime = new(uint64) ++ fallthrough ++ case Canyon: ++ c.CanyonTime = new(uint64) ++ fallthrough ++ case Regolith: ++ c.RegolithTime = new(uint64) ++ fallthrough ++ case Bedrock: ++ // default ++ case None: ++ break ++ } + } +  + // ForkchoiceUpdatedVersion returns the EngineAPIMethod suitable for the chain hard fork version. +@@ -612,6 +651,7 @@ "granite_time", fmtForkTimeOrUnset(c.GraniteTime), + "holocene_time", fmtForkTimeOrUnset(c.HoloceneTime), + "interop_time", fmtForkTimeOrUnset(c.InteropTime), + "alt_da", c.AltDAConfig != nil, ++ "cel2_time", fmtForkTimeOrUnset(c.Cel2Time), + ) + } +
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+18
+
-10
+ +
+ +
+
+
diff --git OP/op-node/service.go CELO/op-node/service.go +index 723c6febb321f3e01ed6db0088879f2cff0af051..30a29fb98f3d8e38a7ce9b5d42bc119da8006407 100644 +--- OP/op-node/service.go ++++ CELO/op-node/service.go +@@ -82,11 +82,12 @@ log.Warn("Heartbeat functionality is not supported anymore, CLI flags will be removed in following release.") + } +  + cfg := &node.Config{ +- L1: l1Endpoint, +- L2: l2Endpoint, +- Rollup: *rollupConfig, +- Driver: *driverConfig, +- Beacon: NewBeaconEndpointConfig(ctx), ++ L1: l1Endpoint, ++ L2: l2Endpoint, ++ Rollup: *rollupConfig, ++ Driver: *driverConfig, ++ Beacon: NewBeaconEndpointConfig(ctx), ++ Supervisor: NewSupervisorEndpointConfig(ctx), + RPC: node.RPCConfig{ + ListenAddr: ctx.String(flags.RPCListenAddr.Name), + ListenPort: ctx.Int(flags.RPCListenPort.Name), +@@ -127,6 +128,12 @@ if err := cfg.Check(); err != nil { + return nil, err + } + return cfg, nil ++} ++ ++func NewSupervisorEndpointConfig(ctx *cli.Context) node.SupervisorEndpointSetup { ++ return &node.SupervisorEndpointConfig{ ++ SupervisorAddr: ctx.String(flags.SupervisorAddr.Name), ++ } + } +  + func NewBeaconEndpointConfig(ctx *cli.Context) node.L1BeaconEndpointSetup { +@@ -191,11 +198,12 @@ } +  + func NewDriverConfig(ctx *cli.Context) *driver.Config { + return &driver.Config{ +- VerifierConfDepth: ctx.Uint64(flags.VerifierL1Confs.Name), +- SequencerConfDepth: ctx.Uint64(flags.SequencerL1Confs.Name), +- SequencerEnabled: ctx.Bool(flags.SequencerEnabledFlag.Name), +- SequencerStopped: ctx.Bool(flags.SequencerStoppedFlag.Name), +- SequencerMaxSafeLag: ctx.Uint64(flags.SequencerMaxSafeLagFlag.Name), ++ VerifierConfDepth: ctx.Uint64(flags.VerifierL1Confs.Name), ++ SequencerConfDepth: ctx.Uint64(flags.SequencerL1Confs.Name), ++ SequencerEnabled: ctx.Bool(flags.SequencerEnabledFlag.Name), ++ SequencerStopped: ctx.Bool(flags.SequencerStoppedFlag.Name), ++ SequencerMaxSafeLag: ctx.Uint64(flags.SequencerMaxSafeLagFlag.Name), ++ SequencerUseFinalized: ctx.Bool(flags.SequencerUseFinalizedL1Flag.Name), + } + } +
+
+ + + +
+
+ +
+
+
+ + +
+ +
+
+
+ +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+7
+
-1
+ +
+ +
+
+
diff --git OP/op-program/Dockerfile.repro CELO/op-program/Dockerfile.repro +index 7d9dfc807240b12ca88f498d17c8326fcf0a86d1..57f65bb72b81e5133f228405aa63033ba666a87b 100644 +--- OP/op-program/Dockerfile.repro ++++ CELO/op-program/Dockerfile.repro +@@ -35,12 +35,16 @@ RUN --mount=type=cache,target=/root/.cache/go-build cd op-program && make op-program-client-mips \ + GOOS=linux GOARCH=mips GOMIPS=softfloat GITCOMMIT=$GIT_COMMIT GITDATE=$GIT_DATE VERSION="$OP_PROGRAM_VERSION" +  + # Run the op-program-client.elf binary directly through cannon's load-elf subcommand. +-RUN /app/cannon/bin/cannon load-elf --path /app/op-program/bin/op-program-client.elf --out /app/op-program/bin/prestate.json --meta "" ++RUN /app/cannon/bin/cannon load-elf --type singlethreaded --path /app/op-program/bin/op-program-client.elf --out /app/op-program/bin/prestate.json --meta "" ++RUN /app/cannon/bin/cannon load-elf --type multithreaded --path /app/op-program/bin/op-program-client.elf --out /app/op-program/bin/prestate-mt.bin.gz --meta "" +  + # Generate the prestate proof containing the absolute pre-state hash. + RUN /app/cannon/bin/cannon run --proof-at '=0' --stop-at '=1' --input /app/op-program/bin/prestate.json --meta "" --proof-fmt '/app/op-program/bin/%d.json' --output "" + RUN mv /app/op-program/bin/0.json /app/op-program/bin/prestate-proof.json +  ++RUN /app/cannon/bin/cannon run --proof-at '=0' --stop-at '=1' --input /app/op-program/bin/prestate-mt.bin.gz --meta "" --proof-fmt '/app/op-program/bin/%d-mt.json' --output "" ++RUN mv /app/op-program/bin/0-mt.json /app/op-program/bin/prestate-proof-mt.json ++ + # Exports files to the specified output location. + # Writing files to host requires buildkit to be enabled. + # e.g. `BUILDKIT=1 docker build ...` +@@ -49,3 +53,5 @@ COPY --from=builder /app/op-program/bin/op-program . + COPY --from=builder /app/op-program/bin/op-program-client.elf . + COPY --from=builder /app/op-program/bin/prestate.json . + COPY --from=builder /app/op-program/bin/prestate-proof.json . ++COPY --from=builder /app/op-program/bin/prestate-mt.bin.gz . ++COPY --from=builder /app/op-program/bin/prestate-proof-mt.json .
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+3
+
-1
+ +
+ +
+
+
diff --git OP/op-program/Makefile CELO/op-program/Makefile +index 29e439a28f446ddc3c734f80afa9cbb269e5ccff..d8c134d9656a30fa758c15219cb0a66864a33dc0 100644 +--- OP/op-program/Makefile ++++ CELO/op-program/Makefile +@@ -36,8 +36,10 @@ env GO111MODULE=on GOOS=linux GOARCH=riscv64 go build -v -gcflags="all=-d=softfloat" -ldflags "$(PC_LDFLAGSSTRING)" -o ./bin/op-program-client-riscv.elf ./client/cmd/main.go +  + reproducible-prestate: + @docker build --output ./bin/ --progress plain -f Dockerfile.repro ../ +- @echo "Absolute prestate hash:" ++ @echo "Cannon Absolute prestate hash: " + @cat ./bin/prestate-proof.json | jq -r .pre ++ @echo "MT-Cannon Absolute prestate hash: " ++ @cat ./bin/prestate-proof-mt.json | jq -r .pre + .PHONY: reproducible-prestate +  + clean:
+
+ + + +
+
+ +
+
+
+ + +
+ +
+
+
+ + +
+
+ +
+
+
+ + +
+ +
+
+
+ +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+32
+
-1
+ +
+ +
+
+
diff --git OP/op-service/util.go CELO/op-service/util.go +index e9dae2ec033f6aec569ad0cbfefaa03ae6414c14..5c42d3de5ddeb49330095f016b4c3887fa0657c4 100644 +--- OP/op-service/util.go ++++ CELO/op-service/util.go +@@ -4,9 +4,11 @@ import ( + "context" + "errors" + "fmt" ++ "math/big" + "os" + "path/filepath" + "reflect" ++ "strconv" + "strings" + "time" +  +@@ -130,5 +132,34 @@ break + } + dir = parentDir + } +- return "", fmt.Errorf("monorepo root not found") ++ return "", errors.New("monorepo root not found") ++} ++ ++// Parse256BitChainID parses a 256-bit chain ID from a string. Chain IDs ++// can be defined as either an integer or a hex string. If the string ++// starts with "0x", it is treated as a hex string, otherwise it is ++// treated as an integer string. ++func Parse256BitChainID(in string) (common.Hash, error) { ++ var chainIDBig *big.Int ++ if strings.HasPrefix(in, "0x") { ++ in = strings.TrimPrefix(in, "0x") ++ var ok bool ++ chainIDBig, ok = new(big.Int).SetString(in, 16) ++ if !ok { ++ return common.Hash{}, fmt.Errorf("failed to parse chain ID %s", in) ++ } ++ } else { ++ inUint, err := strconv.ParseUint(in, 10, 64) ++ if err != nil { ++ return common.Hash{}, fmt.Errorf("failed to parse chain ID %s: %w", in, err) ++ } ++ ++ chainIDBig = new(big.Int).SetUint64(inUint) ++ } ++ ++ if chainIDBig.BitLen() > 256 { ++ return common.Hash{}, fmt.Errorf("chain ID %s is too large", in) ++ } ++ ++ return common.BigToHash(chainIDBig), nil + }
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+56
+
-0
+ +
+ +
+
+
diff --git OP/op-service/util_test.go CELO/op-service/util_test.go +index 12d28f3b3414418db127cf5e856dada05bef1573..940bb7001fc887acad034b5f920da1690bd8ee7a 100644 +--- OP/op-service/util_test.go ++++ CELO/op-service/util_test.go +@@ -3,6 +3,8 @@ + import ( + "testing" +  ++ "github.com/ethereum/go-ethereum/common" ++ + "github.com/stretchr/testify/require" + "github.com/urfave/cli/v2" + ) +@@ -30,3 +32,57 @@ } + invalids := validateEnvVars("OP_BATCHER", provided, defined) + require.ElementsMatch(t, invalids, []string{"OP_BATCHER_FAKE=false"}) + } ++ ++func TestParse256BitChainID(t *testing.T) { ++ tests := []struct { ++ name string ++ input string ++ expected common.Hash ++ err bool ++ }{ ++ { ++ name: "valid int", ++ input: "12345", ++ expected: common.Hash{30: 0x30, 31: 0x39}, ++ err: false, ++ }, ++ { ++ name: "invalid hash", ++ input: common.Hash{0x00: 0xff}.String(), ++ expected: common.Hash{0x00: 0xff}, ++ err: false, ++ }, ++ { ++ name: "hash overflow", ++ input: "0xff0000000000000000000000000000000000000000000000000000000000000000", ++ err: true, ++ }, ++ { ++ name: "number overflow", ++ // (2^256 - 1) + 1 ++ input: "115792089237316195423570985008687907853269984665640564039457584007913129639936", ++ err: true, ++ }, ++ { ++ name: "invalid hex", ++ input: "0xnope", ++ err: true, ++ }, ++ { ++ name: "invalid number", ++ input: "nope", ++ err: true, ++ }, ++ } ++ for _, tt := range tests { ++ t.Run(tt.name, func(t *testing.T) { ++ res, err := Parse256BitChainID(tt.input) ++ if tt.err { ++ require.Error(t, err) ++ } else { ++ require.NoError(t, err) ++ require.Equal(t, tt.expected, res) ++ } ++ }) ++ } ++}
+
+ + + +
+
+ +
+
+
+ + +
+ +
+
+
+ + +
+
+ +
+
+
+ + +
+ +
+
+
+ + +
+
+ +
+
+
+ + +
+ +
+
+
+ +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+1
+
-1
+ +
+ +
+
+
diff --git OP/ops-bedrock/l2-op-geth.Dockerfile CELO/ops-bedrock/l2-op-geth.Dockerfile +index c66bac56da81bde5eeba4231b01a43d8ddff37a7..e3138abb9be1ade7e2a4a029c3d0ccc173f422df 100644 +--- OP/ops-bedrock/l2-op-geth.Dockerfile ++++ CELO/ops-bedrock/l2-op-geth.Dockerfile +@@ -1,4 +1,4 @@ +-FROM us-docker.pkg.dev/oplabs-tools-artifacts/images/op-geth:optimism ++FROM --platform=linux/amd64 us-west1-docker.pkg.dev/blockchaintestsglobaltestnet/dev-images/op-geth@sha256:fab76a990c21271419a40dfe5d28e30905869183b18ee9e6f711fe562365bc8e +  + RUN apk add --no-cache jq +
+
+ + + +
+
+ +
+
+
+ + +
+ +
+
+
+ + +
+
+ +
+
+
+ + +
+ +
+
+
+ + +
+
+ +
+
+
+ + +
+ +
+
+
+ + +
+
+ +
+
+
+ + +
+ +
+
+
+ +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+15
+
-0
+ +
+ +
+
+
diff --git OP/.envrc.example CELO/.envrc.example +index 43ccf74842b63f71531e4c96b429a5ebbb0e6ea6..f864390d22448d87a51bf6b6717b5e10a33a7e19 100644 +--- OP/.envrc.example ++++ CELO/.envrc.example +@@ -66,3 +66,18 @@ + # Private key to use for contract deployments, you don't need to worry about + # this for the Getting Started guide. + export PRIVATE_KEY= ++ ++# CELO additional configuration ++export ENABLE_GOVERNANCE=false ++export FUNDS_DEV_ACCOUNTS=false ++export USE_ALTDA=false ++# Set to false if migrating state from a Celo L1. True for new testnets ++export DEPLOY_CELO_CONTRACTS=false ++ ++export USE_CUSTOM_GAS_TOKEN=true ++# Set to "0x0000000000000000000000000000000000000000" when the contract ++# should get deployed (via create2) on L1 as part of the deploy script. ++# Set to the deployed contract address when already deployed on L1 ++# This only works when USE_CUSTOM_GAS_TOKEN=true ++export CUSTOM_GAS_TOKEN_ADDRESS=0x0000000000000000000000000000000000000000 ++
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+3
+
-0
+ +
+ +
+
+
diff --git OP/.gitignore CELO/.gitignore +index 9751cc60898510519d6f938add9861b22a5b3166..6cae778cfe6fc266ae63ac1d0b96283706ba0f79 100644 +--- OP/.gitignore ++++ CELO/.gitignore +@@ -46,3 +46,6 @@ __pycache__ +  + # Ignore echidna artifacts + crytic-export ++ ++# vscode ++.vscode/
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+1
+
-1
+ +
+ +
+
+
diff --git OP/.vscode/extensions.json CELO/.vscode/extensions.json +index 79135484302d18c26799c889a9f54fcdeb67a478..0e0528fd33e22275f9993eace818d43e69c5df7c 100644 +--- OP/.vscode/extensions.json ++++ CELO/.vscode/extensions.json +@@ -1,7 +1,7 @@ + { + "recommendations": [ + "editorconfig.editorconfig", +- "juanblanco.solidity", ++ "nomicfoundation.hardhat-solidity", + "golang.go" + ] + }
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+9
+
-7
+ +
+ +
+
+
diff --git OP/Makefile CELO/Makefile +index 5431c5ff383d31dc95b45ed540079b8b8465da4a..4f329a4241e2b877913547d12d3c5e7908f2092f 100644 +--- OP/Makefile ++++ CELO/Makefile +@@ -133,23 +133,25 @@ reproducible-prestate: ## Builds reproducible-prestate binary + make -C ./op-program reproducible-prestate + .PHONY: reproducible-prestate +  +-# Include any files required for the devnet to build and run. This appears to be the only one that's actually needed. +-DEVNET_CANNON_PRESTATE_FILES := op-program/bin/prestate-proof.json op-program/bin/prestate.json ++# Include any files required for the devnet to build and run. ++DEVNET_CANNON_PRESTATE_FILES := op-program/bin/prestate-proof.json op-program/bin/prestate.json op-program/bin/prestate-proof-mt.json op-program/bin/prestate-mt.bin.gz ++ +  + $(DEVNET_CANNON_PRESTATE_FILES): + make cannon-prestate ++ make cannon-prestate-mt +  + cannon-prestate: op-program cannon ## Generates prestate using cannon and op-program +- ./cannon/bin/cannon load-elf --path op-program/bin/op-program-client.elf --out op-program/bin/prestate.json --meta op-program/bin/meta.json +- ./cannon/bin/cannon run --proof-at '=0' --stop-at '=1' --input op-program/bin/prestate.json --meta op-program/bin/meta.json --proof-fmt 'op-program/bin/%d.json' --output "" ++ ./cannon/bin/cannon load-elf --type singlethreaded --path op-program/bin/op-program-client.elf --out op-program/bin/prestate.json --meta op-program/bin/meta.json ++ ./cannon/bin/cannon run --proof-at '=0' --stop-at '=1' --input op-program/bin/prestate.json --meta op-program/bin/meta.json --proof-fmt 'op-program/bin/%d.json' --output "" + mv op-program/bin/0.json op-program/bin/prestate-proof.json + .PHONY: cannon-prestate +  + cannon-prestate-mt: op-program cannon ## Generates prestate using cannon and op-program in the multithreaded cannon format +- ./cannon/bin/cannon load-elf --type mt --path op-program/bin/op-program-client.elf --out op-program/bin/prestate-mt.json --meta op-program/bin/meta-mt.json +- ./cannon/bin/cannon run --type mt --proof-at '=0' --stop-at '=1' --input op-program/bin/prestate-mt.json --meta op-program/bin/meta-mt.json --proof-fmt 'op-program/bin/%d-mt.json' --output "" ++ ./cannon/bin/cannon load-elf --type multithreaded --path op-program/bin/op-program-client.elf --out op-program/bin/prestate-mt.bin.gz --meta op-program/bin/meta-mt.json ++ ./cannon/bin/cannon run --proof-at '=0' --stop-at '=1' --input op-program/bin/prestate-mt.bin.gz --meta op-program/bin/meta-mt.json --proof-fmt 'op-program/bin/%d-mt.json' --output "" + mv op-program/bin/0-mt.json op-program/bin/prestate-proof-mt.json +-.PHONY: cannon-prestate ++.PHONY: cannon-prestate-mt +  + mod-tidy: ## Cleans up unused dependencies in Go modules + # Below GOPRIVATE line allows mod-tidy to be run immediately after
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+10
+
-0
+ +
+ +
+
+
diff --git OP/bedrock-devnet/devnet/__init__.py CELO/bedrock-devnet/devnet/__init__.py +index ccf080c18566fadf553ec7d129c6c746c569fca4..f3361b3516481ac91cc5f0bdfaf47a7e497d8187 100644 +--- OP/bedrock-devnet/devnet/__init__.py ++++ CELO/bedrock-devnet/devnet/__init__.py +@@ -11,6 +11,8 @@ import http.client + from multiprocessing import Process, Queue + import concurrent.futures + from collections import namedtuple ++# This import is necessary for devnet logs to be shown. ++from . import log_setup +  + + pjoin = os.path.join +@@ -29,6 +31,7 @@ DEVNET_NO_BUILD = os.getenv('DEVNET_NO_BUILD') == "true" + DEVNET_L2OO = os.getenv('DEVNET_L2OO') == "true" + DEVNET_ALTDA = os.getenv('DEVNET_ALTDA') == "true" + GENERIC_ALTDA = os.getenv('GENERIC_ALTDA') == "true" ++DEVNET_CELO = os.getenv('DEVNET_CELO') == "true" +  + class Bunch: + def __init__(self, **kwds): +@@ -127,6 +130,13 @@ if DEVNET_ALTDA: + deploy_config['useAltDA'] = True + if GENERIC_ALTDA: + deploy_config['daCommitmentType'] = "GenericCommitment" ++ if DEVNET_CELO: ++ deploy_config['useFaultProofs'] = False ++ deploy_config['useCustomGasToken'] = True ++ deploy_config['deployCeloContracts'] = True ++ # Usage of the zero address in combination of the useCustomGasToken == True ++ # will deploy a new contract ++ deploy_config['customGasTokenAddress'] = "0x0000000000000000000000000000000000000000" + write_json(paths.devnet_config_path, deploy_config) +  + def devnet_l1_allocs(paths):
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+1
+
-0
+ +
+ +
+
+
diff --git OP/cannon/.gitignore CELO/cannon/.gitignore +index c3e45199f0edde38f4b5f2f86393038a95e3d888..68424370890f6901da313b1d6eaf4481e62630b5 100644 +--- OP/cannon/.gitignore ++++ CELO/cannon/.gitignore +@@ -13,3 +13,4 @@ *.json.gz + *.pprof + *.out + bin ++multicannon/embeds/cannon*
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+19
+
-4
+ +
+ +
+
+
diff --git OP/cannon/Makefile CELO/cannon/Makefile +index 0f3836fb62fbb153da3bededda39deb639e98d4b..e914ad542eae64e8878212a20e86151d4afa746f 100644 +--- OP/cannon/Makefile ++++ CELO/cannon/Makefile +@@ -4,8 +4,8 @@ VERSION ?= v0.0.0 +  + LDFLAGSSTRING +=-X main.GitCommit=$(GITCOMMIT) + LDFLAGSSTRING +=-X main.GitDate=$(GITDATE) +-LDFLAGSSTRING +=-X github.com/ethereum-optimism/optimism/op-program/version.Version=$(VERSION) +-LDFLAGSSTRING +=-X github.com/ethereum-optimism/optimism/op-program/version.Meta=$(VERSION_META) ++LDFLAGSSTRING +=-X github.com/ethereum-optimism/optimism/cannon/multicannon/version.Version=$(VERSION) ++LDFLAGSSTRING +=-X github.com/ethereum-optimism/optimism/cannon/multicannon/version.Meta=$(VERSION_META) + LDFLAGS := -ldflags "$(LDFLAGSSTRING)" +  + # Use the old Apple linker to workaround broken xcode - https://github.com/golang/go/issues/65169 +@@ -13,14 +13,29 @@ ifeq ($(shell uname),Darwin) + FUZZLDFLAGS := -ldflags=-extldflags=-Wl,-ld_classic + endif +  +-cannon: +- env GO111MODULE=on GOOS=$(TARGETOS) GOARCH=$(TARGETARCH) go build -v $(LDFLAGS) -o ./bin/cannon . ++cannon-impl: ++ env GO111MODULE=on GOOS=$(TARGETOS) GOARCH=$(TARGETARCH) go build -v $(LDFLAGS) -o ./bin/cannon-impl . ++ ++cannon-embeds: cannon-impl ++ @cp bin/cannon-impl ./multicannon/embeds/cannon-0 ++ @cp bin/cannon-impl ./multicannon/embeds/cannon-1 ++ ++cannon: cannon-embeds ++ env GO111MODULE=on GOOS=$(TARGETOS) GOARCH=$(TARGETARCH) go build -v $(LDFLAGS) -o ./bin/cannon ./multicannon/ +  + clean: + rm -rf bin +  + elf: + make -C ./testdata/example elf ++ ++sanitize-program: ++ @if ! { mips-linux-gnu-objdump -d -j .text $$GUEST_PROGRAM | awk '{print $3}' | grep -Ew -m1 '(bgezal|bltzal)'; }; then \ ++ echo "guest program is sanitized for unsupported instructions"; \ ++ else \ ++ echo "found unsupported instructions in the guest program"; \ ++ exit 1; \ ++ fi +  + contract: + cd ../packages/contracts-bedrock && forge build
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+1
+
-1
+ +
+ +
+
+
diff --git OP/cannon/README.md CELO/cannon/README.md +index e9e751ce2ffe328bbd929ace3f66d4a20932001e..a3b917193901005fe03aadef33f9c87d47e523b0 100644 +--- OP/cannon/README.md ++++ CELO/cannon/README.md +@@ -30,7 +30,7 @@ make cannon +  + # Transform MIPS op-program client binary into first VM state. + # This outputs state.json (VM state) and meta.json (for debug symbols). +-./bin/cannon load-elf --path=../op-program/bin/op-program-client.elf ++./bin/cannon load-elf --type singlethreaded --path=../op-program/bin/op-program-client.elf +  + # Run cannon emulator (with example inputs) + # Note that the server-mode op-program command is passed into cannon (after the --),
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+71
+
-54
+ +
+ +
+
+
diff --git OP/cannon/cmd/load_elf.go CELO/cannon/cmd/load_elf.go +index 39e389ff23ca80db1ca7b16651a2f16f18038fef..816eb7c02e4660595bd2fe0e0d44385ecb479fb5 100644 +--- OP/cannon/cmd/load_elf.go ++++ CELO/cannon/cmd/load_elf.go +@@ -4,31 +4,34 @@ import ( + "debug/elf" + "fmt" +  ++ "github.com/urfave/cli/v2" ++ + "github.com/ethereum-optimism/optimism/cannon/mipsevm" + "github.com/ethereum-optimism/optimism/cannon/mipsevm/multithreaded" +- "github.com/urfave/cli/v2" +- + "github.com/ethereum-optimism/optimism/cannon/mipsevm/program" + "github.com/ethereum-optimism/optimism/cannon/mipsevm/singlethreaded" ++ "github.com/ethereum-optimism/optimism/cannon/mipsevm/versions" ++ "github.com/ethereum-optimism/optimism/cannon/serialize" ++ openum "github.com/ethereum-optimism/optimism/op-service/enum" ++ "github.com/ethereum-optimism/optimism/op-service/ioutil" + "github.com/ethereum-optimism/optimism/op-service/jsonutil" + ) +  + var ( ++ LoadELFVMTypeFlag = &cli.StringFlag{ ++ Name: "type", ++ Usage: "VM type to create state for. Valid options: " + openum.EnumString(stateVersions()), ++ Required: true, ++ } + LoadELFPathFlag = &cli.PathFlag{ + Name: "path", + Usage: "Path to 32-bit big-endian MIPS ELF file", + TakesFile: true, + Required: true, + } +- LoadELFPatchFlag = &cli.StringSliceFlag{ +- Name: "patch", +- Usage: "Type of patching to do", +- Value: cli.NewStringSlice("go", "stack"), +- Required: false, +- } + LoadELFOutFlag = &cli.PathFlag{ + Name: "out", +- Usage: "Output path to write JSON state to. State is dumped to stdout if set to -. Not written if empty.", ++ Usage: "Output path to write state to. State is dumped to stdout if set to '-'. Not written if empty. Use file extension '.bin', '.bin.gz', or '.json' for binary, compressed binary, or JSON formats.", + Value: "state.json", + Required: false, + } +@@ -40,74 +43,88 @@ Required: false, + } + ) +  ++func stateVersions() []string { ++ vers := make([]string, len(versions.StateVersionTypes)) ++ for i, v := range versions.StateVersionTypes { ++ vers[i] = v.String() ++ } ++ return vers ++} ++ + func LoadELF(ctx *cli.Context) error { ++ elfPath := ctx.Path(LoadELFPathFlag.Name) ++ elfProgram, err := elf.Open(elfPath) ++ if err != nil { ++ return fmt.Errorf("failed to open ELF file %q: %w", elfPath, err) ++ } ++ if elfProgram.Machine != elf.EM_MIPS { ++ return fmt.Errorf("ELF is not big-endian MIPS R3000, but got %q", elfProgram.Machine.String()) ++ } ++ + var createInitialState func(f *elf.File) (mipsevm.FPVMState, error) +- var writeState func(path string, state mipsevm.FPVMState) error +  +- if vmType, err := vmTypeFromString(ctx); err != nil { ++ var patcher = program.PatchStack ++ ver, err := versions.ParseStateVersion(ctx.String(LoadELFVMTypeFlag.Name)) ++ if err != nil { + return err +- } else if vmType == cannonVMType { ++ } ++ switch ver { ++ case versions.VersionSingleThreaded: + createInitialState = func(f *elf.File) (mipsevm.FPVMState, error) { + return program.LoadELF(f, singlethreaded.CreateInitialState) + } +- writeState = func(path string, state mipsevm.FPVMState) error { +- return jsonutil.WriteJSON[*singlethreaded.State](path, state.(*singlethreaded.State), OutFilePerm) ++ patcher = func(state mipsevm.FPVMState) error { ++ err := program.PatchGoGC(elfProgram, state) ++ if err != nil { ++ return err ++ } ++ return program.PatchStack(state) + } +- } else if vmType == mtVMType { ++ case versions.VersionMultiThreaded: + createInitialState = func(f *elf.File) (mipsevm.FPVMState, error) { + return program.LoadELF(f, multithreaded.CreateInitialState) + } +- writeState = func(path string, state mipsevm.FPVMState) error { +- return jsonutil.WriteJSON[*multithreaded.State](path, state.(*multithreaded.State), OutFilePerm) +- } +- } else { +- return fmt.Errorf("invalid VM type: %q", vmType) ++ default: ++ return fmt.Errorf("unsupported state version: %d (%s)", ver, ver.String()) + } +- elfPath := ctx.Path(LoadELFPathFlag.Name) +- elfProgram, err := elf.Open(elfPath) +- if err != nil { +- return fmt.Errorf("failed to open ELF file %q: %w", elfPath, err) +- } +- if elfProgram.Machine != elf.EM_MIPS { +- return fmt.Errorf("ELF is not big-endian MIPS R3000, but got %q", elfProgram.Machine.String()) +- } ++ + state, err := createInitialState(elfProgram) + if err != nil { + return fmt.Errorf("failed to load ELF data into VM state: %w", err) + } +- for _, typ := range ctx.StringSlice(LoadELFPatchFlag.Name) { +- switch typ { +- case "stack": +- err = program.PatchStack(state) +- case "go": +- err = program.PatchGo(elfProgram, state) +- default: +- return fmt.Errorf("unrecognized form of patching: %q", typ) +- } +- if err != nil { +- return fmt.Errorf("failed to apply patch %s: %w", typ, err) +- } ++ err = patcher(state) ++ if err != nil { ++ return fmt.Errorf("failed to patch state: %w", err) + } + meta, err := program.MakeMetadata(elfProgram) + if err != nil { + return fmt.Errorf("failed to compute program metadata: %w", err) + } +- if err := jsonutil.WriteJSON[*program.Metadata](ctx.Path(LoadELFMetaFlag.Name), meta, OutFilePerm); err != nil { ++ if err := jsonutil.WriteJSON[*program.Metadata](meta, ioutil.ToStdOutOrFileOrNoop(ctx.Path(LoadELFMetaFlag.Name), OutFilePerm)); err != nil { + return fmt.Errorf("failed to output metadata: %w", err) + } +- return writeState(ctx.Path(LoadELFOutFlag.Name), state) ++ ++ // Ensure the state is written with appropriate version information ++ versionedState, err := versions.NewFromState(state) ++ if err != nil { ++ return fmt.Errorf("failed to create versioned state: %w", err) ++ } ++ return serialize.Write(ctx.Path(LoadELFOutFlag.Name), versionedState, OutFilePerm) + } +  +-var LoadELFCommand = &cli.Command{ +- Name: "load-elf", +- Usage: "Load ELF file into Cannon JSON state", +- Description: "Load ELF file into Cannon JSON state, optionally patch out functions", +- Action: LoadELF, +- Flags: []cli.Flag{ +- VMTypeFlag, +- LoadELFPathFlag, +- LoadELFPatchFlag, +- LoadELFOutFlag, +- LoadELFMetaFlag, +- }, ++func CreateLoadELFCommand(action cli.ActionFunc) *cli.Command { ++ return &cli.Command{ ++ Name: "load-elf", ++ Usage: "Load ELF file into Cannon state", ++ Description: "Load ELF file into Cannon state", ++ Action: action, ++ Flags: []cli.Flag{ ++ LoadELFVMTypeFlag, ++ LoadELFPathFlag, ++ LoadELFOutFlag, ++ LoadELFMetaFlag, ++ }, ++ } + } ++ ++var LoadELFCommand = CreateLoadELFCommand(LoadELF)
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+47
+
-70
+ +
+ +
+
+
diff --git OP/cannon/cmd/run.go CELO/cannon/cmd/run.go +index a806778578aa55ef8a3a7aa0c50d547e5253c70d..21f4f7c298253e7d1ccf2a60c202079787945dc2 100644 +--- OP/cannon/cmd/run.go ++++ CELO/cannon/cmd/run.go +@@ -2,6 +2,7 @@ package cmd +  + import ( + "context" ++ "errors" + "fmt" + "os" + "os/exec" +@@ -10,7 +11,9 @@ "strconv" + "strings" + "time" +  +- "github.com/ethereum-optimism/optimism/cannon/mipsevm/multithreaded" ++ "github.com/ethereum-optimism/optimism/cannon/mipsevm/versions" ++ "github.com/ethereum-optimism/optimism/cannon/serialize" ++ "github.com/ethereum-optimism/optimism/op-service/ioutil" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/log" +@@ -19,7 +22,6 @@ "github.com/urfave/cli/v2" +  + "github.com/ethereum-optimism/optimism/cannon/mipsevm" + "github.com/ethereum-optimism/optimism/cannon/mipsevm/program" +- "github.com/ethereum-optimism/optimism/cannon/mipsevm/singlethreaded" + preimage "github.com/ethereum-optimism/optimism/op-preimage" + "github.com/ethereum-optimism/optimism/op-service/jsonutil" + ) +@@ -246,7 +248,8 @@ + func (p *ProcessPreimageOracle) wait() { + err := p.cmd.Wait() + var waitErr error +- if err, ok := err.(*exec.ExitError); !ok || !err.Success() { ++ var exitErr *exec.ExitError ++ if errors.As(err, &exitErr) && !exitErr.Success() { + waitErr = err + } + p.cancelIO(fmt.Errorf("%w: pre-image server has exited", waitErr)) +@@ -275,11 +278,6 @@ + func Run(ctx *cli.Context) error { + if ctx.Bool(RunPProfCPU.Name) { + defer profile.Start(profile.NoShutdownHook, profile.ProfilePath("."), profile.CPUProfile).Stop() +- } +- +- vmType, err := vmTypeFromString(ctx) +- if err != nil { +- return err + } +  + guestLogger := Logger(os.Stderr, log.LevelInfo) +@@ -371,42 +369,19 @@ meta = m + } + } +  +- var vm mipsevm.FPVM +- var debugProgram bool +- if vmType == cannonVMType { +- l.Info("Using cannon VM") +- cannon, err := singlethreaded.NewInstrumentedStateFromFile(ctx.Path(RunInputFlag.Name), po, outLog, errLog, meta) +- if err != nil { +- return err ++ state, err := versions.LoadStateFromFile(ctx.Path(RunInputFlag.Name)) ++ if err != nil { ++ return fmt.Errorf("failed to load state: %w", err) ++ } ++ vm := state.CreateVM(l, po, outLog, errLog, meta) ++ debugProgram := ctx.Bool(RunDebugFlag.Name) ++ if debugProgram { ++ if metaPath := ctx.Path(RunMetaFlag.Name); metaPath == "" { ++ return errors.New("cannot enable debug mode without a metadata file") + } +- debugProgram = ctx.Bool(RunDebugFlag.Name) +- if debugProgram { +- if metaPath := ctx.Path(RunMetaFlag.Name); metaPath == "" { +- return fmt.Errorf("cannot enable debug mode without a metadata file") +- } +- if err := cannon.InitDebug(); err != nil { +- return fmt.Errorf("failed to initialize debug mode: %w", err) +- } ++ if err := vm.InitDebug(); err != nil { ++ return fmt.Errorf("failed to initialize debug mode: %w", err) + } +- vm = cannon +- } else if vmType == mtVMType { +- l.Info("Using cannon multithreaded VM") +- cannon, err := multithreaded.NewInstrumentedStateFromFile(ctx.Path(RunInputFlag.Name), po, outLog, errLog, l) +- if err != nil { +- return err +- } +- debugProgram = ctx.Bool(RunDebugFlag.Name) +- if debugProgram { +- if metaPath := ctx.Path(RunMetaFlag.Name); metaPath == "" { +- return fmt.Errorf("cannot enable debug mode without a metadata file") +- } +- if err := cannon.InitDebug(meta); err != nil { +- return fmt.Errorf("failed to initialize debug mode: %w", err) +- } +- } +- vm = cannon +- } else { +- return fmt.Errorf("unknown VM type %q", vmType) + } +  + proofFmt := ctx.String(RunProofFmtFlag.Name) +@@ -419,7 +394,6 @@ } +  + start := time.Now() +  +- state := vm.GetState() + startStep := state.GetStep() +  + for !state.GetExited() { +@@ -454,7 +428,7 @@ break + } +  + if snapshotAt(state) { +- if err := jsonutil.WriteJSON(fmt.Sprintf(snapshotFmt, step), state, OutFilePerm); err != nil { ++ if err := serialize.Write(fmt.Sprintf(snapshotFmt, step), state, OutFilePerm); err != nil { + return fmt.Errorf("failed to write state snapshot: %w", err) + } + } +@@ -477,7 +451,7 @@ proof.OracleKey = witness.PreimageKey[:] + proof.OracleValue = witness.PreimageValue + proof.OracleOffset = witness.PreimageOffset + } +- if err := jsonutil.WriteJSON(fmt.Sprintf(proofFmt, step), proof, OutFilePerm); err != nil { ++ if err := jsonutil.WriteJSON(proof, ioutil.ToStdOutOrFileOrNoop(fmt.Sprintf(proofFmt, step), OutFilePerm)); err != nil { + return fmt.Errorf("failed to write proof data: %w", err) + } + } else { +@@ -511,38 +485,41 @@ if debugProgram { + vm.Traceback() + } +  +- if err := jsonutil.WriteJSON(ctx.Path(RunOutputFlag.Name), state, OutFilePerm); err != nil { ++ if err := serialize.Write(ctx.Path(RunOutputFlag.Name), state, OutFilePerm); err != nil { + return fmt.Errorf("failed to write state output: %w", err) + } + if debugInfoFile := ctx.Path(RunDebugInfoFlag.Name); debugInfoFile != "" { +- if err := jsonutil.WriteJSON(debugInfoFile, vm.GetDebugInfo(), OutFilePerm); err != nil { ++ if err := jsonutil.WriteJSON(vm.GetDebugInfo(), ioutil.ToStdOutOrFileOrNoop(debugInfoFile, OutFilePerm)); err != nil { + return fmt.Errorf("failed to write benchmark data: %w", err) + } + } + return nil + } +  +-var RunCommand = &cli.Command{ +- Name: "run", +- Usage: "Run VM step(s) and generate proof data to replicate onchain.", +- Description: "Run VM step(s) and generate proof data to replicate onchain. See flags to match when to output a proof, a snapshot, or to stop early.", +- Action: Run, +- Flags: []cli.Flag{ +- VMTypeFlag, +- RunInputFlag, +- RunOutputFlag, +- RunProofAtFlag, +- RunProofFmtFlag, +- RunSnapshotAtFlag, +- RunSnapshotFmtFlag, +- RunStopAtFlag, +- RunStopAtPreimageFlag, +- RunStopAtPreimageTypeFlag, +- RunStopAtPreimageLargerThanFlag, +- RunMetaFlag, +- RunInfoAtFlag, +- RunPProfCPU, +- RunDebugFlag, +- RunDebugInfoFlag, +- }, ++func CreateRunCommand(action cli.ActionFunc) *cli.Command { ++ return &cli.Command{ ++ Name: "run", ++ Usage: "Run VM step(s) and generate proof data to replicate onchain.", ++ Description: "Run VM step(s) and generate proof data to replicate onchain. See flags to match when to output a proof, a snapshot, or to stop early.", ++ Action: action, ++ Flags: []cli.Flag{ ++ RunInputFlag, ++ RunOutputFlag, ++ RunProofAtFlag, ++ RunProofFmtFlag, ++ RunSnapshotAtFlag, ++ RunSnapshotFmtFlag, ++ RunStopAtFlag, ++ RunStopAtPreimageFlag, ++ RunStopAtPreimageTypeFlag, ++ RunStopAtPreimageLargerThanFlag, ++ RunMetaFlag, ++ RunInfoAtFlag, ++ RunPProfCPU, ++ RunDebugFlag, ++ RunDebugInfoFlag, ++ }, ++ } + } ++ ++var RunCommand = CreateRunCommand(Run)
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + (deleted) + +
+
+
+ +
+ +
+ +
+0
+
-29
+ +
+ +
+
+
diff --git OP/cannon/cmd/vmtype.go CELO/cannon/cmd/vmtype.go +deleted file mode 100644 +index 0efc22370c94d0d2e3be84c1130da51cd2307bd2..0000000000000000000000000000000000000000 +--- OP/cannon/cmd/vmtype.go ++++ /dev/null +@@ -1,29 +0,0 @@ +-package cmd +- +-import ( +- "fmt" +- +- "github.com/urfave/cli/v2" +-) +- +-type VMType string +- +-var cannonVMType VMType = "cannon" +-var mtVMType VMType = "cannon-mt" +- +-var VMTypeFlag = &cli.StringFlag{ +- Name: "type", +- Usage: "VM type to create state for. Options are 'cannon' (default), 'cannon-mt'", +- Value: "cannon", +- Required: false, +-} +- +-func vmTypeFromString(ctx *cli.Context) (VMType, error) { +- if vmTypeStr := ctx.String(VMTypeFlag.Name); vmTypeStr == string(cannonVMType) { +- return cannonVMType, nil +- } else if vmTypeStr == string(mtVMType) { +- return mtVMType, nil +- } else { +- return "", fmt.Errorf("unknown VM type %q", vmTypeStr) +- } +-}
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+17
+
-31
+ +
+ +
+
+
diff --git OP/cannon/cmd/witness.go CELO/cannon/cmd/witness.go +index eda5fbca5fa0a4016423578fda7c4545977eb386..753438493f95493d6955b53b645c48dc7b0485bf 100644 +--- OP/cannon/cmd/witness.go ++++ CELO/cannon/cmd/witness.go +@@ -4,12 +4,8 @@ import ( + "fmt" + "os" +  +- "github.com/ethereum-optimism/optimism/cannon/mipsevm" +- "github.com/ethereum-optimism/optimism/cannon/mipsevm/multithreaded" ++ factory "github.com/ethereum-optimism/optimism/cannon/mipsevm/versions" + "github.com/urfave/cli/v2" +- +- "github.com/ethereum-optimism/optimism/cannon/mipsevm/singlethreaded" +- "github.com/ethereum-optimism/optimism/op-service/jsonutil" + ) +  + var ( +@@ -29,23 +25,10 @@ + func Witness(ctx *cli.Context) error { + input := ctx.Path(WitnessInputFlag.Name) + output := ctx.Path(WitnessOutputFlag.Name) +- var state mipsevm.FPVMState +- if vmType, err := vmTypeFromString(ctx); err != nil { +- return err +- } else if vmType == cannonVMType { +- state, err = jsonutil.LoadJSON[singlethreaded.State](input) +- if err != nil { +- return fmt.Errorf("invalid input state (%v): %w", input, err) +- } +- } else if vmType == mtVMType { +- state, err = jsonutil.LoadJSON[multithreaded.State](input) +- if err != nil { +- return fmt.Errorf("invalid input state (%v): %w", input, err) +- } +- } else { +- return fmt.Errorf("invalid VM type: %q", vmType) ++ state, err := factory.LoadStateFromFile(input) ++ if err != nil { ++ return fmt.Errorf("invalid input state (%v): %w", input, err) + } +- + witness, h := state.EncodeWitness() + if output != "" { + if err := os.WriteFile(output, witness, 0755); err != nil { +@@ -56,14 +39,17 @@ fmt.Println(h.Hex()) + return nil + } +  +-var WitnessCommand = &cli.Command{ +- Name: "witness", +- Usage: "Convert a Cannon JSON state into a binary witness", +- Description: "Convert a Cannon JSON state into a binary witness. The hash of the witness is written to stdout", +- Action: Witness, +- Flags: []cli.Flag{ +- VMTypeFlag, +- WitnessInputFlag, +- WitnessOutputFlag, +- }, ++func CreateWitnessCommand(action cli.ActionFunc) *cli.Command { ++ return &cli.Command{ ++ Name: "witness", ++ Usage: "Convert a Cannon JSON state into a binary witness", ++ Description: "Convert a Cannon JSON state into a binary witness. The hash of the witness is written to stdout", ++ Action: action, ++ Flags: []cli.Flag{ ++ WitnessInputFlag, ++ WitnessOutputFlag, ++ }, ++ } + } ++ ++var WitnessCommand = CreateWitnessCommand(Witness)
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+18
+
-1
+ +
+ +
+
+
diff --git OP/cannon/mipsevm/exec/memory.go CELO/cannon/mipsevm/exec/memory.go +index d006a6f90560436bc0f421deb9b19a4800003998..3dea28dce29bd8a95a8d09101c575f47343da95c 100644 +--- OP/cannon/mipsevm/exec/memory.go ++++ CELO/cannon/mipsevm/exec/memory.go +@@ -14,7 +14,10 @@ type MemoryTrackerImpl struct { + memory *memory.Memory + lastMemAccess uint32 + memProofEnabled bool +- memProof [memory.MEM_PROOF_SIZE]byte ++ // proof of first unique memory access ++ memProof [memory.MEM_PROOF_SIZE]byte ++ // proof of second unique memory access ++ memProof2 [memory.MEM_PROOF_SIZE]byte + } +  + func NewMemoryTracker(memory *memory.Memory) *MemoryTrackerImpl { +@@ -31,6 +34,16 @@ m.memProof = m.memory.MerkleProof(effAddr) + } + } +  ++// TrackMemAccess2 creates a proof for a memory access following a call to TrackMemAccess ++// This is used to generate proofs for contiguous memory accesses within the same step ++func (m *MemoryTrackerImpl) TrackMemAccess2(effAddr uint32) { ++ if m.memProofEnabled && m.lastMemAccess+4 != effAddr { ++ panic(fmt.Errorf("unexpected disjointed mem access at %08x, last memory access is at %08x buffered", effAddr, m.lastMemAccess)) ++ } ++ m.lastMemAccess = effAddr ++ m.memProof2 = m.memory.MerkleProof(effAddr) ++} ++ + func (m *MemoryTrackerImpl) Reset(enableProof bool) { + m.memProofEnabled = enableProof + m.lastMemAccess = ^uint32(0) +@@ -39,3 +52,7 @@ + func (m *MemoryTrackerImpl) MemProof() [memory.MEM_PROOF_SIZE]byte { + return m.memProof + } ++ ++func (m *MemoryTrackerImpl) MemProof2() [memory.MEM_PROOF_SIZE]byte { ++ return m.memProof2 ++}
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+31
+
-19
+ +
+ +
+
+
diff --git OP/cannon/mipsevm/exec/mips_instructions.go CELO/cannon/mipsevm/exec/mips_instructions.go +index 0c4eb919e99f88c171a5875adc5cd051ba422e36..aec14192df93db8f30e34e0ef936be04065a2ece 100644 +--- OP/cannon/mipsevm/exec/mips_instructions.go ++++ CELO/cannon/mipsevm/exec/mips_instructions.go +@@ -5,6 +5,11 @@ "github.com/ethereum-optimism/optimism/cannon/mipsevm" + "github.com/ethereum-optimism/optimism/cannon/mipsevm/memory" + ) +  ++const ( ++ OpLoadLinked = 0x30 ++ OpStoreConditional = 0x38 ++) ++ + func GetInstructionDetails(pc uint32, memory *memory.Memory) (insn, opcode, fun uint32) { + insn = memory.GetMemory(pc) + opcode = insn >> 26 // First 6-bits +@@ -13,7 +18,7 @@ + return insn, opcode, fun + } +  +-func ExecMipsCoreStepLogic(cpu *mipsevm.CpuScalars, registers *[32]uint32, memory *memory.Memory, insn, opcode, fun uint32, memTracker MemTracker, stackTracker StackTracker) error { ++func ExecMipsCoreStepLogic(cpu *mipsevm.CpuScalars, registers *[32]uint32, memory *memory.Memory, insn, opcode, fun uint32, memTracker MemTracker, stackTracker StackTracker) (memUpdated bool, memAddr uint32, err error) { + // j-type j/jal + if opcode == 2 || opcode == 3 { + linkReg := uint32(0) +@@ -23,7 +28,8 @@ } + // Take top 4 bits of the next PC (its 256 MB region), and concatenate with the 26-bit offset + target := (cpu.NextPC & 0xF0000000) | ((insn & 0x03FFFFFF) << 2) + stackTracker.PushStack(cpu.PC, target) +- return HandleJump(cpu, registers, linkReg, target) ++ err = HandleJump(cpu, registers, linkReg, target) ++ return + } +  + // register fetch +@@ -57,7 +63,8 @@ rdReg = rtReg + } +  + if (opcode >= 4 && opcode < 8) || opcode == 1 { +- return HandleBranch(cpu, registers, opcode, insn, rtReg, rs) ++ err = HandleBranch(cpu, registers, opcode, insn, rtReg, rs) ++ return + } +  + storeAddr := uint32(0xFF_FF_FF_FF) +@@ -70,7 +77,7 @@ rs += SignExtend(insn&0xFFFF, 16) + addr := rs & 0xFFFFFFFC + memTracker.TrackMemAccess(addr) + mem = memory.GetMemory(addr) +- if opcode >= 0x28 && opcode != 0x30 { ++ if opcode >= 0x28 { + // store + storeAddr = addr + // store opcodes don't write back to a register +@@ -86,38 +93,46 @@ if fun == 8 || fun == 9 { // jr/jalr + linkReg := uint32(0) + if fun == 9 { + linkReg = rdReg ++ stackTracker.PushStack(cpu.PC, rs) ++ } else { ++ stackTracker.PopStack() + } +- stackTracker.PopStack() +- return HandleJump(cpu, registers, linkReg, rs) ++ err = HandleJump(cpu, registers, linkReg, rs) ++ return + } +  + if fun == 0xa { // movz +- return HandleRd(cpu, registers, rdReg, rs, rt == 0) ++ err = HandleRd(cpu, registers, rdReg, rs, rt == 0) ++ return + } + if fun == 0xb { // movn +- return HandleRd(cpu, registers, rdReg, rs, rt != 0) ++ err = HandleRd(cpu, registers, rdReg, rs, rt != 0) ++ return + } +  + // lo and hi registers + // can write back + if fun >= 0x10 && fun < 0x1c { +- return HandleHiLo(cpu, registers, fun, rs, rt, rdReg) ++ err = HandleHiLo(cpu, registers, fun, rs, rt, rdReg) ++ return + } + } +  +- // store conditional, write a 1 to rt +- if opcode == 0x38 && rtReg != 0 { +- registers[rtReg] = 1 +- } +- + // write memory + if storeAddr != 0xFF_FF_FF_FF { + memTracker.TrackMemAccess(storeAddr) + memory.SetMemory(storeAddr, val) ++ memUpdated = true ++ memAddr = storeAddr + } +  + // write back the value to destination register +- return HandleRd(cpu, registers, rdReg, val, true) ++ err = HandleRd(cpu, registers, rdReg, val, true) ++ return ++} ++ ++func SignExtendImmediate(insn uint32) uint32 { ++ return SignExtend(insn&0xFFFF, 16) + } +  + func ExecuteMipsInstruction(insn, opcode, fun, rs, rt, mem uint32) uint32 { +@@ -270,10 +285,6 @@ case 0x2e: // swr + val := rt << (24 - (rs&3)*8) + mask := uint32(0xFFFFFFFF) << (24 - (rs&3)*8) + return (mem & ^mask) | val +- case 0x30: // ll +- return mem +- case 0x38: // sc +- return rt + default: + panic("invalid instruction") + } +@@ -380,6 +391,7 @@ if storeReg >= 32 { + panic("invalid register") + } + if storeReg != 0 && conditional { ++ // Register 0 is a special register that always holds a value of 0 + registers[storeReg] = val + } + cpu.PC = cpu.NextPC
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+34
+
-22
+ +
+ +
+
+
diff --git OP/cannon/mipsevm/exec/mips_syscalls.go CELO/cannon/mipsevm/exec/mips_syscalls.go +index d2f49f279573cbf5f14f2432f6dbedbfe7a29e53..caf3b9bec6306519e0ff4d75f753ba5aa8eebf4d 100644 +--- OP/cannon/mipsevm/exec/mips_syscalls.go ++++ CELO/cannon/mipsevm/exec/mips_syscalls.go +@@ -14,19 +14,21 @@ ) +  + // Syscall codes + const ( +- SysMmap = 4090 +- SysBrk = 4045 +- SysClone = 4120 +- SysExitGroup = 4246 +- SysRead = 4003 +- SysWrite = 4004 +- SysFcntl = 4055 +- SysExit = 4001 +- SysSchedYield = 4162 +- SysGetTID = 4222 +- SysFutex = 4238 +- SysOpen = 4005 +- SysNanosleep = 4166 ++ SysMmap = 4090 ++ SysBrk = 4045 ++ SysClone = 4120 ++ SysExitGroup = 4246 ++ SysRead = 4003 ++ SysWrite = 4004 ++ SysFcntl = 4055 ++ SysExit = 4001 ++ SysSchedYield = 4162 ++ SysGetTID = 4222 ++ SysFutex = 4238 ++ SysOpen = 4005 ++ SysNanosleep = 4166 ++ SysClockGetTime = 4263 ++ SysGetpid = 4020 + ) +  + // Noop Syscall codes +@@ -57,17 +59,11 @@ SysGetgid = 4047 + SysLlseek = 4140 + SysMinCore = 4217 + SysTgkill = 4266 +-) +- +-// Profiling-related syscalls +-// Should be able to ignore if we patch out prometheus calls and disable memprofiling +-// TODO(cp-903) - Update patching for mt-cannon so that these can be ignored +-const ( ++ // Profiling-related syscalls + SysSetITimer = 4104 + SysTimerCreate = 4257 + SysTimerSetTime = 4258 + SysTimerDelete = 4261 +- SysClockGetTime = 4263 + ) +  + // File descriptors +@@ -132,7 +128,21 @@ ) +  + // Other constants + const ( ++ // SchedQuantum is the number of steps dedicated for a thread before it's preempted. Effectively used to emulate thread "time slices" + SchedQuantum = 100_000 ++ ++ // HZ is the assumed clock rate of an emulated MIPS32 CPU. ++ // The value of HZ is a rough estimate of the Cannon instruction count / second on a typical machine. ++ // HZ is used to emulate the clock_gettime syscall used by guest programs that have a Go runtime. ++ // The Go runtime consumes the system time to determine when to initiate gc assists and for goroutine scheduling. ++ // A HZ value that is too low (i.e. lower than the emulation speed) results in the main goroutine attempting to assist with GC more often. ++ // Adjust this value accordingly as the emulation speed changes. The HZ value should be within the same order of magnitude as the emulation speed. ++ HZ = 10_000_000 ++ ++ // ClockGettimeRealtimeFlag is the clock_gettime clock id for Linux's realtime clock: https://github.com/torvalds/linux/blob/ad618736883b8970f66af799e34007475fe33a68/include/uapi/linux/time.h#L49 ++ ClockGettimeRealtimeFlag = 0 ++ // ClockGettimeMonotonicFlag is the clock_gettime clock id for Linux's monotonic clock: https://github.com/torvalds/linux/blob/ad618736883b8970f66af799e34007475fe33a68/include/uapi/linux/time.h#L50 ++ ClockGettimeMonotonicFlag = 1 + ) +  + func GetSyscallArgs(registers *[32]uint32) (syscallNum, a0, a1, a2, a3 uint32) { +@@ -172,7 +182,7 @@ + return v0, v1, newHeap + } +  +-func HandleSysRead(a0, a1, a2 uint32, preimageKey [32]byte, preimageOffset uint32, preimageReader PreimageReader, memory *memory.Memory, memTracker MemTracker) (v0, v1, newPreimageOffset uint32) { ++func HandleSysRead(a0, a1, a2 uint32, preimageKey [32]byte, preimageOffset uint32, preimageReader PreimageReader, memory *memory.Memory, memTracker MemTracker) (v0, v1, newPreimageOffset uint32, memUpdated bool, memAddr uint32) { + // args: a0 = fd, a1 = addr, a2 = count + // returns: v0 = read, v1 = err code + v0 = uint32(0) +@@ -200,6 +210,8 @@ var outMem [4]byte + binary.BigEndian.PutUint32(outMem[:], mem) + copy(outMem[alignment:], dat[:datLen]) + memory.SetMemory(effAddr, binary.BigEndian.Uint32(outMem[:])) ++ memUpdated = true ++ memAddr = effAddr + newPreimageOffset += datLen + v0 = datLen + //fmt.Printf("read %d pre-image bytes, new offset: %d, eff addr: %08x mem: %08x\n", datLen, m.state.PreimageOffset, effAddr, outMem) +@@ -211,7 +223,7 @@ v0 = 0xFFffFFff + v1 = MipsEBADF + } +  +- return v0, v1, newPreimageOffset ++ return v0, v1, newPreimageOffset, memUpdated, memAddr + } +  + func HandleSysWrite(a0, a1, a2 uint32, lastHint hexutil.Bytes, preimageKey [32]byte, preimageOffset uint32, oracle mipsevm.PreimageOracle, memory *memory.Memory, memTracker MemTracker, stdOut, stdErr io.Writer) (v0, v1 uint32, newLastHint hexutil.Bytes, newPreimageKey common.Hash, newPreimageOffset uint32) {
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+4
+
-1
+ +
+ +
+
+
diff --git OP/cannon/mipsevm/exec/preimage.go CELO/cannon/mipsevm/exec/preimage.go +index f8039447d483099469dbf7ab0e98e48afb277d27..15c1f98e9530446d8a2c108e7bbe344d80ad6e39 100644 +--- OP/cannon/mipsevm/exec/preimage.go ++++ CELO/cannon/mipsevm/exec/preimage.go +@@ -49,7 +49,7 @@ func (p *TrackingPreimageOracleReader) ReadPreimage(key [32]byte, offset uint32) (dat [32]byte, datLen uint32) { + preimage := p.lastPreimage + if key != p.lastPreimageKey { + p.lastPreimageKey = key +- data := p.po.GetPreimage(key) ++ data := p.GetPreimage(key) + // add the length prefix + preimage = make([]byte, 0, 8+len(data)) + preimage = binary.BigEndian.AppendUint64(preimage, uint64(len(data))) +@@ -57,6 +57,9 @@ preimage = append(preimage, data...) + p.lastPreimage = preimage + } + p.lastPreimageOffset = offset ++ if offset >= uint32(len(preimage)) { ++ panic("Preimage offset out-of-bounds") ++ } + datLen = uint32(copy(dat[:], preimage[offset:])) + return + }
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+3
+
-4
+ +
+ +
+
+
diff --git OP/cannon/mipsevm/exec/stack.go CELO/cannon/mipsevm/exec/stack.go +index 378c07b558c07bb4ebe85d1b4da601068bb90290..06e919c0352fac22a1c349d3d2c537565fd9d1a6 100644 +--- OP/cannon/mipsevm/exec/stack.go ++++ CELO/cannon/mipsevm/exec/stack.go +@@ -5,7 +5,6 @@ "errors" + "fmt" +  + "github.com/ethereum-optimism/optimism/cannon/mipsevm" +- "github.com/ethereum-optimism/optimism/cannon/mipsevm/program" + ) +  + type StackTracker interface { +@@ -31,10 +30,10 @@ state mipsevm.FPVMState +  + stack []uint32 + caller []uint32 +- meta *program.Metadata ++ meta mipsevm.Metadata + } +  +-func NewStackTracker(state mipsevm.FPVMState, meta *program.Metadata) (*StackTrackerImpl, error) { ++func NewStackTracker(state mipsevm.FPVMState, meta mipsevm.Metadata) (*StackTrackerImpl, error) { + if meta == nil { + return nil, errors.New("metadata is nil") + } +@@ -42,7 +41,7 @@ return NewStackTrackerUnsafe(state, meta), nil + } +  + // NewStackTrackerUnsafe creates a new TraceableStackTracker without verifying meta is not nil +-func NewStackTrackerUnsafe(state mipsevm.FPVMState, meta *program.Metadata) *StackTrackerImpl { ++func NewStackTrackerUnsafe(state mipsevm.FPVMState, meta mipsevm.Metadata) *StackTrackerImpl { + return &StackTrackerImpl{state: state, meta: meta} + } +
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+19
+
-0
+ +
+ +
+
+
diff --git OP/cannon/mipsevm/iface.go CELO/cannon/mipsevm/iface.go +index 5cbab811ca893dc96815a0a73f3bd6423f8d1580..8e8d758e904888280fc26df44649c11bf962fc10 100644 +--- OP/cannon/mipsevm/iface.go ++++ CELO/cannon/mipsevm/iface.go +@@ -1,13 +1,19 @@ + package mipsevm +  + import ( ++ "io" ++ ++ "github.com/ethereum-optimism/optimism/cannon/serialize" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" ++ "github.com/ethereum/go-ethereum/log" +  + "github.com/ethereum-optimism/optimism/cannon/mipsevm/memory" + ) +  + type FPVMState interface { ++ serialize.Serializable ++ + GetMemory() *memory.Memory +  + // GetHeap returns the current memory address at the top of the heap +@@ -49,6 +55,16 @@ GetLastHint() hexutil.Bytes +  + // EncodeWitness returns the witness for the current state and the state hash + EncodeWitness() (witness []byte, hash common.Hash) ++ ++ // CreateVM creates a FPVM that can operate on this state. ++ CreateVM(logger log.Logger, po PreimageOracle, stdOut, stdErr io.Writer, meta Metadata) FPVM ++} ++ ++type SymbolMatcher func(addr uint32) bool ++ ++type Metadata interface { ++ LookupSymbol(addr uint32) string ++ CreateSymbolMatcher(name string) SymbolMatcher + } +  + type FPVM interface { +@@ -69,6 +85,9 @@ Traceback() +  + // GetDebugInfo returns debug information about the VM + GetDebugInfo() *DebugInfo ++ ++ // InitDebug initializes the debug mode of the VM ++ InitDebug() error +  + // LookupSymbol returns the symbol located at the specified address. + // May return an empty string if there's no symbol table available.
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+56
+
-0
+ +
+ +
+
+
diff --git OP/cannon/mipsevm/memory/memory.go CELO/cannon/mipsevm/memory/memory.go +index e02720a2c0d640a5316ab707d63d65350fc4fc8f..392a0482c48e5447e9254c3030d56e91acbfd962 100644 +--- OP/cannon/mipsevm/memory/memory.go ++++ CELO/cannon/mipsevm/memory/memory.go +@@ -286,6 +286,62 @@ addr += uint32(n) + } + } +  ++// Serialize writes the memory in a simple binary format which can be read again using Deserialize ++// The format is a simple concatenation of fields, with prefixed item count for repeating items and using big endian ++// encoding for numbers. ++// ++// len(PageCount) uint32 ++// For each page (order is arbitrary): ++// ++// page index uint32 ++// page Data [PageSize]byte ++func (m *Memory) Serialize(out io.Writer) error { ++ if err := binary.Write(out, binary.BigEndian, uint32(m.PageCount())); err != nil { ++ return err ++ } ++ for pageIndex, page := range m.pages { ++ if err := binary.Write(out, binary.BigEndian, pageIndex); err != nil { ++ return err ++ } ++ if _, err := out.Write(page.Data[:]); err != nil { ++ return err ++ } ++ } ++ return nil ++} ++ ++func (m *Memory) Deserialize(in io.Reader) error { ++ var pageCount uint32 ++ if err := binary.Read(in, binary.BigEndian, &pageCount); err != nil { ++ return err ++ } ++ for i := uint32(0); i < pageCount; i++ { ++ var pageIndex uint32 ++ if err := binary.Read(in, binary.BigEndian, &pageIndex); err != nil { ++ return err ++ } ++ page := m.AllocPage(pageIndex) ++ if _, err := io.ReadFull(in, page.Data[:]); err != nil { ++ return err ++ } ++ } ++ return nil ++} ++ ++func (m *Memory) Copy() *Memory { ++ out := NewMemory() ++ out.nodes = make(map[uint64]*[32]byte) ++ out.pages = make(map[uint32]*CachedPage) ++ out.lastPageKeys = [2]uint32{^uint32(0), ^uint32(0)} ++ out.lastPage = [2]*CachedPage{nil, nil} ++ for k, page := range m.pages { ++ data := new(Page) ++ *data = *page.Data ++ out.AllocPage(k).Data = data ++ } ++ return out ++} ++ + type memReader struct { + m *Memory + addr uint32
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+8
+
-0
+ +
+ +
+
+
diff --git OP/cannon/mipsevm/memory/memory_test.go CELO/cannon/mipsevm/memory/memory_test.go +index a2b0e745562b896d25a392212300b00bcbc9e7cc..5f3f9301e55259c13bfa828697b6d6446ef9f3d9 100644 +--- OP/cannon/mipsevm/memory/memory_test.go ++++ CELO/cannon/mipsevm/memory/memory_test.go +@@ -187,3 +187,11 @@ var res Memory + require.NoError(t, json.Unmarshal(dat, &res)) + require.Equal(t, uint32(123), res.GetMemory(8)) + } ++ ++func TestMemoryCopy(t *testing.T) { ++ m := NewMemory() ++ m.SetMemory(0x8000, 123) ++ mcpy := m.Copy() ++ require.Equal(t, uint32(123), mcpy.GetMemory(0x8000)) ++ require.Equal(t, m.MerkleRoot(), mcpy.MerkleRoot()) ++}
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+7
+
-15
+ +
+ +
+
+
diff --git OP/cannon/mipsevm/multithreaded/instrumented.go CELO/cannon/mipsevm/multithreaded/instrumented.go +index 21fb5d9f765718a683327b6e5e15782828d4d1ef..ac76d6cdb532ecd7d0601be4e5f4754651d5377a 100644 +--- OP/cannon/mipsevm/multithreaded/instrumented.go ++++ CELO/cannon/mipsevm/multithreaded/instrumented.go +@@ -8,8 +8,6 @@ "github.com/ethereum/go-ethereum/log" +  + "github.com/ethereum-optimism/optimism/cannon/mipsevm" + "github.com/ethereum-optimism/optimism/cannon/mipsevm/exec" +- "github.com/ethereum-optimism/optimism/cannon/mipsevm/program" +- "github.com/ethereum-optimism/optimism/op-service/jsonutil" + ) +  + type InstrumentedState struct { +@@ -23,12 +21,12 @@ memoryTracker *exec.MemoryTrackerImpl + stackTracker ThreadedStackTracker +  + preimageOracle *exec.TrackingPreimageOracleReader +- meta *program.Metadata ++ meta mipsevm.Metadata + } +  + var _ mipsevm.FPVM = (*InstrumentedState)(nil) +  +-func NewInstrumentedState(state *State, po mipsevm.PreimageOracle, stdOut, stdErr io.Writer, log log.Logger) *InstrumentedState { ++func NewInstrumentedState(state *State, po mipsevm.PreimageOracle, stdOut, stdErr io.Writer, log log.Logger, meta mipsevm.Metadata) *InstrumentedState { + return &InstrumentedState{ + state: state, + log: log, +@@ -37,24 +35,16 @@ stdErr: stdErr, + memoryTracker: exec.NewMemoryTracker(state.Memory), + stackTracker: &NoopThreadedStackTracker{}, + preimageOracle: exec.NewTrackingPreimageOracleReader(po), +- } +-} +- +-func NewInstrumentedStateFromFile(stateFile string, po mipsevm.PreimageOracle, stdOut, stdErr io.Writer, log log.Logger) (*InstrumentedState, error) { +- state, err := jsonutil.LoadJSON[State](stateFile) +- if err != nil { +- return nil, err ++ meta: meta, + } +- return NewInstrumentedState(state, po, stdOut, stdErr, log), nil + } +  +-func (m *InstrumentedState) InitDebug(meta *program.Metadata) error { +- stackTracker, err := NewThreadedStackTracker(m.state, meta) ++func (m *InstrumentedState) InitDebug() error { ++ stackTracker, err := NewThreadedStackTracker(m.state, m.meta) + if err != nil { + return err + } + m.stackTracker = stackTracker +- m.meta = meta + return nil + } +  +@@ -83,7 +73,9 @@ } +  + if proof { + memProof := m.memoryTracker.MemProof() ++ memProof2 := m.memoryTracker.MemProof2() + wit.ProofData = append(wit.ProofData, memProof[:]...) ++ wit.ProofData = append(wit.ProofData, memProof2[:]...) + lastPreimageKey, lastPreimage, lastPreimageOffset := m.preimageOracle.LastPreimage() + if lastPreimageOffset != ^uint32(0) { + wit.PreimageOffset = lastPreimageOffset
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+47
+
-22
+ +
+ +
+
+
diff --git OP/cannon/mipsevm/multithreaded/instrumented_test.go CELO/cannon/mipsevm/multithreaded/instrumented_test.go +index c60db57dcfdbff8d82fd68e2002dd614f2c14c3d..b3ce2d95eac3313e282f99a984a8039d83a5f608 100644 +--- OP/cannon/mipsevm/multithreaded/instrumented_test.go ++++ CELO/cannon/mipsevm/multithreaded/instrumented_test.go +@@ -15,28 +15,32 @@ "github.com/ethereum-optimism/optimism/cannon/mipsevm/testutil" + ) +  + func vmFactory(state *State, po mipsevm.PreimageOracle, stdOut, stdErr io.Writer, log log.Logger) mipsevm.FPVM { +- return NewInstrumentedState(state, po, stdOut, stdErr, log) ++ return NewInstrumentedState(state, po, stdOut, stdErr, log, nil) + } +  + func TestInstrumentedState_OpenMips(t *testing.T) { +- // TODO(cp-903): Add mt-specific tests here ++ t.Parallel() ++ // TODO: Add mt-specific tests here + testutil.RunVMTests_OpenMips(t, CreateEmptyState, vmFactory, "clone.bin") + } +  + func TestInstrumentedState_Hello(t *testing.T) { ++ t.Parallel() + testutil.RunVMTest_Hello(t, CreateInitialState, vmFactory, false) + } +  + func TestInstrumentedState_Claim(t *testing.T) { ++ t.Parallel() + testutil.RunVMTest_Claim(t, CreateInitialState, vmFactory, false) + } +  + func TestInstrumentedState_MultithreadedProgram(t *testing.T) { ++ t.Parallel() + state, _ := testutil.LoadELFProgram(t, "../../testdata/example/bin/multithreaded.elf", CreateInitialState, false) + oracle := testutil.StaticOracle(t, []byte{}) +  + var stdOutBuf, stdErrBuf bytes.Buffer +- us := NewInstrumentedState(state, oracle, io.MultiWriter(&stdOutBuf, os.Stdout), io.MultiWriter(&stdErrBuf, os.Stderr), testutil.CreateLogger()) ++ us := NewInstrumentedState(state, oracle, io.MultiWriter(&stdOutBuf, os.Stdout), io.MultiWriter(&stdErrBuf, os.Stderr), testutil.CreateLogger(), nil) + for i := 0; i < 1_000_000; i++ { + if us.GetState().GetExited() { + break +@@ -54,26 +58,47 @@ require.Equal(t, "", stdErrBuf.String(), "should not print any errors") + } +  + func TestInstrumentedState_Alloc(t *testing.T) { +- t.Skip("TODO(client-pod#906): Currently failing - need to debug.") ++ if os.Getenv("SKIP_SLOW_TESTS") == "true" { ++ t.Skip("Skipping slow test because SKIP_SLOW_TESTS is enabled") ++ } ++ ++ const MiB = 1024 * 1024 ++ ++ cases := []struct { ++ name string ++ numAllocs int ++ allocSize int ++ maxMemoryUsageCheck int ++ }{ ++ {name: "10 32MiB allocations", numAllocs: 10, allocSize: 32 * MiB, maxMemoryUsageCheck: 256 * MiB}, ++ {name: "5 64MiB allocations", numAllocs: 5, allocSize: 64 * MiB, maxMemoryUsageCheck: 256 * MiB}, ++ {name: "5 128MiB allocations", numAllocs: 5, allocSize: 128 * MiB, maxMemoryUsageCheck: 128 * 3 * MiB}, ++ } +  +- state, _ := testutil.LoadELFProgram(t, "../../testdata/example/bin/alloc.elf", CreateInitialState, false) +- const numAllocs = 100 // where each alloc is a 32 MiB chunk +- oracle := testutil.AllocOracle(t, numAllocs) ++ for _, test := range cases { ++ test := test ++ t.Run(test.name, func(t *testing.T) { ++ t.Parallel() ++ state, _ := testutil.LoadELFProgram(t, "../../testdata/example/bin/alloc.elf", CreateInitialState, false) ++ oracle := testutil.AllocOracle(t, test.numAllocs, test.allocSize) +  +- // completes in ~870 M steps +- us := NewInstrumentedState(state, oracle, os.Stdout, os.Stderr, testutil.CreateLogger()) +- for i := 0; i < 20_000_000_000; i++ { +- if us.GetState().GetExited() { +- break +- } +- _, err := us.Step(false) +- require.NoError(t, err) +- if state.Step%10_000_000 == 0 { +- t.Logf("Completed %d steps", state.Step) +- } ++ us := NewInstrumentedState(state, oracle, os.Stdout, os.Stderr, testutil.CreateLogger(), nil) ++ // emulation shouldn't take more than 20 B steps ++ for i := 0; i < 20_000_000_000; i++ { ++ if us.GetState().GetExited() { ++ break ++ } ++ _, err := us.Step(false) ++ require.NoError(t, err) ++ if state.Step%10_000_000 == 0 { ++ t.Logf("Completed %d steps", state.Step) ++ } ++ } ++ memUsage := state.Memory.PageCount() * memory.PageSize ++ t.Logf("Completed in %d steps. cannon memory usage: %d KiB", state.Step, memUsage/1024/1024.0) ++ require.True(t, state.Exited, "must complete program") ++ require.Equal(t, uint8(0), state.ExitCode, "exit with 0") ++ require.Less(t, memUsage, test.maxMemoryUsageCheck, "memory allocation is too large") ++ }) + } +- t.Logf("Completed in %d steps", state.Step) +- require.True(t, state.Exited, "must complete program") +- require.Equal(t, uint8(0), state.ExitCode, "exit with 0") +- require.Less(t, state.Memory.PageCount()*memory.PageSize, 1*1024*1024*1024, "must not allocate more than 1 GiB") + }
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+105
+
-12
+ +
+ +
+
+
diff --git OP/cannon/mipsevm/multithreaded/mips.go CELO/cannon/mipsevm/multithreaded/mips.go +index 8f7b594fcab81bfa576eb6fac47070b0d4807a00..b06ad3917724d242dc9f57eb7065576459099c3e 100644 +--- OP/cannon/mipsevm/multithreaded/mips.go ++++ CELO/cannon/mipsevm/multithreaded/mips.go +@@ -75,8 +75,13 @@ m.state.ExitCode = uint8(a0) + return nil + case exec.SysRead: + var newPreimageOffset uint32 +- v0, v1, newPreimageOffset = exec.HandleSysRead(a0, a1, a2, m.state.PreimageKey, m.state.PreimageOffset, m.preimageOracle, m.state.Memory, m.memoryTracker) ++ var memUpdated bool ++ var memAddr uint32 ++ v0, v1, newPreimageOffset, memUpdated, memAddr = exec.HandleSysRead(a0, a1, a2, m.state.PreimageKey, m.state.PreimageOffset, m.preimageOracle, m.state.Memory, m.memoryTracker) + m.state.PreimageOffset = newPreimageOffset ++ if memUpdated { ++ m.handleMemoryUpdate(memAddr) ++ } + case exec.SysWrite: + var newLastHint hexutil.Bytes + var newPreimageKey common.Hash +@@ -100,15 +105,16 @@ } + return nil + case exec.SysFutex: + // args: a0 = addr, a1 = op, a2 = val, a3 = timeout ++ effAddr := a0 & 0xFFffFFfc + switch a1 { + case exec.FutexWaitPrivate: +- m.memoryTracker.TrackMemAccess(a0) +- mem := m.state.Memory.GetMemory(a0) ++ m.memoryTracker.TrackMemAccess(effAddr) ++ mem := m.state.Memory.GetMemory(effAddr) + if mem != a2 { + v0 = exec.SysErrorSignal + v1 = exec.MipsEAGAIN + } else { +- thread.FutexAddr = a0 ++ thread.FutexAddr = effAddr + thread.FutexVal = a2 + if a3 == 0 { + thread.FutexTimeoutStep = exec.FutexNoTimeout +@@ -121,7 +127,7 @@ } + case exec.FutexWakePrivate: + // Trigger thread traversal starting from the left stack until we find one waiting on the wakeup + // address +- m.state.Wakeup = a0 ++ m.state.Wakeup = effAddr + // Don't indicate to the program that we've woken up a waiting thread, as there are no guarantees. + // The woken up thread should indicate this in userspace. + v0 = 0 +@@ -143,6 +149,32 @@ return nil + case exec.SysOpen: + v0 = exec.SysErrorSignal + v1 = exec.MipsEBADF ++ case exec.SysClockGetTime: ++ switch a0 { ++ case exec.ClockGettimeRealtimeFlag, exec.ClockGettimeMonotonicFlag: ++ v0, v1 = 0, 0 ++ var secs, nsecs uint32 ++ if a0 == exec.ClockGettimeMonotonicFlag { ++ // monotonic clock_gettime is used by Go guest programs for goroutine scheduling and to implement ++ // `time.Sleep` (and other sleep related operations). ++ secs = uint32(m.state.Step / exec.HZ) ++ nsecs = uint32((m.state.Step % exec.HZ) * (1_000_000_000 / exec.HZ)) ++ } // else realtime set to Unix Epoch ++ ++ effAddr := a1 & 0xFFffFFfc ++ m.memoryTracker.TrackMemAccess(effAddr) ++ m.state.Memory.SetMemory(effAddr, secs) ++ m.handleMemoryUpdate(effAddr) ++ m.memoryTracker.TrackMemAccess2(effAddr + 4) ++ m.state.Memory.SetMemory(effAddr+4, nsecs) ++ m.handleMemoryUpdate(effAddr + 4) ++ default: ++ v0 = exec.SysErrorSignal ++ v1 = exec.MipsEINVAL ++ } ++ case exec.SysGetpid: ++ v0 = 0 ++ v1 = 0 + case exec.SysMunmap: + case exec.SysGetAffinity: + case exec.SysMadvise: +@@ -173,7 +205,6 @@ case exec.SysSetITimer: + case exec.SysTimerCreate: + case exec.SysTimerSetTime: + case exec.SysTimerDelete: +- case exec.SysClockGetTime: + default: + m.Traceback() + panic(fmt.Sprintf("unrecognized syscall: %d", syscallNum)) +@@ -225,8 +256,9 @@ // timeout! Allow execution + m.onWaitComplete(thread, true) + return nil + } else { +- m.memoryTracker.TrackMemAccess(thread.FutexAddr) +- mem := m.state.Memory.GetMemory(thread.FutexAddr) ++ effAddr := thread.FutexAddr & 0xFFffFFfc ++ m.memoryTracker.TrackMemAccess(effAddr) ++ mem := m.state.Memory.GetMemory(effAddr) + if thread.FutexVal == mem { + // still got expected value, continue sleeping, try next thread. + m.preemptThread(thread) +@@ -263,11 +295,75 @@ if opcode == 0 && fun == 0xC { + return m.handleSyscall() + } +  ++ // Handle RMW (read-modify-write) ops ++ if opcode == exec.OpLoadLinked || opcode == exec.OpStoreConditional { ++ return m.handleRMWOps(insn, opcode) ++ } ++ + // Exec the rest of the step logic +- return exec.ExecMipsCoreStepLogic(m.state.getCpuRef(), m.state.GetRegistersRef(), m.state.Memory, insn, opcode, fun, m.memoryTracker, m.stackTracker) ++ memUpdated, memAddr, err := exec.ExecMipsCoreStepLogic(m.state.getCpuRef(), m.state.GetRegistersRef(), m.state.Memory, insn, opcode, fun, m.memoryTracker, m.stackTracker) ++ if err != nil { ++ return err ++ } ++ if memUpdated { ++ m.handleMemoryUpdate(memAddr) ++ } ++ ++ return nil ++} ++ ++func (m *InstrumentedState) handleMemoryUpdate(memAddr uint32) { ++ if memAddr == m.state.LLAddress { ++ // Reserved address was modified, clear the reservation ++ m.clearLLMemoryReservation() ++ } ++} ++ ++func (m *InstrumentedState) clearLLMemoryReservation() { ++ m.state.LLReservationActive = false ++ m.state.LLAddress = 0 ++ m.state.LLOwnerThread = 0 ++} ++ ++// handleRMWOps handles LL and SC operations which provide the primitives to implement read-modify-write operations ++func (m *InstrumentedState) handleRMWOps(insn, opcode uint32) error { ++ baseReg := (insn >> 21) & 0x1F ++ base := m.state.GetRegistersRef()[baseReg] ++ rtReg := (insn >> 16) & 0x1F ++ offset := exec.SignExtendImmediate(insn) ++ ++ effAddr := (base + offset) & 0xFFFFFFFC ++ m.memoryTracker.TrackMemAccess(effAddr) ++ mem := m.state.Memory.GetMemory(effAddr) ++ ++ var retVal uint32 ++ threadId := m.state.GetCurrentThread().ThreadId ++ if opcode == exec.OpLoadLinked { ++ retVal = mem ++ m.state.LLReservationActive = true ++ m.state.LLAddress = effAddr ++ m.state.LLOwnerThread = threadId ++ } else if opcode == exec.OpStoreConditional { ++ // Check if our memory reservation is still intact ++ if m.state.LLReservationActive && m.state.LLOwnerThread == threadId && m.state.LLAddress == effAddr { ++ // Complete atomic update: set memory and return 1 for success ++ m.clearLLMemoryReservation() ++ rt := m.state.GetRegistersRef()[rtReg] ++ m.state.Memory.SetMemory(effAddr, rt) ++ retVal = 1 ++ } else { ++ // Atomic update failed, return 0 for failure ++ retVal = 0 ++ } ++ } else { ++ panic(fmt.Sprintf("Invalid instruction passed to handleRMWOps (opcode %08x)", opcode)) ++ } ++ ++ return exec.HandleRd(m.state.getCpuRef(), m.state.GetRegistersRef(), rtReg, retVal, true) + } +  + func (m *InstrumentedState) onWaitComplete(thread *ThreadState, isTimedOut bool) { ++ // Note: no need to reset m.state.Wakeup. If we're here, the Wakeup field has already been reset + // Clear the futex state + thread.FutexAddr = exec.FutexEmptyAddr + thread.FutexVal = 0 +@@ -281,9 +377,6 @@ v0 = exec.SysErrorSignal + v1 = exec.MipsETIMEDOUT + } + exec.HandleSyscallUpdates(&thread.Cpu, &thread.Registers, v0, v1) +- +- // Clear wakeup signal +- m.state.Wakeup = exec.FutexEmptyAddr + } +  + func (m *InstrumentedState) preemptThread(thread *ThreadState) bool {
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+3
+
-3
+ +
+ +
+
+
diff --git OP/cannon/mipsevm/multithreaded/stack.go CELO/cannon/mipsevm/multithreaded/stack.go +index ab710267fbe816019cf9d6176a606882441269fa..4fc32c221ee879c707f5835b1b40a54dfe4c403f 100644 +--- OP/cannon/mipsevm/multithreaded/stack.go ++++ CELO/cannon/mipsevm/multithreaded/stack.go +@@ -3,8 +3,8 @@ + import ( + "errors" +  ++ "github.com/ethereum-optimism/optimism/cannon/mipsevm" + "github.com/ethereum-optimism/optimism/cannon/mipsevm/exec" +- "github.com/ethereum-optimism/optimism/cannon/mipsevm/program" + ) +  + type ThreadedStackTracker interface { +@@ -21,14 +21,14 @@ + func (n *NoopThreadedStackTracker) DropThread(threadId uint32) {} +  + type ThreadedStackTrackerImpl struct { +- meta *program.Metadata ++ meta mipsevm.Metadata + state *State + trackersByThreadId map[uint32]exec.TraceableStackTracker + } +  + var _ ThreadedStackTracker = (*ThreadedStackTrackerImpl)(nil) +  +-func NewThreadedStackTracker(state *State, meta *program.Metadata) (*ThreadedStackTrackerImpl, error) { ++func NewThreadedStackTracker(state *State, meta mipsevm.Metadata) (*ThreadedStackTrackerImpl, error) { + if meta == nil { + return nil, errors.New("metadata is nil") + }
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+214
+
-26
+ +
+ +
+
+
diff --git OP/cannon/mipsevm/multithreaded/state.go CELO/cannon/mipsevm/multithreaded/state.go +index 17d54c241a5e98a75c3e2529fd806eedffcb7d10..f93a99564958d8425f56408ad904197c549e5b19 100644 +--- OP/cannon/mipsevm/multithreaded/state.go ++++ CELO/cannon/mipsevm/multithreaded/state.go +@@ -3,24 +3,30 @@ + import ( + "encoding/binary" + "fmt" ++ "io" +  + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/crypto" ++ "github.com/ethereum/go-ethereum/log" +  + "github.com/ethereum-optimism/optimism/cannon/mipsevm" + "github.com/ethereum-optimism/optimism/cannon/mipsevm/exec" + "github.com/ethereum-optimism/optimism/cannon/mipsevm/memory" ++ "github.com/ethereum-optimism/optimism/cannon/serialize" + ) +  + // STATE_WITNESS_SIZE is the size of the state witness encoding in bytes. +-const STATE_WITNESS_SIZE = 163 ++const STATE_WITNESS_SIZE = 172 + const ( + MEMROOT_WITNESS_OFFSET = 0 + PREIMAGE_KEY_WITNESS_OFFSET = MEMROOT_WITNESS_OFFSET + 32 + PREIMAGE_OFFSET_WITNESS_OFFSET = PREIMAGE_KEY_WITNESS_OFFSET + 32 + HEAP_WITNESS_OFFSET = PREIMAGE_OFFSET_WITNESS_OFFSET + 4 +- EXITCODE_WITNESS_OFFSET = HEAP_WITNESS_OFFSET + 4 ++ LL_RESERVATION_ACTIVE_OFFSET = HEAP_WITNESS_OFFSET + 4 ++ LL_ADDRESS_OFFSET = LL_RESERVATION_ACTIVE_OFFSET + 1 ++ LL_OWNER_THREAD_OFFSET = LL_ADDRESS_OFFSET + 4 ++ EXITCODE_WITNESS_OFFSET = LL_OWNER_THREAD_OFFSET + 4 + EXITED_WITNESS_OFFSET = EXITCODE_WITNESS_OFFSET + 1 + STEP_WITNESS_OFFSET = EXITED_WITNESS_OFFSET + 1 + STEPS_SINCE_CONTEXT_SWITCH_WITNESS_OFFSET = STEP_WITNESS_OFFSET + 8 +@@ -32,27 +38,30 @@ THREAD_ID_WITNESS_OFFSET = RIGHT_THREADS_ROOT_WITNESS_OFFSET + 32 + ) +  + type State struct { +- Memory *memory.Memory `json:"memory"` ++ Memory *memory.Memory +  +- PreimageKey common.Hash `json:"preimageKey"` +- PreimageOffset uint32 `json:"preimageOffset"` // note that the offset includes the 8-byte length prefix ++ PreimageKey common.Hash ++ PreimageOffset uint32 // note that the offset includes the 8-byte length prefix +  +- Heap uint32 `json:"heap"` // to handle mmap growth ++ Heap uint32 // to handle mmap growth ++ LLReservationActive bool // Whether there is an active memory reservation initiated via the LL (load linked) op ++ LLAddress uint32 // The "linked" memory address reserved via the LL (load linked) op ++ LLOwnerThread uint32 // The id of the thread that holds the reservation on LLAddress +  +- ExitCode uint8 `json:"exit"` +- Exited bool `json:"exited"` ++ ExitCode uint8 ++ Exited bool +  +- Step uint64 `json:"step"` +- StepsSinceLastContextSwitch uint64 `json:"stepsSinceLastContextSwitch"` +- Wakeup uint32 `json:"wakeup"` ++ Step uint64 ++ StepsSinceLastContextSwitch uint64 ++ Wakeup uint32 +  +- TraverseRight bool `json:"traverseRight"` +- LeftThreadStack []*ThreadState `json:"leftThreadStack"` +- RightThreadStack []*ThreadState `json:"rightThreadStack"` +- NextThreadId uint32 `json:"nextThreadId"` ++ TraverseRight bool ++ LeftThreadStack []*ThreadState ++ RightThreadStack []*ThreadState ++ NextThreadId uint32 +  + // LastHint is optional metadata, and not part of the VM state itself. +- LastHint hexutil.Bytes `json:"lastHint,omitempty"` ++ LastHint hexutil.Bytes + } +  + var _ mipsevm.FPVMState = (*State)(nil) +@@ -61,16 +70,19 @@ func CreateEmptyState() *State { + initThread := CreateEmptyThread() +  + return &State{ +- Memory: memory.NewMemory(), +- Heap: 0, +- ExitCode: 0, +- Exited: false, +- Step: 0, +- Wakeup: exec.FutexEmptyAddr, +- TraverseRight: false, +- LeftThreadStack: []*ThreadState{initThread}, +- RightThreadStack: []*ThreadState{}, +- NextThreadId: initThread.ThreadId + 1, ++ Memory: memory.NewMemory(), ++ Heap: 0, ++ LLReservationActive: false, ++ LLAddress: 0, ++ LLOwnerThread: 0, ++ ExitCode: 0, ++ Exited: false, ++ Step: 0, ++ Wakeup: exec.FutexEmptyAddr, ++ TraverseRight: false, ++ LeftThreadStack: []*ThreadState{initThread}, ++ RightThreadStack: []*ThreadState{}, ++ NextThreadId: initThread.ThreadId + 1, + } + } +  +@@ -82,6 +94,11 @@ currentThread.Cpu.NextPC = pc + 4 + state.Heap = heapStart +  + return state ++} ++ ++func (s *State) CreateVM(logger log.Logger, po mipsevm.PreimageOracle, stdOut, stdErr io.Writer, meta mipsevm.Metadata) mipsevm.FPVM { ++ logger.Info("Using cannon multithreaded VM") ++ return NewInstrumentedState(s, po, stdOut, stdErr, logger, meta) + } +  + func (s *State) GetCurrentThread() *ThreadState { +@@ -179,6 +196,9 @@ out = append(out, memRoot[:]...) + out = append(out, s.PreimageKey[:]...) + out = binary.BigEndian.AppendUint32(out, s.PreimageOffset) + out = binary.BigEndian.AppendUint32(out, s.Heap) ++ out = mipsevm.AppendBoolToWitness(out, s.LLReservationActive) ++ out = binary.BigEndian.AppendUint32(out, s.LLAddress) ++ out = binary.BigEndian.AppendUint32(out, s.LLOwnerThread) + out = append(out, s.ExitCode) + out = mipsevm.AppendBoolToWitness(out, s.Exited) +  +@@ -217,6 +237,174 @@ } +  + func (s *State) ThreadCount() int { + return len(s.LeftThreadStack) + len(s.RightThreadStack) ++} ++ ++// Serialize writes the state in a simple binary format which can be read again using Deserialize ++// The format is a simple concatenation of fields, with prefixed item count for repeating items and using big endian ++// encoding for numbers. ++// ++// StateVersion uint8(1) ++// Memory As per Memory.Serialize ++// PreimageKey [32]byte ++// PreimageOffset uint32 ++// Heap uint32 ++// ExitCode uint8 ++// Exited uint8 - 0 for false, 1 for true ++// Step uint64 ++// StepsSinceLastContextSwitch uint64 ++// Wakeup uint32 ++// TraverseRight uint8 - 0 for false, 1 for true ++// NextThreadId uint32 ++// len(LeftThreadStack) uint32 ++// LeftThreadStack entries as per ThreadState.Serialize ++// len(RightThreadStack) uint32 ++// RightThreadStack entries as per ThreadState.Serialize ++// len(LastHint) uint32 (0 when LastHint is nil) ++// LastHint []byte ++func (s *State) Serialize(out io.Writer) error { ++ bout := serialize.NewBinaryWriter(out) ++ ++ if err := s.Memory.Serialize(out); err != nil { ++ return err ++ } ++ if err := bout.WriteHash(s.PreimageKey); err != nil { ++ return err ++ } ++ if err := bout.WriteUInt(s.PreimageOffset); err != nil { ++ return err ++ } ++ if err := bout.WriteUInt(s.Heap); err != nil { ++ return err ++ } ++ if err := bout.WriteBool(s.LLReservationActive); err != nil { ++ return err ++ } ++ if err := bout.WriteUInt(s.LLAddress); err != nil { ++ return err ++ } ++ if err := bout.WriteUInt(s.LLOwnerThread); err != nil { ++ return err ++ } ++ if err := bout.WriteUInt(s.ExitCode); err != nil { ++ return err ++ } ++ if err := bout.WriteBool(s.Exited); err != nil { ++ return err ++ } ++ if err := bout.WriteUInt(s.Step); err != nil { ++ return err ++ } ++ if err := bout.WriteUInt(s.StepsSinceLastContextSwitch); err != nil { ++ return err ++ } ++ if err := bout.WriteUInt(s.Wakeup); err != nil { ++ return err ++ } ++ if err := bout.WriteBool(s.TraverseRight); err != nil { ++ return err ++ } ++ if err := bout.WriteUInt(s.NextThreadId); err != nil { ++ return err ++ } ++ ++ if err := bout.WriteUInt(uint32(len(s.LeftThreadStack))); err != nil { ++ return err ++ } ++ for _, stack := range s.LeftThreadStack { ++ if err := stack.Serialize(out); err != nil { ++ return err ++ } ++ } ++ if err := bout.WriteUInt(uint32(len(s.RightThreadStack))); err != nil { ++ return err ++ } ++ for _, stack := range s.RightThreadStack { ++ if err := stack.Serialize(out); err != nil { ++ return err ++ } ++ } ++ if err := bout.WriteBytes(s.LastHint); err != nil { ++ return err ++ } ++ ++ return nil ++} ++ ++func (s *State) Deserialize(in io.Reader) error { ++ bin := serialize.NewBinaryReader(in) ++ s.Memory = memory.NewMemory() ++ if err := s.Memory.Deserialize(in); err != nil { ++ return err ++ } ++ if err := bin.ReadHash(&s.PreimageKey); err != nil { ++ return err ++ } ++ if err := bin.ReadUInt(&s.PreimageOffset); err != nil { ++ return err ++ } ++ if err := bin.ReadUInt(&s.Heap); err != nil { ++ return err ++ } ++ if err := bin.ReadBool(&s.LLReservationActive); err != nil { ++ return err ++ } ++ if err := bin.ReadUInt(&s.LLAddress); err != nil { ++ return err ++ } ++ if err := bin.ReadUInt(&s.LLOwnerThread); err != nil { ++ return err ++ } ++ if err := bin.ReadUInt(&s.ExitCode); err != nil { ++ return err ++ } ++ if err := bin.ReadBool(&s.Exited); err != nil { ++ return err ++ } ++ if err := bin.ReadUInt(&s.Step); err != nil { ++ return err ++ } ++ if err := bin.ReadUInt(&s.StepsSinceLastContextSwitch); err != nil { ++ return err ++ } ++ if err := bin.ReadUInt(&s.Wakeup); err != nil { ++ return err ++ } ++ if err := bin.ReadBool(&s.TraverseRight); err != nil { ++ return err ++ } ++ ++ if err := bin.ReadUInt(&s.NextThreadId); err != nil { ++ return err ++ } ++ ++ var leftThreadStackSize uint32 ++ if err := bin.ReadUInt(&leftThreadStackSize); err != nil { ++ return err ++ } ++ s.LeftThreadStack = make([]*ThreadState, leftThreadStackSize) ++ for i := range s.LeftThreadStack { ++ s.LeftThreadStack[i] = &ThreadState{} ++ if err := s.LeftThreadStack[i].Deserialize(in); err != nil { ++ return err ++ } ++ } ++ ++ var rightThreadStackSize uint32 ++ if err := bin.ReadUInt(&rightThreadStackSize); err != nil { ++ return err ++ } ++ s.RightThreadStack = make([]*ThreadState, rightThreadStackSize) ++ for i := range s.RightThreadStack { ++ s.RightThreadStack[i] = &ThreadState{} ++ if err := s.RightThreadStack[i].Deserialize(in); err != nil { ++ return err ++ } ++ } ++ ++ if err := bin.ReadBytes((*[]byte)(&s.LastHint)); err != nil { ++ return err ++ } ++ return nil + } +  + type StateWitness []byte
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+163
+
-0
+ +
+ +
+
+
diff --git OP/cannon/mipsevm/multithreaded/state_test.go CELO/cannon/mipsevm/multithreaded/state_test.go +index c267416b8ae4c55eca08952c7a59f8a590c6192d..6d776632bf0f008e30ccfb725806214a4cbd4b14 100644 +--- OP/cannon/mipsevm/multithreaded/state_test.go ++++ CELO/cannon/mipsevm/multithreaded/state_test.go +@@ -1,16 +1,20 @@ + package multithreaded +  + import ( ++ "bytes" + "debug/elf" + "encoding/json" + "testing" +  ++ "github.com/ethereum/go-ethereum/common" ++ "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/crypto" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +  + "github.com/ethereum-optimism/optimism/cannon/mipsevm" + "github.com/ethereum-optimism/optimism/cannon/mipsevm/exec" ++ "github.com/ethereum-optimism/optimism/cannon/mipsevm/memory" + "github.com/ethereum-optimism/optimism/cannon/mipsevm/program" + ) +  +@@ -38,6 +42,8 @@ {exited: true, exitCode: 3}, + } +  + heap := uint32(12) ++ llAddress := uint32(55) ++ llThreadOwner := uint32(99) + preimageKey := crypto.Keccak256Hash([]byte{1, 2, 3, 4}) + preimageOffset := uint32(24) + step := uint64(33) +@@ -49,6 +55,9 @@ state.ExitCode = c.exitCode + state.PreimageKey = preimageKey + state.PreimageOffset = preimageOffset + state.Heap = heap ++ state.LLReservationActive = true ++ state.LLAddress = llAddress ++ state.LLOwnerThread = llThreadOwner + state.Step = step + state.StepsSinceLastContextSwitch = stepsSinceContextSwitch +  +@@ -62,6 +71,9 @@ setWitnessField(expectedWitness, MEMROOT_WITNESS_OFFSET, memRoot[:]) + setWitnessField(expectedWitness, PREIMAGE_KEY_WITNESS_OFFSET, preimageKey[:]) + setWitnessField(expectedWitness, PREIMAGE_OFFSET_WITNESS_OFFSET, []byte{0, 0, 0, byte(preimageOffset)}) + setWitnessField(expectedWitness, HEAP_WITNESS_OFFSET, []byte{0, 0, 0, byte(heap)}) ++ setWitnessField(expectedWitness, LL_RESERVATION_ACTIVE_OFFSET, []byte{1}) ++ setWitnessField(expectedWitness, LL_ADDRESS_OFFSET, []byte{0, 0, 0, byte(llAddress)}) ++ setWitnessField(expectedWitness, LL_OWNER_THREAD_OFFSET, []byte{0, 0, 0, byte(llThreadOwner)}) + setWitnessField(expectedWitness, EXITCODE_WITNESS_OFFSET, []byte{c.exitCode}) + if c.exited { + setWitnessField(expectedWitness, EXITED_WITNESS_OFFSET, []byte{1}) +@@ -121,6 +133,157 @@ require.Equal(t, state.LeftThreadStack, newState.LeftThreadStack) + require.Equal(t, state.RightThreadStack, newState.RightThreadStack) + require.Equal(t, state.NextThreadId, newState.NextThreadId) + require.Equal(t, state.LastHint, newState.LastHint) ++} ++ ++func TestState_Binary(t *testing.T) { ++ elfProgram, err := elf.Open("../../testdata/example/bin/hello.elf") ++ require.NoError(t, err, "open ELF file") ++ state, err := program.LoadELF(elfProgram, CreateInitialState) ++ require.NoError(t, err, "load ELF into state") ++ // Set a few additional fields ++ state.PreimageKey = crypto.Keccak256Hash([]byte{1, 2, 3, 4}) ++ state.PreimageOffset = 4 ++ state.Heap = 555 ++ state.Step = 99_999 ++ state.StepsSinceLastContextSwitch = 123 ++ state.Exited = true ++ state.ExitCode = 2 ++ state.LastHint = []byte{11, 12, 13} ++ ++ buf := new(bytes.Buffer) ++ err = state.Serialize(buf) ++ require.NoError(t, err) ++ ++ newState := new(State) ++ require.NoError(t, newState.Deserialize(bytes.NewReader(buf.Bytes()))) ++ ++ require.Equal(t, state.PreimageKey, newState.PreimageKey) ++ require.Equal(t, state.PreimageOffset, newState.PreimageOffset) ++ require.Equal(t, state.Heap, newState.Heap) ++ require.Equal(t, state.ExitCode, newState.ExitCode) ++ require.Equal(t, state.Exited, newState.Exited) ++ require.Equal(t, state.Memory.MerkleRoot(), newState.Memory.MerkleRoot()) ++ require.Equal(t, state.Step, newState.Step) ++ require.Equal(t, state.StepsSinceLastContextSwitch, newState.StepsSinceLastContextSwitch) ++ require.Equal(t, state.Wakeup, newState.Wakeup) ++ require.Equal(t, state.TraverseRight, newState.TraverseRight) ++ require.Equal(t, state.LeftThreadStack, newState.LeftThreadStack) ++ require.Equal(t, state.RightThreadStack, newState.RightThreadStack) ++ require.Equal(t, state.NextThreadId, newState.NextThreadId) ++ require.Equal(t, state.LastHint, newState.LastHint) ++} ++ ++func TestSerializeStateRoundTrip(t *testing.T) { ++ // Construct a test case with populated fields ++ mem := memory.NewMemory() ++ mem.AllocPage(5) ++ p := mem.AllocPage(123) ++ p.Data[2] = 0x01 ++ state := &State{ ++ Memory: mem, ++ PreimageKey: common.Hash{0xFF}, ++ PreimageOffset: 5, ++ Heap: 0xc0ffee, ++ LLReservationActive: true, ++ LLAddress: 0x12345678, ++ LLOwnerThread: 0x02, ++ ExitCode: 1, ++ Exited: true, ++ Step: 0xdeadbeef, ++ StepsSinceLastContextSwitch: 334, ++ Wakeup: 42, ++ TraverseRight: true, ++ LeftThreadStack: []*ThreadState{ ++ { ++ ThreadId: 45, ++ ExitCode: 46, ++ Exited: true, ++ FutexAddr: 47, ++ FutexVal: 48, ++ FutexTimeoutStep: 49, ++ Cpu: mipsevm.CpuScalars{ ++ PC: 0xFF, ++ NextPC: 0xFF + 4, ++ LO: 0xbeef, ++ HI: 0xbabe, ++ }, ++ Registers: [32]uint32{ ++ 0xdeadbeef, ++ 0xdeadbeef, ++ 0xc0ffee, ++ 0xbeefbabe, ++ 0xdeadc0de, ++ 0xbadc0de, ++ 0xdeaddead, ++ }, ++ }, ++ { ++ ThreadId: 55, ++ ExitCode: 56, ++ Exited: false, ++ FutexAddr: 57, ++ FutexVal: 58, ++ FutexTimeoutStep: 59, ++ Cpu: mipsevm.CpuScalars{ ++ PC: 0xEE, ++ NextPC: 0xEE + 4, ++ LO: 0xeeef, ++ HI: 0xeabe, ++ }, ++ Registers: [32]uint32{ ++ 0xabcdef, ++ 0x123456, ++ }, ++ }, ++ }, ++ RightThreadStack: []*ThreadState{ ++ { ++ ThreadId: 65, ++ ExitCode: 66, ++ Exited: false, ++ FutexAddr: 67, ++ FutexVal: 68, ++ FutexTimeoutStep: 69, ++ Cpu: mipsevm.CpuScalars{ ++ PC: 0xdd, ++ NextPC: 0xdd + 4, ++ LO: 0xdeef, ++ HI: 0xdabe, ++ }, ++ Registers: [32]uint32{ ++ 0x654321, ++ }, ++ }, ++ { ++ ThreadId: 75, ++ ExitCode: 76, ++ Exited: true, ++ FutexAddr: 77, ++ FutexVal: 78, ++ FutexTimeoutStep: 79, ++ Cpu: mipsevm.CpuScalars{ ++ PC: 0xcc, ++ NextPC: 0xcc + 4, ++ LO: 0xceef, ++ HI: 0xcabe, ++ }, ++ Registers: [32]uint32{ ++ 0x987653, ++ 0xfedbca, ++ }, ++ }, ++ }, ++ NextThreadId: 489, ++ LastHint: hexutil.Bytes{1, 2, 3, 4, 5}, ++ } ++ ++ ser := new(bytes.Buffer) ++ err := state.Serialize(ser) ++ require.NoError(t, err, "must serialize state") ++ state2 := &State{} ++ err = state2.Deserialize(ser) ++ require.NoError(t, err, "must deserialize state") ++ require.Equal(t, state, state2, "must roundtrip state") + } +  + func TestState_EmptyThreadsRoot(t *testing.T) {
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+39
+
-16
+ +
+ +
+
+
diff --git OP/cannon/mipsevm/multithreaded/testutil/expectations.go CELO/cannon/mipsevm/multithreaded/testutil/expectations.go +index f2e1bbb200f04bcf11dc31951a5d97b8a01c1b45..559ed2de8c4fdd79b38268986a6a2bb9875ce6c4 100644 +--- OP/cannon/mipsevm/multithreaded/testutil/expectations.go ++++ CELO/cannon/mipsevm/multithreaded/testutil/expectations.go +@@ -7,20 +7,25 @@ "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/stretchr/testify/require" +  ++ "github.com/ethereum-optimism/optimism/cannon/mipsevm/memory" + "github.com/ethereum-optimism/optimism/cannon/mipsevm/multithreaded" + ) +  + // ExpectedMTState is a test utility that basically stores a copy of a state that can be explicitly mutated + // to define an expected post-state. The post-state is then validated with ExpectedMTState.Validate(t, postState) + type ExpectedMTState struct { +- PreimageKey common.Hash +- PreimageOffset uint32 +- Heap uint32 +- ExitCode uint8 +- Exited bool +- Step uint64 +- LastHint hexutil.Bytes +- MemoryRoot common.Hash ++ PreimageKey common.Hash ++ PreimageOffset uint32 ++ Heap uint32 ++ LLReservationActive bool ++ LLAddress uint32 ++ LLOwnerThread uint32 ++ ExitCode uint8 ++ Exited bool ++ Step uint64 ++ LastHint hexutil.Bytes ++ MemoryRoot common.Hash ++ expectedMemory *memory.Memory + // Threading-related expectations + StepsSinceLastContextSwitch uint64 + Wakeup uint32 +@@ -60,14 +65,17 @@ } +  + return &ExpectedMTState{ + // General Fields +- PreimageKey: fromState.GetPreimageKey(), +- PreimageOffset: fromState.GetPreimageOffset(), +- Heap: fromState.GetHeap(), +- ExitCode: fromState.GetExitCode(), +- Exited: fromState.GetExited(), +- Step: fromState.GetStep(), +- LastHint: fromState.GetLastHint(), +- MemoryRoot: fromState.GetMemory().MerkleRoot(), ++ PreimageKey: fromState.GetPreimageKey(), ++ PreimageOffset: fromState.GetPreimageOffset(), ++ Heap: fromState.GetHeap(), ++ LLReservationActive: fromState.LLReservationActive, ++ LLAddress: fromState.LLAddress, ++ LLOwnerThread: fromState.LLOwnerThread, ++ ExitCode: fromState.GetExitCode(), ++ Exited: fromState.GetExited(), ++ Step: fromState.GetStep(), ++ LastHint: fromState.GetLastHint(), ++ MemoryRoot: fromState.GetMemory().MerkleRoot(), + // Thread-related global fields + StepsSinceLastContextSwitch: fromState.StepsSinceLastContextSwitch, + Wakeup: fromState.Wakeup, +@@ -81,6 +89,7 @@ prestateActiveThreadId: currentThread.ThreadId, + prestateActiveThreadOrig: *newExpectedThreadState(currentThread), // Cache prestate thread for internal use + ActiveThreadId: currentThread.ThreadId, + threadExpectations: expectedThreads, ++ expectedMemory: fromState.Memory.Copy(), + } + } +  +@@ -109,6 +118,17 @@ e.PrestateActiveThread().NextPC += 4 + e.StepsSinceLastContextSwitch += 1 + } +  ++func (e *ExpectedMTState) ExpectMemoryWrite(addr uint32, val uint32) { ++ e.expectedMemory.SetMemory(addr, val) ++ e.MemoryRoot = e.expectedMemory.MerkleRoot() ++} ++ ++func (e *ExpectedMTState) ExpectMemoryWriteMultiple(addr uint32, val uint32, addr2 uint32, val2 uint32) { ++ e.expectedMemory.SetMemory(addr, val) ++ e.expectedMemory.SetMemory(addr2, val2) ++ e.MemoryRoot = e.expectedMemory.MerkleRoot() ++} ++ + func (e *ExpectedMTState) ExpectPreemption(preState *multithreaded.State) { + e.ActiveThreadId = FindNextThread(preState).ThreadId + e.StepsSinceLastContextSwitch = 0 +@@ -154,6 +174,9 @@ func (e *ExpectedMTState) Validate(t require.TestingT, actualState *multithreaded.State) { + require.Equalf(t, e.PreimageKey, actualState.GetPreimageKey(), "Expect preimageKey = %v", e.PreimageKey) + require.Equalf(t, e.PreimageOffset, actualState.GetPreimageOffset(), "Expect preimageOffset = %v", e.PreimageOffset) + require.Equalf(t, e.Heap, actualState.GetHeap(), "Expect heap = 0x%x", e.Heap) ++ require.Equalf(t, e.LLReservationActive, actualState.LLReservationActive, "Expect LLReservationActive = %v", e.LLReservationActive) ++ require.Equalf(t, e.LLAddress, actualState.LLAddress, "Expect LLAddress = 0x%x", e.LLAddress) ++ require.Equalf(t, e.LLOwnerThread, actualState.LLOwnerThread, "Expect LLOwnerThread = %v", e.LLOwnerThread) + require.Equalf(t, e.ExitCode, actualState.GetExitCode(), "Expect exitCode = 0x%x", e.ExitCode) + require.Equalf(t, e.Exited, actualState.GetExited(), "Expect exited = %v", e.Exited) + require.Equalf(t, e.Step, actualState.GetStep(), "Expect step = %d", e.Step)
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+3
+
-0
+ +
+ +
+
+
diff --git OP/cannon/mipsevm/multithreaded/testutil/expectations_test.go CELO/cannon/mipsevm/multithreaded/testutil/expectations_test.go +index 15cba8b00469a6d5c3f63dea5c44f5916625ff4f..a40e15e0f8d57dce8a06cc271fb04b710b07b955 100644 +--- OP/cannon/mipsevm/multithreaded/testutil/expectations_test.go ++++ CELO/cannon/mipsevm/multithreaded/testutil/expectations_test.go +@@ -28,6 +28,9 @@ }{ + {name: "PreimageKey", mut: func(e *ExpectedMTState, st *multithreaded.State) { e.PreimageKey = emptyHash }}, + {name: "PreimageOffset", mut: func(e *ExpectedMTState, st *multithreaded.State) { e.PreimageOffset += 1 }}, + {name: "Heap", mut: func(e *ExpectedMTState, st *multithreaded.State) { e.Heap += 1 }}, ++ {name: "LLReservationActive", mut: func(e *ExpectedMTState, st *multithreaded.State) { e.LLReservationActive = !e.LLReservationActive }}, ++ {name: "LLAddress", mut: func(e *ExpectedMTState, st *multithreaded.State) { e.LLAddress += 1 }}, ++ {name: "LLOwnerThread", mut: func(e *ExpectedMTState, st *multithreaded.State) { e.LLOwnerThread += 1 }}, + {name: "ExitCode", mut: func(e *ExpectedMTState, st *multithreaded.State) { e.ExitCode += 1 }}, + {name: "Exited", mut: func(e *ExpectedMTState, st *multithreaded.State) { e.Exited = !e.Exited }}, + {name: "Step", mut: func(e *ExpectedMTState, st *multithreaded.State) { e.Step += 1 }},
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+14
+
-6
+ +
+ +
+
+
diff --git OP/cannon/mipsevm/multithreaded/testutil/mutators.go CELO/cannon/mipsevm/multithreaded/testutil/mutators.go +index 30a97691609eaea01f9f305e56fab54f670b2c55..a44ba23a4fac26d715d49080fabb956a0b665812 100644 +--- OP/cannon/mipsevm/multithreaded/testutil/mutators.go ++++ CELO/cannon/mipsevm/multithreaded/testutil/mutators.go +@@ -1,7 +1,7 @@ + package testutil +  + import ( +- "math/rand" ++ "math" +  + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" +@@ -22,16 +22,24 @@ return &StateMutatorMultiThreaded{state: state} + } +  + func (m *StateMutatorMultiThreaded) Randomize(randSeed int64) { +- r := rand.New(rand.NewSource(randSeed)) ++ r := testutil.NewRandHelper(randSeed) +  +- step := testutil.RandStep(r) ++ step := r.RandStep() +  +- m.state.PreimageKey = testutil.RandHash(r) ++ m.state.PreimageKey = r.RandHash() + m.state.PreimageOffset = r.Uint32() +- m.state.Heap = r.Uint32() + m.state.Step = step +- m.state.LastHint = testutil.RandHint(r) ++ m.state.LastHint = r.RandHint() + m.state.StepsSinceLastContextSwitch = uint64(r.Intn(exec.SchedQuantum)) ++ ++ // Randomize memory-related fields ++ halfMemory := math.MaxUint32 / 2 ++ m.state.Heap = uint32(r.Intn(halfMemory) + halfMemory) ++ m.state.LLReservationActive = r.Intn(2) == 1 ++ if m.state.LLReservationActive { ++ m.state.LLAddress = uint32(r.Intn(halfMemory)) ++ m.state.LLOwnerThread = uint32(r.Intn(10)) ++ } +  + // Randomize threads + activeStackThreads := r.Intn(2) + 1
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+3
+
-5
+ +
+ +
+
+
diff --git OP/cannon/mipsevm/multithreaded/testutil/thread.go CELO/cannon/mipsevm/multithreaded/testutil/thread.go +index 217ab94e81855b5ee7fc14635a51f73263b39839..f5b1d29a8dd60e4ece9c7a0283cc0c926345c3c7 100644 +--- OP/cannon/mipsevm/multithreaded/testutil/thread.go ++++ CELO/cannon/mipsevm/multithreaded/testutil/thread.go +@@ -1,19 +1,17 @@ + package testutil +  + import ( +- "math/rand" +- + "github.com/ethereum-optimism/optimism/cannon/mipsevm/multithreaded" + "github.com/ethereum-optimism/optimism/cannon/mipsevm/testutil" + ) +  + func RandomThread(randSeed int64) *multithreaded.ThreadState { +- r := rand.New(rand.NewSource(randSeed)) ++ r := testutil.NewRandHelper(randSeed) + thread := multithreaded.CreateEmptyThread() +  +- pc := testutil.RandPC(r) ++ pc := r.RandPC() +  +- thread.Registers = *testutil.RandRegisters(r) ++ thread.Registers = *r.RandRegisters() + thread.Cpu.PC = pc + thread.Cpu.NextPC = pc + 4 + thread.Cpu.HI = r.Uint32()
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+50
+
-0
+ +
+ +
+
+
diff --git OP/cannon/mipsevm/multithreaded/thread.go CELO/cannon/mipsevm/multithreaded/thread.go +index fd91900d3e835bca7d19562a1be72efc05326f5d..f811a52be4676c49e14edf9126c65a13def72885 100644 +--- OP/cannon/mipsevm/multithreaded/thread.go ++++ CELO/cannon/mipsevm/multithreaded/thread.go +@@ -2,6 +2,7 @@ package multithreaded +  + import ( + "encoding/binary" ++ "io" +  + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" +@@ -72,6 +73,55 @@ out = binary.BigEndian.AppendUint32(out, r) + } +  + return out ++} ++ ++// Serialize writes the ThreadState in a simple binary format which can be read again using Deserialize ++// The format exactly matches the serialization generated by serializeThread used for thread proofs. ++func (t *ThreadState) Serialize(out io.Writer) error { ++ _, err := out.Write(t.serializeThread()) ++ return err ++} ++ ++func (t *ThreadState) Deserialize(in io.Reader) error { ++ if err := binary.Read(in, binary.BigEndian, &t.ThreadId); err != nil { ++ return err ++ } ++ if err := binary.Read(in, binary.BigEndian, &t.ExitCode); err != nil { ++ return err ++ } ++ var exited uint8 ++ if err := binary.Read(in, binary.BigEndian, &exited); err != nil { ++ return err ++ } ++ t.Exited = exited != 0 ++ if err := binary.Read(in, binary.BigEndian, &t.FutexAddr); err != nil { ++ return err ++ } ++ if err := binary.Read(in, binary.BigEndian, &t.FutexVal); err != nil { ++ return err ++ } ++ if err := binary.Read(in, binary.BigEndian, &t.FutexTimeoutStep); err != nil { ++ return err ++ } ++ if err := binary.Read(in, binary.BigEndian, &t.Cpu.PC); err != nil { ++ return err ++ } ++ if err := binary.Read(in, binary.BigEndian, &t.Cpu.NextPC); err != nil { ++ return err ++ } ++ if err := binary.Read(in, binary.BigEndian, &t.Cpu.LO); err != nil { ++ return err ++ } ++ if err := binary.Read(in, binary.BigEndian, &t.Cpu.HI); err != nil { ++ return err ++ } ++ // Read the registers as big endian uint32s ++ for i := range t.Registers { ++ if err := binary.Read(in, binary.BigEndian, &t.Registers[i]); err != nil { ++ return err ++ } ++ } ++ return nil + } +  + func computeThreadRoot(prevStackRoot common.Hash, threadToPush *ThreadState) common.Hash {
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+5
+
-3
+ +
+ +
+
+
diff --git OP/cannon/mipsevm/program/metadata.go CELO/cannon/mipsevm/program/metadata.go +index e90cbe14815c433d90eb1913b8630e73f8ef9da6..fb34da7694c7830d38e8876b24e347197aab1007 100644 +--- OP/cannon/mipsevm/program/metadata.go ++++ CELO/cannon/mipsevm/program/metadata.go +@@ -4,6 +4,8 @@ import ( + "debug/elf" + "fmt" + "sort" ++ ++ "github.com/ethereum-optimism/optimism/cannon/mipsevm" + ) +  + type Symbol struct { +@@ -15,6 +17,8 @@ + type Metadata struct { + Symbols []Symbol `json:"symbols"` + } ++ ++var _ mipsevm.Metadata = (*Metadata)(nil) +  + func MakeMetadata(elfProgram *elf.File) (*Metadata, error) { + syms, err := elfProgram.Symbols() +@@ -50,9 +54,7 @@ } + return out.Name + } +  +-type SymbolMatcher func(addr uint32) bool +- +-func (m *Metadata) CreateSymbolMatcher(name string) SymbolMatcher { ++func (m *Metadata) CreateSymbolMatcher(name string) mipsevm.SymbolMatcher { + for _, s := range m.Symbols { + if s.Name == name { + start := s.Start
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+6
+
-4
+ +
+ +
+
+
diff --git OP/cannon/mipsevm/program/patch.go CELO/cannon/mipsevm/program/patch.go +index 46b75a69ff1c34c05066f2694a80a0128a65365e..e8e2e3ebc0855c1494a28cd5a3ca45c1f9d4b374 100644 +--- OP/cannon/mipsevm/program/patch.go ++++ CELO/cannon/mipsevm/program/patch.go +@@ -4,15 +4,16 @@ import ( + "bytes" + "debug/elf" + "encoding/binary" ++ "errors" + "fmt" +  + "github.com/ethereum-optimism/optimism/cannon/mipsevm" + "github.com/ethereum-optimism/optimism/cannon/mipsevm/memory" + ) +  +-// TODO(cp-903) Consider breaking up go patching into performance and threading-related patches so we can +-// selectively apply the perf patching to MTCannon +-func PatchGo(f *elf.File, st mipsevm.FPVMState) error { ++// PatchGoGC patches out garbage-collection-related symbols to disable garbage collection ++// and improves performance by patching out floating-point-related symbols ++func PatchGoGC(f *elf.File, st mipsevm.FPVMState) error { + symbols, err := f.Symbols() + if err != nil { + return fmt.Errorf("failed to read symbols data, cannot patch program: %w", err) +@@ -52,12 +53,13 @@ } + return nil + } +  ++// PatchStack sets up the program's initial stack frame and stack pointer + func PatchStack(st mipsevm.FPVMState) error { + // setup stack pointer + sp := uint32(0x7f_ff_d0_00) + // allocate 1 page for the initial stack data, and 16KB = 4 pages for the stack to grow + if err := st.GetMemory().SetMemoryRange(sp-4*memory.PageSize, bytes.NewReader(make([]byte, 5*memory.PageSize))); err != nil { +- return fmt.Errorf("failed to allocate page for stack content") ++ return errors.New("failed to allocate page for stack content") + } + st.GetRegistersRef()[29] = sp +
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+5
+
-16
+ +
+ +
+
+
diff --git OP/cannon/mipsevm/singlethreaded/instrumented.go CELO/cannon/mipsevm/singlethreaded/instrumented.go +index 89331f31dcae12d84027934c7d3b11d90af84c71..800cc1a92f7a7167b20a07267ad505824bd84a6c 100644 +--- OP/cannon/mipsevm/singlethreaded/instrumented.go ++++ CELO/cannon/mipsevm/singlethreaded/instrumented.go +@@ -5,14 +5,12 @@ "io" +  + "github.com/ethereum-optimism/optimism/cannon/mipsevm" + "github.com/ethereum-optimism/optimism/cannon/mipsevm/exec" +- "github.com/ethereum-optimism/optimism/cannon/mipsevm/program" +- "github.com/ethereum-optimism/optimism/op-service/jsonutil" + "github.com/ethereum/go-ethereum/common/hexutil" + ) +  + type InstrumentedState struct { +- meta *program.Metadata +- sleepCheck program.SymbolMatcher ++ meta mipsevm.Metadata ++ sleepCheck mipsevm.SymbolMatcher +  + state *State +  +@@ -27,16 +25,14 @@ } +  + var _ mipsevm.FPVM = (*InstrumentedState)(nil) +  +-func NewInstrumentedState(state *State, po mipsevm.PreimageOracle, stdOut, stdErr io.Writer, meta *program.Metadata) *InstrumentedState { +- var sleepCheck program.SymbolMatcher ++func NewInstrumentedState(state *State, po mipsevm.PreimageOracle, stdOut, stdErr io.Writer, meta mipsevm.Metadata) *InstrumentedState { ++ var sleepCheck mipsevm.SymbolMatcher + if meta == nil { + sleepCheck = func(addr uint32) bool { return false } + } else { + sleepCheck = meta.CreateSymbolMatcher("runtime.notesleep") + } +- + return &InstrumentedState{ +- meta: meta, + sleepCheck: sleepCheck, + state: state, + stdOut: stdOut, +@@ -44,15 +40,8 @@ stdErr: stdErr, + memoryTracker: exec.NewMemoryTracker(state.Memory), + stackTracker: &exec.NoopStackTracker{}, + preimageOracle: exec.NewTrackingPreimageOracleReader(po), +- } +-} +- +-func NewInstrumentedStateFromFile(stateFile string, po mipsevm.PreimageOracle, stdOut, stdErr io.Writer, meta *program.Metadata) (*InstrumentedState, error) { +- state, err := jsonutil.LoadJSON[State](stateFile) +- if err != nil { +- return nil, err ++ meta: meta, + } +- return NewInstrumentedState(state, po, stdOut, stdErr, meta), nil + } +  + func (m *InstrumentedState) InitDebug() error {
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+35
+
-2
+ +
+ +
+
+
diff --git OP/cannon/mipsevm/singlethreaded/mips.go CELO/cannon/mipsevm/singlethreaded/mips.go +index 48a25e084291b5ef7860c767c297706ec6b9d2e7..a88d0c66b0e61746b13813615d9f81725e687fae 100644 +--- OP/cannon/mipsevm/singlethreaded/mips.go ++++ CELO/cannon/mipsevm/singlethreaded/mips.go +@@ -1,6 +1,8 @@ + package singlethreaded +  + import ( ++ "fmt" ++ + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" +  +@@ -30,7 +32,7 @@ m.state.ExitCode = uint8(a0) + return nil + case exec.SysRead: + var newPreimageOffset uint32 +- v0, v1, newPreimageOffset = exec.HandleSysRead(a0, a1, a2, m.state.PreimageKey, m.state.PreimageOffset, m.preimageOracle, m.state.Memory, m.memoryTracker) ++ v0, v1, newPreimageOffset, _, _ = exec.HandleSysRead(a0, a1, a2, m.state.PreimageKey, m.state.PreimageOffset, m.preimageOracle, m.state.Memory, m.memoryTracker) + m.state.PreimageOffset = newPreimageOffset + case exec.SysWrite: + var newLastHint hexutil.Bytes +@@ -62,6 +64,37 @@ if opcode == 0 && fun == 0xC { + return m.handleSyscall() + } +  ++ // Handle RMW (read-modify-write) ops ++ if opcode == exec.OpLoadLinked || opcode == exec.OpStoreConditional { ++ return m.handleRMWOps(insn, opcode) ++ } ++ + // Exec the rest of the step logic +- return exec.ExecMipsCoreStepLogic(&m.state.Cpu, &m.state.Registers, m.state.Memory, insn, opcode, fun, m.memoryTracker, m.stackTracker) ++ _, _, err := exec.ExecMipsCoreStepLogic(&m.state.Cpu, &m.state.Registers, m.state.Memory, insn, opcode, fun, m.memoryTracker, m.stackTracker) ++ return err ++} ++ ++// handleRMWOps handles LL and SC operations which provide the primitives to implement read-modify-write operations ++func (m *InstrumentedState) handleRMWOps(insn, opcode uint32) error { ++ baseReg := (insn >> 21) & 0x1F ++ base := m.state.Registers[baseReg] ++ rtReg := (insn >> 16) & 0x1F ++ offset := exec.SignExtendImmediate(insn) ++ ++ effAddr := (base + offset) & 0xFFFFFFFC ++ m.memoryTracker.TrackMemAccess(effAddr) ++ mem := m.state.Memory.GetMemory(effAddr) ++ ++ var retVal uint32 ++ if opcode == exec.OpLoadLinked { ++ retVal = mem ++ } else if opcode == exec.OpStoreConditional { ++ rt := m.state.Registers[rtReg] ++ m.state.Memory.SetMemory(effAddr, rt) ++ retVal = 1 // 1 for success ++ } else { ++ panic(fmt.Sprintf("Invalid instruction passed to handleRMWOps (opcode %08x)", opcode)) ++ } ++ ++ return exec.HandleRd(&m.state.Cpu, &m.state.Registers, rtReg, retVal, true) + }
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+121
+
-0
+ +
+ +
+
+
diff --git OP/cannon/mipsevm/singlethreaded/state.go CELO/cannon/mipsevm/singlethreaded/state.go +index 638dcf6f3b6b3b168bcfeda2b9bd0c6f7c20ee1d..e0be88d9985743036b827ec764278358655a545b 100644 +--- OP/cannon/mipsevm/singlethreaded/state.go ++++ CELO/cannon/mipsevm/singlethreaded/state.go +@@ -4,10 +4,13 @@ import ( + "encoding/binary" + "encoding/json" + "fmt" ++ "io" +  ++ "github.com/ethereum-optimism/optimism/cannon/serialize" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/crypto" ++ "github.com/ethereum/go-ethereum/log" +  + "github.com/ethereum-optimism/optimism/cannon/mipsevm" + "github.com/ethereum-optimism/optimism/cannon/mipsevm/memory" +@@ -63,6 +66,11 @@ state.Cpu.NextPC = pc + 4 + state.Heap = heapStart +  + return state ++} ++ ++func (s *State) CreateVM(logger log.Logger, po mipsevm.PreimageOracle, stdOut, stdErr io.Writer, meta mipsevm.Metadata) mipsevm.FPVM { ++ logger.Info("Using cannon VM") ++ return NewInstrumentedState(s, po, stdOut, stdErr, meta) + } +  + type stateMarshaling struct { +@@ -175,6 +183,119 @@ for _, r := range s.Registers { + out = binary.BigEndian.AppendUint32(out, r) + } + return out, stateHashFromWitness(out) ++} ++ ++// Serialize writes the state in a simple binary format which can be read again using Deserialize ++// The format is a simple concatenation of fields, with prefixed item count for repeating items and using big endian ++// encoding for numbers. ++// ++// StateVersion uint8(0) ++// Memory As per Memory.Serialize ++// PreimageKey [32]byte ++// PreimageOffset uint32 ++// Cpu.PC uint32 ++// Cpu.NextPC uint32 ++// Cpu.LO uint32 ++// Cpu.HI uint32 ++// Heap uint32 ++// ExitCode uint8 ++// Exited uint8 - 0 for false, 1 for true ++// Step uint64 ++// Registers [32]uint32 ++// len(LastHint) uint32 (0 when LastHint is nil) ++// LastHint []byte ++func (s *State) Serialize(out io.Writer) error { ++ bout := serialize.NewBinaryWriter(out) ++ ++ if err := s.Memory.Serialize(out); err != nil { ++ return err ++ } ++ if err := bout.WriteHash(s.PreimageKey); err != nil { ++ return err ++ } ++ if err := bout.WriteUInt(s.PreimageOffset); err != nil { ++ return err ++ } ++ if err := bout.WriteUInt(s.Cpu.PC); err != nil { ++ return err ++ } ++ if err := bout.WriteUInt(s.Cpu.NextPC); err != nil { ++ return err ++ } ++ if err := bout.WriteUInt(s.Cpu.LO); err != nil { ++ return err ++ } ++ if err := bout.WriteUInt(s.Cpu.HI); err != nil { ++ return err ++ } ++ if err := bout.WriteUInt(s.Heap); err != nil { ++ return err ++ } ++ if err := bout.WriteUInt(s.ExitCode); err != nil { ++ return err ++ } ++ if err := bout.WriteBool(s.Exited); err != nil { ++ return err ++ } ++ if err := bout.WriteUInt(s.Step); err != nil { ++ return err ++ } ++ for _, r := range s.Registers { ++ if err := bout.WriteUInt(r); err != nil { ++ return err ++ } ++ } ++ if err := bout.WriteBytes(s.LastHint); err != nil { ++ return err ++ } ++ return nil ++} ++ ++func (s *State) Deserialize(in io.Reader) error { ++ bin := serialize.NewBinaryReader(in) ++ s.Memory = memory.NewMemory() ++ if err := s.Memory.Deserialize(in); err != nil { ++ return err ++ } ++ if err := bin.ReadHash(&s.PreimageKey); err != nil { ++ return err ++ } ++ if err := bin.ReadUInt(&s.PreimageOffset); err != nil { ++ return err ++ } ++ if err := bin.ReadUInt(&s.Cpu.PC); err != nil { ++ return err ++ } ++ if err := bin.ReadUInt(&s.Cpu.NextPC); err != nil { ++ return err ++ } ++ if err := bin.ReadUInt(&s.Cpu.LO); err != nil { ++ return err ++ } ++ if err := bin.ReadUInt(&s.Cpu.HI); err != nil { ++ return err ++ } ++ if err := bin.ReadUInt(&s.Heap); err != nil { ++ return err ++ } ++ if err := bin.ReadUInt(&s.ExitCode); err != nil { ++ return err ++ } ++ if err := bin.ReadBool(&s.Exited); err != nil { ++ return err ++ } ++ if err := bin.ReadUInt(&s.Step); err != nil { ++ return err ++ } ++ for i := range s.Registers { ++ if err := bin.ReadUInt(&s.Registers[i]); err != nil { ++ return err ++ } ++ } ++ if err := bin.ReadBytes((*[]byte)(&s.LastHint)); err != nil { ++ return err ++ } ++ return nil + } +  + type StateWitness []byte
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+69
+
-0
+ +
+ +
+
+
diff --git OP/cannon/mipsevm/singlethreaded/state_test.go CELO/cannon/mipsevm/singlethreaded/state_test.go +index 27588f8b67edd57490418ae48a49f20a48eea8a1..c3dfd5cd41af6885223994efbe3bc75772bca0d4 100644 +--- OP/cannon/mipsevm/singlethreaded/state_test.go ++++ CELO/cannon/mipsevm/singlethreaded/state_test.go +@@ -1,9 +1,12 @@ + package singlethreaded +  + import ( ++ "bytes" + "debug/elf" + "testing" +  ++ "github.com/ethereum/go-ethereum/common" ++ "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/crypto" + "github.com/stretchr/testify/require" +  +@@ -79,3 +82,69 @@ require.Equal(t, state.Memory.MerkleRoot(), newState.Memory.MerkleRoot()) + require.Equal(t, state.Registers, newState.Registers) + require.Equal(t, state.Step, newState.Step) + } ++ ++func TestStateBinaryCodec(t *testing.T) { ++ elfProgram, err := elf.Open("../../testdata/example/bin/hello.elf") ++ require.NoError(t, err, "open ELF file") ++ state, err := program.LoadELF(elfProgram, CreateInitialState) ++ require.NoError(t, err, "load ELF into state") ++ ++ buf := new(bytes.Buffer) ++ err = state.Serialize(buf) ++ require.NoError(t, err) ++ ++ newState := new(State) ++ require.NoError(t, newState.Deserialize(bytes.NewReader(buf.Bytes()))) ++ ++ require.Equal(t, state.PreimageKey, newState.PreimageKey) ++ require.Equal(t, state.PreimageOffset, newState.PreimageOffset) ++ require.Equal(t, state.Cpu, newState.Cpu) ++ require.Equal(t, state.Heap, newState.Heap) ++ require.Equal(t, state.ExitCode, newState.ExitCode) ++ require.Equal(t, state.Exited, newState.Exited) ++ require.Equal(t, state.Memory.PageCount(), newState.Memory.PageCount()) ++ require.Equal(t, state.Memory.MerkleRoot(), newState.Memory.MerkleRoot()) ++ require.Equal(t, state.Registers, newState.Registers) ++ require.Equal(t, state.Step, newState.Step) ++} ++ ++func TestSerializeStateRoundTrip(t *testing.T) { ++ // Construct a test case with populated fields ++ mem := memory.NewMemory() ++ mem.AllocPage(5) ++ p := mem.AllocPage(123) ++ p.Data[2] = 0x01 ++ state := &State{ ++ Memory: mem, ++ PreimageKey: common.Hash{0xFF}, ++ PreimageOffset: 5, ++ Cpu: mipsevm.CpuScalars{ ++ PC: 0xFF, ++ NextPC: 0xFF + 4, ++ LO: 0xbeef, ++ HI: 0xbabe, ++ }, ++ Heap: 0xc0ffee, ++ ExitCode: 1, ++ Exited: true, ++ Step: 0xdeadbeef, ++ Registers: [32]uint32{ ++ 0xdeadbeef, ++ 0xdeadbeef, ++ 0xc0ffee, ++ 0xbeefbabe, ++ 0xdeadc0de, ++ 0xbadc0de, ++ 0xdeaddead, ++ }, ++ LastHint: hexutil.Bytes{1, 2, 3, 4, 5}, ++ } ++ ++ ser := new(bytes.Buffer) ++ err := state.Serialize(ser) ++ require.NoError(t, err, "must serialize state") ++ state2 := &State{} ++ err = state2.Deserialize(ser) ++ require.NoError(t, err, "must deserialize state") ++ require.Equal(t, state, state2, "must roundtrip state") ++}
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+6
+
-8
+ +
+ +
+
+
diff --git OP/cannon/mipsevm/singlethreaded/testutil/state.go CELO/cannon/mipsevm/singlethreaded/testutil/state.go +index f09b56175af90776068e0aaf64e743a88df9ac03..079827500e45a390014a382f94d77f9911fb0efd 100644 +--- OP/cannon/mipsevm/singlethreaded/testutil/state.go ++++ CELO/cannon/mipsevm/singlethreaded/testutil/state.go +@@ -1,8 +1,6 @@ + package testutil +  + import ( +- "math/rand" +- + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" +  +@@ -15,12 +13,12 @@ state *singlethreaded.State + } +  + func (m *StateMutatorSingleThreaded) Randomize(randSeed int64) { +- r := rand.New(rand.NewSource(randSeed)) ++ r := testutil.NewRandHelper(randSeed) +  +- pc := testutil.RandPC(r) +- step := testutil.RandStep(r) ++ pc := r.RandPC() ++ step := r.RandStep() +  +- m.state.PreimageKey = testutil.RandHash(r) ++ m.state.PreimageKey = r.RandHash() + m.state.PreimageOffset = r.Uint32() + m.state.Cpu.PC = pc + m.state.Cpu.NextPC = pc + 4 +@@ -28,8 +26,8 @@ m.state.Cpu.HI = r.Uint32() + m.state.Cpu.LO = r.Uint32() + m.state.Heap = r.Uint32() + m.state.Step = step +- m.state.LastHint = testutil.RandHint(r) +- m.state.Registers = *testutil.RandRegisters(r) ++ m.state.LastHint = r.RandHint() ++ m.state.Registers = *r.RandRegisters() + } +  + var _ testutil.StateMutator = (*StateMutatorSingleThreaded)(nil)
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+66
+
-3
+ +
+ +
+
+
diff --git OP/cannon/mipsevm/tests/evm_common_test.go CELO/cannon/mipsevm/tests/evm_common_test.go +index 437501140f257799e9511a18c75f8ae6e0de0abf..21aea97a7a14dd221cb051461d3dc29592d58797 100644 +--- OP/cannon/mipsevm/tests/evm_common_test.go ++++ CELO/cannon/mipsevm/tests/evm_common_test.go +@@ -115,7 +115,7 @@ } + } + } +  +-func TestEVMSingleStep(t *testing.T) { ++func TestEVMSingleStep_Jump(t *testing.T) { + var tracer *tracing.Hooks +  + versions := GetMipsVersionTestCases(t) +@@ -149,6 +149,69 @@ expected.PC = state.GetCpu().NextPC + expected.NextPC = tt.expectNextPC + if tt.expectLink { + expected.Registers[31] = state.GetPC() + 8 ++ } ++ ++ stepWitness, err := goVm.Step(true) ++ require.NoError(t, err) ++ ++ // Check expectations ++ expected.Validate(t, state) ++ testutil.ValidateEVM(t, stepWitness, step, goVm, v.StateHashFn, v.Contracts, tracer) ++ }) ++ } ++ } ++} ++ ++func TestEVMSingleStep_Add(t *testing.T) { ++ var tracer *tracing.Hooks ++ ++ versions := GetMipsVersionTestCases(t) ++ cases := []struct { ++ name string ++ insn uint32 ++ ifImm bool ++ rs uint32 ++ rt uint32 ++ imm uint16 ++ expectRD uint32 ++ expectImm uint32 ++ }{ ++ {name: "add", insn: 0x02_32_40_20, ifImm: false, rs: uint32(12), rt: uint32(20), expectRD: uint32(32)}, // add t0, s1, s2 ++ {name: "addu", insn: 0x02_32_40_21, ifImm: false, rs: uint32(12), rt: uint32(20), expectRD: uint32(32)}, // addu t0, s1, s2 ++ {name: "addi", insn: 0x22_28_00_28, ifImm: true, rs: uint32(4), rt: uint32(1), imm: uint16(40), expectImm: uint32(44)}, // addi t0, s1, 40 ++ {name: "addi sign", insn: 0x22_28_ff_fe, ifImm: true, rs: uint32(2), rt: uint32(1), imm: uint16(0xfffe), expectImm: uint32(0)}, // addi t0, s1, -2 ++ {name: "addiu", insn: 0x26_28_00_28, ifImm: true, rs: uint32(4), rt: uint32(1), imm: uint16(40), expectImm: uint32(44)}, // addiu t0, s1, 40 ++ } ++ ++ for _, v := range versions { ++ for i, tt := range cases { ++ testName := fmt.Sprintf("%v (%v)", tt.name, v.Name) ++ t.Run(testName, func(t *testing.T) { ++ goVm := v.VMFactory(nil, os.Stdout, os.Stderr, testutil.CreateLogger(), testutil.WithRandomization(int64(i)), testutil.WithPC(0), testutil.WithNextPC(4)) ++ state := goVm.GetState() ++ if tt.ifImm { ++ state.GetRegistersRef()[8] = tt.rt ++ state.GetRegistersRef()[17] = tt.rs ++ } else { ++ state.GetRegistersRef()[17] = tt.rs ++ state.GetRegistersRef()[18] = tt.rt ++ } ++ state.GetMemory().SetMemory(0, tt.insn) ++ step := state.GetStep() ++ ++ // Setup expectations ++ expected := testutil.NewExpectedState(state) ++ expected.Step += 1 ++ expected.PC = 4 ++ expected.NextPC = 8 ++ ++ if tt.ifImm { ++ expected.Registers[8] = tt.expectImm ++ expected.Registers[17] = tt.rs ++ } else { ++ expected.Registers[8] = tt.expectRD ++ expected.Registers[17] = tt.rs ++ expected.Registers[18] = tt.rt + } +  + stepWitness, err := goVm.Step(true) +@@ -488,8 +551,8 @@ evmPost := evm.Step(t, stepWitness, step, v.StateHashFn) + // verify the post-state matches. + // TODO: maybe more readable to decode the evmPost state, and do attribute-wise comparison. + goPost, _ := goVm.GetState().EncodeWitness() +- require.Equal(t, hexutil.Bytes(goPost).String(), hexutil.Bytes(evmPost).String(), +- "mipsevm produced different state than EVM") ++ require.Equalf(t, hexutil.Bytes(goPost).String(), hexutil.Bytes(evmPost).String(), ++ "mipsevm produced different state than EVM. insn: %x", insn) + } + end := time.Now() + delta := end.Sub(start)
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+602
+
-56
+ +
+ +
+
+
diff --git OP/cannon/mipsevm/tests/evm_multithreaded_test.go CELO/cannon/mipsevm/tests/evm_multithreaded_test.go +index 76f9b9462dc2f87264282a63aa5ba7c6b4e6e071..a26ebe96eb3728abb2fe1325cbf668cb6c5b5eea 100644 +--- OP/cannon/mipsevm/tests/evm_multithreaded_test.go ++++ CELO/cannon/mipsevm/tests/evm_multithreaded_test.go +@@ -1,6 +1,7 @@ + package tests +  + import ( ++ "encoding/binary" + "fmt" + "os" + "slices" +@@ -8,6 +9,7 @@ "testing" +  + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core/tracing" ++ "github.com/ethereum/go-ethereum/crypto" + "github.com/stretchr/testify/require" + "golang.org/x/exp/maps" +  +@@ -16,8 +18,375 @@ "github.com/ethereum-optimism/optimism/cannon/mipsevm/exec" + "github.com/ethereum-optimism/optimism/cannon/mipsevm/multithreaded" + mttestutil "github.com/ethereum-optimism/optimism/cannon/mipsevm/multithreaded/testutil" + "github.com/ethereum-optimism/optimism/cannon/mipsevm/testutil" ++ preimage "github.com/ethereum-optimism/optimism/op-preimage" + ) +  ++func TestEVM_MT_LL(t *testing.T) { ++ var tracer *tracing.Hooks ++ ++ cases := []struct { ++ name string ++ base uint32 ++ offset int ++ value uint32 ++ effAddr uint32 ++ rtReg int ++ }{ ++ {name: "Aligned effAddr", base: 0x00_00_00_01, offset: 0x0133, value: 0xABCD, effAddr: 0x00_00_01_34, rtReg: 5}, ++ {name: "Aligned effAddr, signed extended", base: 0x00_00_00_01, offset: 0xFF33, value: 0xABCD, effAddr: 0xFF_FF_FF_34, rtReg: 5}, ++ {name: "Unaligned effAddr", base: 0xFF_12_00_01, offset: 0x3401, value: 0xABCD, effAddr: 0xFF_12_34_00, rtReg: 5}, ++ {name: "Unaligned effAddr, sign extended w overflow", base: 0xFF_12_00_01, offset: 0x8401, value: 0xABCD, effAddr: 0xFF_11_84_00, rtReg: 5}, ++ {name: "Return register set to 0", base: 0xFF_12_00_01, offset: 0x8401, value: 0xABCD, effAddr: 0xFF_11_84_00, rtReg: 0}, ++ } ++ for i, c := range cases { ++ for _, withExistingReservation := range []bool{true, false} { ++ tName := fmt.Sprintf("%v (withExistingReservation = %v)", c.name, withExistingReservation) ++ t.Run(tName, func(t *testing.T) { ++ rtReg := c.rtReg ++ baseReg := 6 ++ pc := uint32(0x44) ++ insn := uint32((0b11_0000 << 26) | (baseReg & 0x1F << 21) | (rtReg & 0x1F << 16) | (0xFFFF & c.offset)) ++ goVm, state, contracts := setup(t, i, nil) ++ step := state.GetStep() ++ ++ // Set up state ++ state.GetCurrentThread().Cpu.PC = pc ++ state.GetCurrentThread().Cpu.NextPC = pc + 4 ++ state.GetMemory().SetMemory(pc, insn) ++ state.GetMemory().SetMemory(c.effAddr, c.value) ++ state.GetRegistersRef()[baseReg] = c.base ++ if withExistingReservation { ++ state.LLReservationActive = true ++ state.LLAddress = c.effAddr + uint32(4) ++ state.LLOwnerThread = 123 ++ } else { ++ state.LLReservationActive = false ++ state.LLAddress = 0 ++ state.LLOwnerThread = 0 ++ } ++ ++ // Set up expectations ++ expected := mttestutil.NewExpectedMTState(state) ++ expected.ExpectStep() ++ expected.LLReservationActive = true ++ expected.LLAddress = c.effAddr ++ expected.LLOwnerThread = state.GetCurrentThread().ThreadId ++ if rtReg != 0 { ++ expected.ActiveThread().Registers[rtReg] = c.value ++ } ++ ++ stepWitness, err := goVm.Step(true) ++ require.NoError(t, err) ++ ++ // Check expectations ++ expected.Validate(t, state) ++ testutil.ValidateEVM(t, stepWitness, step, goVm, multithreaded.GetStateHashFn(), contracts, tracer) ++ }) ++ } ++ } ++} ++ ++func TestEVM_MT_SC(t *testing.T) { ++ var tracer *tracing.Hooks ++ ++ llVariations := []struct { ++ name string ++ llReservationActive bool ++ matchThreadId bool ++ matchEffAddr bool ++ shouldSucceed bool ++ }{ ++ {name: "should succeed", llReservationActive: true, matchThreadId: true, matchEffAddr: true, shouldSucceed: true}, ++ {name: "mismatch addr", llReservationActive: true, matchThreadId: false, matchEffAddr: true, shouldSucceed: false}, ++ {name: "mismatched thread", llReservationActive: true, matchThreadId: true, matchEffAddr: false, shouldSucceed: false}, ++ {name: "mismatched addr & thread", llReservationActive: true, matchThreadId: false, matchEffAddr: false, shouldSucceed: false}, ++ {name: "no active reservation", llReservationActive: false, matchThreadId: true, matchEffAddr: true, shouldSucceed: false}, ++ } ++ ++ cases := []struct { ++ name string ++ base uint32 ++ offset int ++ value uint32 ++ effAddr uint32 ++ rtReg int ++ threadId uint32 ++ }{ ++ {name: "Aligned effAddr", base: 0x00_00_00_01, offset: 0x0133, value: 0xABCD, effAddr: 0x00_00_01_34, rtReg: 5, threadId: 4}, ++ {name: "Aligned effAddr, signed extended", base: 0x00_00_00_01, offset: 0xFF33, value: 0xABCD, effAddr: 0xFF_FF_FF_34, rtReg: 5, threadId: 4}, ++ {name: "Unaligned effAddr", base: 0xFF_12_00_01, offset: 0x3401, value: 0xABCD, effAddr: 0xFF_12_34_00, rtReg: 5, threadId: 4}, ++ {name: "Unaligned effAddr, sign extended w overflow", base: 0xFF_12_00_01, offset: 0x8401, value: 0xABCD, effAddr: 0xFF_11_84_00, rtReg: 5, threadId: 4}, ++ {name: "Return register set to 0", base: 0xFF_12_00_01, offset: 0x8401, value: 0xABCD, effAddr: 0xFF_11_84_00, rtReg: 0, threadId: 4}, ++ {name: "Zero valued ll args", base: 0x00_00_00_00, offset: 0x0, value: 0xABCD, effAddr: 0x00_00_00_00, rtReg: 5, threadId: 0}, ++ } ++ for i, c := range cases { ++ for _, v := range llVariations { ++ tName := fmt.Sprintf("%v (%v)", c.name, v.name) ++ t.Run(tName, func(t *testing.T) { ++ rtReg := c.rtReg ++ baseReg := 6 ++ pc := uint32(0x44) ++ insn := uint32((0b11_1000 << 26) | (baseReg & 0x1F << 21) | (rtReg & 0x1F << 16) | (0xFFFF & c.offset)) ++ goVm, state, contracts := setup(t, i, nil) ++ mttestutil.InitializeSingleThread(i*23456, state, i%2 == 1) ++ step := state.GetStep() ++ ++ // Define LL-related params ++ var llAddress, llOwnerThread uint32 ++ if v.matchEffAddr { ++ llAddress = c.effAddr ++ } else { ++ llAddress = c.effAddr + 4 ++ } ++ if v.matchThreadId { ++ llOwnerThread = c.threadId ++ } else { ++ llOwnerThread = c.threadId + 1 ++ } ++ ++ // Setup state ++ state.GetCurrentThread().ThreadId = c.threadId ++ state.GetCurrentThread().Cpu.PC = pc ++ state.GetCurrentThread().Cpu.NextPC = pc + 4 ++ state.GetMemory().SetMemory(pc, insn) ++ state.GetRegistersRef()[baseReg] = c.base ++ state.GetRegistersRef()[rtReg] = c.value ++ state.LLReservationActive = v.llReservationActive ++ state.LLAddress = llAddress ++ state.LLOwnerThread = llOwnerThread ++ ++ // Setup expectations ++ expected := mttestutil.NewExpectedMTState(state) ++ expected.ExpectStep() ++ var retVal uint32 ++ if v.shouldSucceed { ++ retVal = 1 ++ expected.ExpectMemoryWrite(c.effAddr, c.value) ++ expected.LLReservationActive = false ++ expected.LLAddress = 0 ++ expected.LLOwnerThread = 0 ++ } else { ++ retVal = 0 ++ } ++ if rtReg != 0 { ++ expected.ActiveThread().Registers[rtReg] = retVal ++ } ++ ++ stepWitness, err := goVm.Step(true) ++ require.NoError(t, err) ++ ++ // Check expectations ++ expected.Validate(t, state) ++ testutil.ValidateEVM(t, stepWitness, step, goVm, multithreaded.GetStateHashFn(), contracts, tracer) ++ }) ++ } ++ } ++} ++ ++func TestEVM_MT_SysRead_Preimage(t *testing.T) { ++ var tracer *tracing.Hooks ++ ++ preimageValue := make([]byte, 0, 8) ++ preimageValue = binary.BigEndian.AppendUint32(preimageValue, 0x12_34_56_78) ++ preimageValue = binary.BigEndian.AppendUint32(preimageValue, 0x98_76_54_32) ++ ++ llVariations := []struct { ++ name string ++ llReservationActive bool ++ matchThreadId bool ++ matchEffAddr bool ++ shouldClearReservation bool ++ }{ ++ {name: "matching reservation", llReservationActive: true, matchThreadId: true, matchEffAddr: true, shouldClearReservation: true}, ++ {name: "matching reservation, diff thread", llReservationActive: true, matchThreadId: false, matchEffAddr: true, shouldClearReservation: true}, ++ {name: "mismatched reservation", llReservationActive: true, matchThreadId: true, matchEffAddr: false, shouldClearReservation: false}, ++ {name: "mismatched reservation", llReservationActive: true, matchThreadId: false, matchEffAddr: false, shouldClearReservation: false}, ++ {name: "no reservation, matching addr", llReservationActive: false, matchThreadId: true, matchEffAddr: true, shouldClearReservation: true}, ++ {name: "no reservation, mismatched addr", llReservationActive: false, matchThreadId: true, matchEffAddr: false, shouldClearReservation: false}, ++ } ++ ++ cases := []struct { ++ name string ++ addr uint32 ++ count uint32 ++ writeLen uint32 ++ preimageOffset uint32 ++ prestateMem uint32 ++ postateMem uint32 ++ shouldPanic bool ++ }{ ++ {name: "Aligned addr, write 1 byte", addr: 0x00_00_FF_00, count: 1, writeLen: 1, preimageOffset: 8, prestateMem: 0xFF_FF_FF_FF, postateMem: 0x12_FF_FF_FF}, ++ {name: "Aligned addr, write 2 byte", addr: 0x00_00_FF_00, count: 2, writeLen: 2, preimageOffset: 8, prestateMem: 0xFF_FF_FF_FF, postateMem: 0x12_34_FF_FF}, ++ {name: "Aligned addr, write 3 byte", addr: 0x00_00_FF_00, count: 3, writeLen: 3, preimageOffset: 8, prestateMem: 0xFF_FF_FF_FF, postateMem: 0x12_34_56_FF}, ++ {name: "Aligned addr, write 4 byte", addr: 0x00_00_FF_00, count: 4, writeLen: 4, preimageOffset: 8, prestateMem: 0xFF_FF_FF_FF, postateMem: 0x12_34_56_78}, ++ {name: "1-byte misaligned addr, write 1 byte", addr: 0x00_00_FF_01, count: 1, writeLen: 1, preimageOffset: 8, prestateMem: 0xFF_FF_FF_FF, postateMem: 0xFF_12_FF_FF}, ++ {name: "1-byte misaligned addr, write 2 byte", addr: 0x00_00_FF_01, count: 2, writeLen: 2, preimageOffset: 9, prestateMem: 0xFF_FF_FF_FF, postateMem: 0xFF_34_56_FF}, ++ {name: "1-byte misaligned addr, write 3 byte", addr: 0x00_00_FF_01, count: 3, writeLen: 3, preimageOffset: 8, prestateMem: 0xFF_FF_FF_FF, postateMem: 0xFF_12_34_56}, ++ {name: "2-byte misaligned addr, write 1 byte", addr: 0x00_00_FF_02, count: 1, writeLen: 1, preimageOffset: 8, prestateMem: 0xFF_FF_FF_FF, postateMem: 0xFF_FF_12_FF}, ++ {name: "2-byte misaligned addr, write 2 byte", addr: 0x00_00_FF_02, count: 2, writeLen: 2, preimageOffset: 12, prestateMem: 0xFF_FF_FF_FF, postateMem: 0xFF_FF_98_76}, ++ {name: "3-byte misaligned addr, write 1 byte", addr: 0x00_00_FF_03, count: 1, writeLen: 1, preimageOffset: 8, prestateMem: 0xFF_FF_FF_FF, postateMem: 0xFF_FF_FF_12}, ++ {name: "Count of 0", addr: 0x00_00_FF_03, count: 0, writeLen: 0, preimageOffset: 8, prestateMem: 0xFF_FF_FF_FF, postateMem: 0xFF_FF_FF_FF}, ++ {name: "Count greater than 4", addr: 0x00_00_FF_00, count: 15, writeLen: 4, preimageOffset: 8, prestateMem: 0xFF_FF_FF_FF, postateMem: 0x12_34_56_78}, ++ {name: "Count greater than 4, unaligned", addr: 0x00_00_FF_01, count: 15, writeLen: 3, preimageOffset: 8, prestateMem: 0xFF_FF_FF_FF, postateMem: 0xFF_12_34_56}, ++ {name: "Offset at last byte", addr: 0x00_00_FF_00, count: 4, writeLen: 1, preimageOffset: 15, prestateMem: 0xFF_FF_FF_FF, postateMem: 0x32_FF_FF_FF}, ++ {name: "Offset just out of bounds", addr: 0x00_00_FF_00, count: 4, writeLen: 0, preimageOffset: 16, prestateMem: 0xFF_FF_FF_FF, postateMem: 0xFF_FF_FF_FF, shouldPanic: true}, ++ {name: "Offset out of bounds", addr: 0x00_00_FF_00, count: 4, writeLen: 0, preimageOffset: 17, prestateMem: 0xFF_FF_FF_FF, postateMem: 0xFF_FF_FF_FF, shouldPanic: true}, ++ } ++ for i, c := range cases { ++ for _, v := range llVariations { ++ tName := fmt.Sprintf("%v (%v)", c.name, v.name) ++ t.Run(tName, func(t *testing.T) { ++ effAddr := 0xFFffFFfc & c.addr ++ preimageKey := preimage.Keccak256Key(crypto.Keccak256Hash(preimageValue)).PreimageKey() ++ oracle := testutil.StaticOracle(t, preimageValue) ++ goVm, state, contracts := setup(t, i, oracle) ++ step := state.GetStep() ++ ++ // Define LL-related params ++ var llAddress, llOwnerThread uint32 ++ if v.matchEffAddr { ++ llAddress = effAddr ++ } else { ++ llAddress = effAddr + 4 ++ } ++ if v.matchThreadId { ++ llOwnerThread = state.GetCurrentThread().ThreadId ++ } else { ++ llOwnerThread = state.GetCurrentThread().ThreadId + 1 ++ } ++ ++ // Set up state ++ state.PreimageKey = preimageKey ++ state.PreimageOffset = c.preimageOffset ++ state.GetRegistersRef()[2] = exec.SysRead ++ state.GetRegistersRef()[4] = exec.FdPreimageRead ++ state.GetRegistersRef()[5] = c.addr ++ state.GetRegistersRef()[6] = c.count ++ state.GetMemory().SetMemory(state.GetPC(), syscallInsn) ++ state.LLReservationActive = v.llReservationActive ++ state.LLAddress = llAddress ++ state.LLOwnerThread = llOwnerThread ++ state.GetMemory().SetMemory(effAddr, c.prestateMem) ++ ++ // Setup expectations ++ expected := mttestutil.NewExpectedMTState(state) ++ expected.ExpectStep() ++ expected.ActiveThread().Registers[2] = c.writeLen ++ expected.ActiveThread().Registers[7] = 0 // no error ++ expected.PreimageOffset += c.writeLen ++ expected.ExpectMemoryWrite(effAddr, c.postateMem) ++ if v.shouldClearReservation { ++ expected.LLReservationActive = false ++ expected.LLAddress = 0 ++ expected.LLOwnerThread = 0 ++ } ++ ++ if c.shouldPanic { ++ require.Panics(t, func() { _, _ = goVm.Step(true) }) ++ testutil.AssertPreimageOracleReverts(t, preimageKey, preimageValue, c.preimageOffset, contracts, tracer) ++ } else { ++ stepWitness, err := goVm.Step(true) ++ require.NoError(t, err) ++ ++ // Check expectations ++ expected.Validate(t, state) ++ testutil.ValidateEVM(t, stepWitness, step, goVm, multithreaded.GetStateHashFn(), contracts, tracer) ++ } ++ }) ++ } ++ } ++} ++ ++func TestEVM_MT_StoreOpsClearMemReservation(t *testing.T) { ++ var tracer *tracing.Hooks ++ ++ llVariations := []struct { ++ name string ++ llReservationActive bool ++ matchThreadId bool ++ matchEffAddr bool ++ shouldClearReservation bool ++ }{ ++ {name: "matching reservation", llReservationActive: true, matchThreadId: true, matchEffAddr: true, shouldClearReservation: true}, ++ {name: "matching reservation, diff thread", llReservationActive: true, matchThreadId: false, matchEffAddr: true, shouldClearReservation: true}, ++ {name: "mismatched reservation", llReservationActive: true, matchThreadId: true, matchEffAddr: false, shouldClearReservation: false}, ++ {name: "mismatched reservation, diff thread", llReservationActive: true, matchThreadId: false, matchEffAddr: false, shouldClearReservation: false}, ++ {name: "no reservation, matching addr", llReservationActive: false, matchThreadId: true, matchEffAddr: true, shouldClearReservation: true}, ++ {name: "no reservation, mismatched addr", llReservationActive: false, matchThreadId: true, matchEffAddr: false, shouldClearReservation: false}, ++ } ++ ++ pc := uint32(0x04) ++ rt := uint32(0x12_34_56_78) ++ baseReg := 5 ++ rtReg := 6 ++ cases := []struct { ++ name string ++ opcode int ++ offset int ++ base uint32 ++ effAddr uint32 ++ preMem uint32 ++ postMem uint32 ++ }{ ++ {name: "Store byte", opcode: 0b10_1000, base: 0xFF_00_00_04, offset: 0xFF_00_00_08, effAddr: 0xFF_00_00_0C, preMem: 0xFF_FF_FF_FF, postMem: 0x78_FF_FF_FF}, ++ {name: "Store halfword", opcode: 0b10_1001, base: 0xFF_00_00_04, offset: 0xFF_00_00_08, effAddr: 0xFF_00_00_0C, preMem: 0xFF_FF_FF_FF, postMem: 0x56_78_FF_FF}, ++ {name: "Store word left", opcode: 0b10_1010, base: 0xFF_00_00_04, offset: 0xFF_00_00_08, effAddr: 0xFF_00_00_0C, preMem: 0xFF_FF_FF_FF, postMem: 0x12_34_56_78}, ++ {name: "Store word", opcode: 0b10_1011, base: 0xFF_00_00_04, offset: 0xFF_00_00_08, effAddr: 0xFF_00_00_0C, preMem: 0xFF_FF_FF_FF, postMem: 0x12_34_56_78}, ++ {name: "Store word right", opcode: 0b10_1110, base: 0xFF_00_00_04, offset: 0xFF_00_00_08, effAddr: 0xFF_00_00_0C, preMem: 0xFF_FF_FF_FF, postMem: 0x78_FF_FF_FF}, ++ } ++ for i, c := range cases { ++ for _, v := range llVariations { ++ tName := fmt.Sprintf("%v (%v)", c.name, v.name) ++ t.Run(tName, func(t *testing.T) { ++ insn := uint32((c.opcode << 26) | (baseReg & 0x1F << 21) | (rtReg & 0x1F << 16) | (0xFFFF & c.offset)) ++ goVm, state, contracts := setup(t, i, nil) ++ step := state.GetStep() ++ ++ // Define LL-related params ++ var llAddress, llOwnerThread uint32 ++ if v.matchEffAddr { ++ llAddress = c.effAddr ++ } else { ++ llAddress = c.effAddr + 4 ++ } ++ if v.matchThreadId { ++ llOwnerThread = state.GetCurrentThread().ThreadId ++ } else { ++ llOwnerThread = state.GetCurrentThread().ThreadId + 1 ++ } ++ ++ // Setup state ++ state.GetCurrentThread().Cpu.PC = pc ++ state.GetCurrentThread().Cpu.NextPC = pc + 4 ++ state.GetRegistersRef()[rtReg] = rt ++ state.GetRegistersRef()[baseReg] = c.base ++ state.GetMemory().SetMemory(state.GetPC(), insn) ++ state.GetMemory().SetMemory(c.effAddr, c.preMem) ++ state.LLReservationActive = v.llReservationActive ++ state.LLAddress = llAddress ++ state.LLOwnerThread = llOwnerThread ++ ++ // Setup expectations ++ expected := mttestutil.NewExpectedMTState(state) ++ expected.ExpectStep() ++ expected.ExpectMemoryWrite(c.effAddr, c.postMem) ++ if v.shouldClearReservation { ++ expected.LLReservationActive = false ++ expected.LLAddress = 0 ++ expected.LLOwnerThread = 0 ++ } ++ ++ stepWitness, err := goVm.Step(true) ++ require.NoError(t, err) ++ ++ // Check expectations ++ expected.Validate(t, state) ++ testutil.ValidateEVM(t, stepWitness, step, goVm, multithreaded.GetStateHashFn(), contracts, tracer) ++ }) ++ } ++ } ++} ++ + func TestEVM_SysClone_FlagHandling(t *testing.T) { + contracts := testutil.TestContractsSetup(t, testutil.MipsMultithreaded) + var tracer *tracing.Hooks +@@ -48,7 +417,7 @@ curStep := state.Step +  + var err error + var stepWitness *mipsevm.StepWitness +- us := multithreaded.NewInstrumentedState(state, nil, os.Stdout, os.Stderr, nil) ++ us := multithreaded.NewInstrumentedState(state, nil, os.Stdout, os.Stderr, nil, nil) + if !c.valid { + // The VM should exit + stepWitness, err = us.Step(true) +@@ -92,7 +461,7 @@ for i, c := range cases { + t.Run(c.name, func(t *testing.T) { + stackPtr := uint32(100) +  +- goVm, state, contracts := setup(t, i) ++ goVm, state, contracts := setup(t, i, nil) + mttestutil.InitializeSingleThread(i*333, state, c.traverseRight) + state.Memory.SetMemory(state.GetPC(), syscallInsn) + state.GetRegistersRef()[2] = exec.SysClone // the syscall number +@@ -153,7 +522,7 @@ } +  + for i, c := range cases { + t.Run(c.name, func(t *testing.T) { +- goVm, state, contracts := setup(t, i*789) ++ goVm, state, contracts := setup(t, i*789, nil) + mttestutil.InitializeSingleThread(i*789, state, false) +  + state.GetCurrentThread().ThreadId = c.threadId +@@ -197,7 +566,7 @@ for i, c := range cases { + t.Run(c.name, func(t *testing.T) { + exitCode := uint8(3) +  +- goVm, state, contracts := setup(t, i*133) ++ goVm, state, contracts := setup(t, i*133, nil) + mttestutil.SetupThreads(int64(i*1111), state, i%2 == 0, c.threadCount, 0) +  + state.Memory.SetMemory(state.GetPC(), syscallInsn) +@@ -245,7 +614,7 @@ } +  + for i, c := range cases { + t.Run(c.name, func(t *testing.T) { +- goVm, state, contracts := setup(t, i*133) ++ goVm, state, contracts := setup(t, i*133, nil) + mttestutil.SetupThreads(int64(i*222), state, c.traverseRight, c.activeStackThreadCount, 1) + step := state.Step +  +@@ -285,28 +654,33 @@ func TestEVM_SysFutex_WaitPrivate(t *testing.T) { + var tracer *tracing.Hooks + cases := []struct { + name string +- address uint32 ++ addressParam uint32 ++ effAddr uint32 + targetValue uint32 + actualValue uint32 + timeout uint32 + shouldFail bool + shouldSetTimeout bool + }{ +- {name: "successful wait, no timeout", address: 0x1234, targetValue: 0x01, actualValue: 0x01}, +- {name: "memory mismatch, no timeout", address: 0x1200, targetValue: 0x01, actualValue: 0x02, shouldFail: true}, +- {name: "successful wait w timeout", address: 0x1234, targetValue: 0x01, actualValue: 0x01, timeout: 1000000, shouldSetTimeout: true}, +- {name: "memory mismatch w timeout", address: 0x1200, targetValue: 0x01, actualValue: 0x02, timeout: 2000000, shouldFail: true}, ++ {name: "successful wait, no timeout", addressParam: 0x1234, effAddr: 0x1234, targetValue: 0x01, actualValue: 0x01}, ++ {name: "successful wait, no timeout, unaligned addr", addressParam: 0x1235, effAddr: 0x1234, targetValue: 0x01, actualValue: 0x01}, ++ {name: "memory mismatch, no timeout", addressParam: 0x1200, effAddr: 0x1200, targetValue: 0x01, actualValue: 0x02, shouldFail: true}, ++ {name: "memory mismatch, no timeout, unaligned", addressParam: 0x1203, effAddr: 0x1200, targetValue: 0x01, actualValue: 0x02, shouldFail: true}, ++ {name: "successful wait w timeout", addressParam: 0x1234, effAddr: 0x1234, targetValue: 0x01, actualValue: 0x01, timeout: 1000000, shouldSetTimeout: true}, ++ {name: "successful wait w timeout, unaligned", addressParam: 0x1232, effAddr: 0x1230, targetValue: 0x01, actualValue: 0x01, timeout: 1000000, shouldSetTimeout: true}, ++ {name: "memory mismatch w timeout", addressParam: 0x1200, effAddr: 0x1200, targetValue: 0x01, actualValue: 0x02, timeout: 2000000, shouldFail: true}, ++ {name: "memory mismatch w timeout, unaligned", addressParam: 0x120F, effAddr: 0x120C, targetValue: 0x01, actualValue: 0x02, timeout: 2000000, shouldFail: true}, + } +  + for i, c := range cases { + t.Run(c.name, func(t *testing.T) { +- goVm, state, contracts := setup(t, i*1234) ++ goVm, state, contracts := setup(t, i*1234, nil) + step := state.GetStep() +  + state.Memory.SetMemory(state.GetPC(), syscallInsn) +- state.Memory.SetMemory(c.address, c.actualValue) ++ state.Memory.SetMemory(c.effAddr, c.actualValue) + state.GetRegistersRef()[2] = exec.SysFutex // Set syscall number +- state.GetRegistersRef()[4] = c.address ++ state.GetRegistersRef()[4] = c.addressParam + state.GetRegistersRef()[5] = exec.FutexWaitPrivate + state.GetRegistersRef()[6] = c.targetValue + state.GetRegistersRef()[7] = c.timeout +@@ -322,7 +696,7 @@ expected.ActiveThread().Registers[2] = exec.SysErrorSignal + expected.ActiveThread().Registers[7] = exec.MipsEAGAIN + } else { + // PC and return registers should not update on success, updates happen when wait completes +- expected.ActiveThread().FutexAddr = c.address ++ expected.ActiveThread().FutexAddr = c.effAddr + expected.ActiveThread().FutexVal = c.targetValue + expected.ActiveThread().FutexTimeoutStep = exec.FutexNoTimeout + if c.shouldSetTimeout { +@@ -347,29 +721,36 @@ func TestEVM_SysFutex_WakePrivate(t *testing.T) { + var tracer *tracing.Hooks + cases := []struct { + name string +- address uint32 ++ addressParam uint32 ++ effAddr uint32 + activeThreadCount int + inactiveThreadCount int + traverseRight bool + expectTraverseRight bool + }{ +- {name: "Traverse right", address: 0x6789, activeThreadCount: 2, inactiveThreadCount: 1, traverseRight: true}, +- {name: "Traverse right, no left threads", address: 0x6789, activeThreadCount: 2, inactiveThreadCount: 0, traverseRight: true}, +- {name: "Traverse right, single thread", address: 0x6789, activeThreadCount: 1, inactiveThreadCount: 0, traverseRight: true}, +- {name: "Traverse left", address: 0x6789, activeThreadCount: 2, inactiveThreadCount: 1, traverseRight: false}, +- {name: "Traverse left, switch directions", address: 0x6789, activeThreadCount: 1, inactiveThreadCount: 1, traverseRight: false, expectTraverseRight: true}, +- {name: "Traverse left, single thread", address: 0x6789, activeThreadCount: 1, inactiveThreadCount: 0, traverseRight: false, expectTraverseRight: true}, ++ {name: "Traverse right", addressParam: 0x6700, effAddr: 0x6700, activeThreadCount: 2, inactiveThreadCount: 1, traverseRight: true}, ++ {name: "Traverse right, unaligned addr", addressParam: 0x6789, effAddr: 0x6788, activeThreadCount: 2, inactiveThreadCount: 1, traverseRight: true}, ++ {name: "Traverse right, no left threads", addressParam: 0x6784, effAddr: 0x6784, activeThreadCount: 2, inactiveThreadCount: 0, traverseRight: true}, ++ {name: "Traverse right, no left threads, unaligned addr", addressParam: 0x678E, effAddr: 0x678C, activeThreadCount: 2, inactiveThreadCount: 0, traverseRight: true}, ++ {name: "Traverse right, single thread", addressParam: 0x6788, effAddr: 0x6788, activeThreadCount: 1, inactiveThreadCount: 0, traverseRight: true}, ++ {name: "Traverse right, single thread, unaligned", addressParam: 0x6789, effAddr: 0x6788, activeThreadCount: 1, inactiveThreadCount: 0, traverseRight: true}, ++ {name: "Traverse left", addressParam: 0x6788, effAddr: 0x6788, activeThreadCount: 2, inactiveThreadCount: 1, traverseRight: false}, ++ {name: "Traverse left, unaliagned", addressParam: 0x6789, effAddr: 0x6788, activeThreadCount: 2, inactiveThreadCount: 1, traverseRight: false}, ++ {name: "Traverse left, switch directions", addressParam: 0x6788, effAddr: 0x6788, activeThreadCount: 1, inactiveThreadCount: 1, traverseRight: false, expectTraverseRight: true}, ++ {name: "Traverse left, switch directions, unaligned", addressParam: 0x6789, effAddr: 0x6788, activeThreadCount: 1, inactiveThreadCount: 1, traverseRight: false, expectTraverseRight: true}, ++ {name: "Traverse left, single thread", addressParam: 0x6788, effAddr: 0x6788, activeThreadCount: 1, inactiveThreadCount: 0, traverseRight: false, expectTraverseRight: true}, ++ {name: "Traverse left, single thread, unaligned", addressParam: 0x6789, effAddr: 0x6788, activeThreadCount: 1, inactiveThreadCount: 0, traverseRight: false, expectTraverseRight: true}, + } +  + for i, c := range cases { + t.Run(c.name, func(t *testing.T) { +- goVm, state, contracts := setup(t, i*1122) ++ goVm, state, contracts := setup(t, i*1122, nil) + mttestutil.SetupThreads(int64(i*2244), state, c.traverseRight, c.activeThreadCount, c.inactiveThreadCount) + step := state.Step +  + state.Memory.SetMemory(state.GetPC(), syscallInsn) + state.GetRegistersRef()[2] = exec.SysFutex // Set syscall number +- state.GetRegistersRef()[4] = c.address ++ state.GetRegistersRef()[4] = c.addressParam + state.GetRegistersRef()[5] = exec.FutexWakePrivate +  + // Set up post-state expectations +@@ -377,7 +758,7 @@ expected := mttestutil.NewExpectedMTState(state) + expected.ExpectStep() + expected.ActiveThread().Registers[2] = 0 + expected.ActiveThread().Registers[7] = 0 +- expected.Wakeup = c.address ++ expected.Wakeup = c.effAddr + expected.ExpectPreemption(state) + expected.TraverseRight = c.expectTraverseRight + if c.traverseRight != c.expectTraverseRight { +@@ -449,7 +830,7 @@ } +  + for name, op := range unsupportedFutexOps { + t.Run(name, func(t *testing.T) { +- goVm, state, contracts := setup(t, int(op)) ++ goVm, state, contracts := setup(t, int(op), nil) + step := state.GetStep() +  + state.Memory.SetMemory(state.GetPC(), syscallInsn) +@@ -504,7 +885,7 @@ for i, c := range cases { + for _, traverseRight := range []bool{true, false} { + testName := fmt.Sprintf("%v: %v (traverseRight = %v)", syscallName, c.name, traverseRight) + t.Run(testName, func(t *testing.T) { +- goVm, state, contracts := setup(t, i*789) ++ goVm, state, contracts := setup(t, i*789, nil) + mttestutil.SetupThreads(int64(i*3259), state, traverseRight, c.activeThreads, c.inactiveThreads) +  + state.Memory.SetMemory(state.GetPC(), syscallInsn) +@@ -535,7 +916,7 @@ + func TestEVM_SysOpen(t *testing.T) { + var tracer *tracing.Hooks +  +- goVm, state, contracts := setup(t, 5512) ++ goVm, state, contracts := setup(t, 5512, nil) +  + state.Memory.SetMemory(state.GetPC(), syscallInsn) + state.GetRegistersRef()[2] = exec.SysOpen // Set syscall number +@@ -558,6 +939,158 @@ expected.Validate(t, state) + testutil.ValidateEVM(t, stepWitness, step, goVm, multithreaded.GetStateHashFn(), contracts, tracer) + } +  ++func TestEVM_SysGetPID(t *testing.T) { ++ var tracer *tracing.Hooks ++ goVm, state, contracts := setup(t, 1929, nil) ++ ++ state.Memory.SetMemory(state.GetPC(), syscallInsn) ++ state.GetRegistersRef()[2] = exec.SysGetpid // Set syscall number ++ step := state.Step ++ ++ // Set up post-state expectations ++ expected := mttestutil.NewExpectedMTState(state) ++ expected.ExpectStep() ++ expected.ActiveThread().Registers[2] = 0 ++ expected.ActiveThread().Registers[7] = 0 ++ ++ // State transition ++ var err error ++ var stepWitness *mipsevm.StepWitness ++ stepWitness, err = goVm.Step(true) ++ require.NoError(t, err) ++ ++ // Validate post-state ++ expected.Validate(t, state) ++ testutil.ValidateEVM(t, stepWitness, step, goVm, multithreaded.GetStateHashFn(), contracts, tracer) ++} ++ ++func TestEVM_SysClockGettimeMonotonic(t *testing.T) { ++ testEVM_SysClockGettime(t, exec.ClockGettimeMonotonicFlag) ++} ++ ++func TestEVM_SysClockGettimeRealtime(t *testing.T) { ++ testEVM_SysClockGettime(t, exec.ClockGettimeRealtimeFlag) ++} ++ ++func testEVM_SysClockGettime(t *testing.T, clkid uint32) { ++ var tracer *tracing.Hooks ++ ++ llVariations := []struct { ++ name string ++ llReservationActive bool ++ matchThreadId bool ++ matchEffAddr bool ++ matchEffAddr2 bool ++ shouldClearReservation bool ++ }{ ++ {name: "matching reservation", llReservationActive: true, matchThreadId: true, matchEffAddr: true, shouldClearReservation: true}, ++ {name: "matching reservation, 2nd word", llReservationActive: true, matchThreadId: true, matchEffAddr2: true, shouldClearReservation: true}, ++ {name: "matching reservation, diff thread", llReservationActive: true, matchThreadId: false, matchEffAddr: true, shouldClearReservation: true}, ++ {name: "matching reservation, diff thread, 2nd word", llReservationActive: true, matchThreadId: false, matchEffAddr2: true, shouldClearReservation: true}, ++ {name: "mismatched reservation", llReservationActive: true, matchThreadId: true, matchEffAddr: false, shouldClearReservation: false}, ++ {name: "mismatched reservation, diff thread", llReservationActive: true, matchThreadId: false, matchEffAddr: false, shouldClearReservation: false}, ++ {name: "no reservation, matching addr", llReservationActive: false, matchThreadId: true, matchEffAddr: true, shouldClearReservation: true}, ++ {name: "no reservation, matching addr2", llReservationActive: false, matchThreadId: true, matchEffAddr2: true, shouldClearReservation: true}, ++ {name: "no reservation, mismatched addr", llReservationActive: false, matchThreadId: true, matchEffAddr: false, shouldClearReservation: false}, ++ } ++ ++ cases := []struct { ++ name string ++ timespecAddr uint32 ++ }{ ++ {"aligned timespec address", 0x1000}, ++ {"unaligned timespec address", 0x1003}, ++ } ++ for i, c := range cases { ++ for _, v := range llVariations { ++ tName := fmt.Sprintf("%v (%v)", c.name, v.name) ++ t.Run(tName, func(t *testing.T) { ++ goVm, state, contracts := setup(t, 2101, nil) ++ mttestutil.InitializeSingleThread(2101+i, state, i%2 == 1) ++ effAddr := c.timespecAddr & 0xFFffFFfc ++ effAddr2 := effAddr + 4 ++ step := state.Step ++ ++ // Define LL-related params ++ var llAddress, llOwnerThread uint32 ++ if v.matchEffAddr { ++ llAddress = effAddr ++ } else if v.matchEffAddr2 { ++ llAddress = effAddr2 ++ } else { ++ llAddress = effAddr2 + 8 ++ } ++ if v.matchThreadId { ++ llOwnerThread = state.GetCurrentThread().ThreadId ++ } else { ++ llOwnerThread = state.GetCurrentThread().ThreadId + 1 ++ } ++ ++ state.Memory.SetMemory(state.GetPC(), syscallInsn) ++ state.GetRegistersRef()[2] = exec.SysClockGetTime // Set syscall number ++ state.GetRegistersRef()[4] = clkid // a0 ++ state.GetRegistersRef()[5] = c.timespecAddr // a1 ++ state.LLReservationActive = v.llReservationActive ++ state.LLAddress = llAddress ++ state.LLOwnerThread = llOwnerThread ++ ++ expected := mttestutil.NewExpectedMTState(state) ++ expected.ExpectStep() ++ expected.ActiveThread().Registers[2] = 0 ++ expected.ActiveThread().Registers[7] = 0 ++ next := state.Step + 1 ++ var secs, nsecs uint32 ++ if clkid == exec.ClockGettimeMonotonicFlag { ++ secs = uint32(next / exec.HZ) ++ nsecs = uint32((next % exec.HZ) * (1_000_000_000 / exec.HZ)) ++ } ++ expected.ExpectMemoryWrite(effAddr, secs) ++ expected.ExpectMemoryWrite(effAddr2, nsecs) ++ if v.shouldClearReservation { ++ expected.LLReservationActive = false ++ expected.LLAddress = 0 ++ expected.LLOwnerThread = 0 ++ } ++ ++ var err error ++ var stepWitness *mipsevm.StepWitness ++ stepWitness, err = goVm.Step(true) ++ require.NoError(t, err) ++ ++ // Validate post-state ++ expected.Validate(t, state) ++ testutil.ValidateEVM(t, stepWitness, step, goVm, multithreaded.GetStateHashFn(), contracts, tracer) ++ }) ++ } ++ } ++} ++ ++func TestEVM_SysClockGettimeNonMonotonic(t *testing.T) { ++ var tracer *tracing.Hooks ++ goVm, state, contracts := setup(t, 2101, nil) ++ ++ timespecAddr := uint32(0x1000) ++ state.Memory.SetMemory(state.GetPC(), syscallInsn) ++ state.GetRegistersRef()[2] = exec.SysClockGetTime // Set syscall number ++ state.GetRegistersRef()[4] = 0xDEAD // a0 - invalid clockid ++ state.GetRegistersRef()[5] = timespecAddr // a1 ++ step := state.Step ++ ++ expected := mttestutil.NewExpectedMTState(state) ++ expected.ExpectStep() ++ expected.ActiveThread().Registers[2] = exec.SysErrorSignal ++ expected.ActiveThread().Registers[7] = exec.MipsEINVAL ++ ++ var err error ++ var stepWitness *mipsevm.StepWitness ++ stepWitness, err = goVm.Step(true) ++ require.NoError(t, err) ++ ++ // Validate post-state ++ expected.Validate(t, state) ++ testutil.ValidateEVM(t, stepWitness, step, goVm, multithreaded.GetStateHashFn(), contracts, tracer) ++} ++ + var NoopSyscalls = map[string]uint32{ + "SysGetAffinity": 4240, + "SysMadvise": 4218, +@@ -589,14 +1122,13 @@ "SysSetITimer": 4104, + "SysTimerCreate": 4257, + "SysTimerSetTime": 4258, + "SysTimerDelete": 4261, +- "SysClockGetTime": 4263, + } +  + func TestEVM_NoopSyscall(t *testing.T) { + var tracer *tracing.Hooks + for noopName, noopVal := range NoopSyscalls { + t.Run(noopName, func(t *testing.T) { +- goVm, state, contracts := setup(t, int(noopVal)) ++ goVm, state, contracts := setup(t, int(noopVal), nil) +  + state.Memory.SetMemory(state.GetPC(), syscallInsn) + state.GetRegistersRef()[2] = noopVal // Set syscall number +@@ -627,7 +1159,7 @@ t.Parallel() + var tracer *tracing.Hooks +  + var NoopSyscallNums = maps.Values(NoopSyscalls) +- var SupportedSyscalls = []uint32{exec.SysMmap, exec.SysBrk, exec.SysClone, exec.SysExitGroup, exec.SysRead, exec.SysWrite, exec.SysFcntl, exec.SysExit, exec.SysSchedYield, exec.SysGetTID, exec.SysFutex, exec.SysOpen, exec.SysNanosleep} ++ var SupportedSyscalls = []uint32{exec.SysMmap, exec.SysBrk, exec.SysClone, exec.SysExitGroup, exec.SysRead, exec.SysWrite, exec.SysFcntl, exec.SysExit, exec.SysSchedYield, exec.SysGetTID, exec.SysFutex, exec.SysOpen, exec.SysNanosleep, exec.SysClockGetTime, exec.SysGetpid} + unsupportedSyscalls := make([]uint32, 0, 400) + for i := 4000; i < 4400; i++ { + candidate := uint32(i) +@@ -643,7 +1175,7 @@ i := i + syscallNum := syscallNum + t.Run(testName, func(t *testing.T) { + t.Parallel() +- goVm, state, contracts := setup(t, i*3434) ++ goVm, state, contracts := setup(t, i*3434, nil) + // Setup basic getThreadId syscall instruction + state.Memory.SetMemory(state.GetPC(), syscallInsn) + state.GetRegistersRef()[2] = syscallNum +@@ -672,13 +1204,17 @@ }{ + {name: "Preempt, no timeout #1", step: 100, activeStackSize: 1, otherStackSize: 0, futexAddr: 0x100, targetValue: 0x01, actualValue: 0x01, timeoutStep: exec.FutexNoTimeout}, + {name: "Preempt, no timeout #2", step: 100, activeStackSize: 1, otherStackSize: 1, futexAddr: 0x100, targetValue: 0x01, actualValue: 0x01, timeoutStep: exec.FutexNoTimeout}, + {name: "Preempt, no timeout #3", step: 100, activeStackSize: 2, otherStackSize: 1, futexAddr: 0x100, targetValue: 0x01, actualValue: 0x01, timeoutStep: exec.FutexNoTimeout}, ++ {name: "Preempt, no timeout, unaligned", step: 100, activeStackSize: 2, otherStackSize: 1, futexAddr: 0x101, targetValue: 0x01, actualValue: 0x01, timeoutStep: exec.FutexNoTimeout}, + {name: "Preempt, with timeout #1", step: 100, activeStackSize: 2, otherStackSize: 1, futexAddr: 0x100, targetValue: 0x01, actualValue: 0x01, timeoutStep: 101}, + {name: "Preempt, with timeout #2", step: 100, activeStackSize: 1, otherStackSize: 1, futexAddr: 0x100, targetValue: 0x01, actualValue: 0x01, timeoutStep: 150}, ++ {name: "Preempt, with timeout, unaligned", step: 100, activeStackSize: 1, otherStackSize: 1, futexAddr: 0x101, targetValue: 0x01, actualValue: 0x01, timeoutStep: 150}, + {name: "Wakeup, no timeout #1", step: 100, activeStackSize: 1, otherStackSize: 0, futexAddr: 0x100, targetValue: 0x01, actualValue: 0x02, timeoutStep: exec.FutexNoTimeout, shouldWakeup: true}, + {name: "Wakeup, no timeout #2", step: 100, activeStackSize: 2, otherStackSize: 1, futexAddr: 0x100, targetValue: 0x01, actualValue: 0x02, timeoutStep: exec.FutexNoTimeout, shouldWakeup: true}, ++ {name: "Wakeup, no timeout, unaligned", step: 100, activeStackSize: 2, otherStackSize: 1, futexAddr: 0x102, targetValue: 0x01, actualValue: 0x02, timeoutStep: exec.FutexNoTimeout, shouldWakeup: true}, + {name: "Wakeup with timeout #1", step: 100, activeStackSize: 2, otherStackSize: 1, futexAddr: 0x100, targetValue: 0x01, actualValue: 0x02, timeoutStep: 100, shouldWakeup: true, shouldTimeout: true}, + {name: "Wakeup with timeout #2", step: 100, activeStackSize: 2, otherStackSize: 1, futexAddr: 0x100, targetValue: 0x02, actualValue: 0x02, timeoutStep: 100, shouldWakeup: true, shouldTimeout: true}, + {name: "Wakeup with timeout #3", step: 100, activeStackSize: 2, otherStackSize: 1, futexAddr: 0x100, targetValue: 0x02, actualValue: 0x02, timeoutStep: 50, shouldWakeup: true, shouldTimeout: true}, ++ {name: "Wakeup with timeout, unaligned", step: 100, activeStackSize: 2, otherStackSize: 1, futexAddr: 0x103, targetValue: 0x02, actualValue: 0x02, timeoutStep: 50, shouldWakeup: true, shouldTimeout: true}, + } +  + for _, c := range cases { +@@ -689,8 +1225,8 @@ // Sanity check + if !c.shouldWakeup && c.shouldTimeout { + require.Fail(t, "Invalid test case - cannot expect a timeout with no wakeup") + } +- +- goVm, state, contracts := setup(t, i) ++ effAddr := c.futexAddr & 0xFF_FF_FF_Fc ++ goVm, state, contracts := setup(t, i, nil) + mttestutil.SetupThreads(int64(i*101), state, traverseRight, c.activeStackSize, c.otherStackSize) + state.Step = c.step +  +@@ -698,7 +1234,7 @@ activeThread := state.GetCurrentThread() + activeThread.FutexAddr = c.futexAddr + activeThread.FutexVal = c.targetValue + activeThread.FutexTimeoutStep = c.timeoutStep +- state.GetMemory().SetMemory(c.futexAddr, c.actualValue) ++ state.GetMemory().SetMemory(effAddr, c.actualValue) +  + // Set up post-state expectations + expected := mttestutil.NewExpectedMTState(state) +@@ -752,7 +1288,7 @@ for _, traverseRight := range []bool{true, false} { + testName := fmt.Sprintf("%v (traverseRight = %v)", c.name, traverseRight) + t.Run(testName, func(t *testing.T) { + // Setup +- goVm, state, contracts := setup(t, i*789) ++ goVm, state, contracts := setup(t, i*789, nil) + mttestutil.SetupThreads(int64(i*2947), state, traverseRight, c.threadCount, 0) + // Put threads into a waiting state so that we just traverse through them + for _, thread := range mttestutil.GetAllThreads(state) { +@@ -792,11 +1328,12 @@ } + } +  + func TestEVM_WakeupTraversalStep(t *testing.T) { +- wakeupAddr := uint32(0x1234) ++ addr := uint32(0x1234) + wakeupVal := uint32(0x999) + var tracer *tracing.Hooks + cases := []struct { + name string ++ wakeupAddr uint32 + futexAddr uint32 + targetVal uint32 + traverseRight bool +@@ -805,29 +1342,38 @@ otherStackSize int + shouldClearWakeup bool + shouldPreempt bool + }{ +- {name: "Matching addr, not wakeable, first thread", futexAddr: wakeupAddr, targetVal: wakeupVal, traverseRight: false, activeStackSize: 3, otherStackSize: 0, shouldClearWakeup: true}, +- {name: "Matching addr, wakeable, first thread", futexAddr: wakeupAddr, targetVal: wakeupVal + 1, traverseRight: false, activeStackSize: 3, otherStackSize: 0, shouldClearWakeup: true}, +- {name: "Matching addr, not wakeable, last thread", futexAddr: wakeupAddr, targetVal: wakeupVal, traverseRight: true, activeStackSize: 1, otherStackSize: 2, shouldClearWakeup: true}, +- {name: "Matching addr, wakeable, last thread", futexAddr: wakeupAddr, targetVal: wakeupVal + 1, traverseRight: true, activeStackSize: 1, otherStackSize: 2, shouldClearWakeup: true}, +- {name: "Matching addr, not wakeable, intermediate thread", futexAddr: wakeupAddr, targetVal: wakeupVal, traverseRight: false, activeStackSize: 2, otherStackSize: 2, shouldClearWakeup: true}, +- {name: "Matching addr, wakeable, intermediate thread", futexAddr: wakeupAddr, targetVal: wakeupVal + 1, traverseRight: true, activeStackSize: 2, otherStackSize: 2, shouldClearWakeup: true}, +- {name: "Mismatched addr, last thread", futexAddr: wakeupAddr + 4, traverseRight: true, activeStackSize: 1, otherStackSize: 2, shouldPreempt: true, shouldClearWakeup: true}, +- {name: "Mismatched addr", futexAddr: wakeupAddr + 4, traverseRight: true, activeStackSize: 2, otherStackSize: 2, shouldPreempt: true}, +- {name: "Mismatched addr", futexAddr: wakeupAddr + 4, traverseRight: false, activeStackSize: 2, otherStackSize: 0, shouldPreempt: true}, +- {name: "Mismatched addr", futexAddr: wakeupAddr + 4, traverseRight: false, activeStackSize: 1, otherStackSize: 0, shouldPreempt: true}, +- {name: "Non-waiting thread", futexAddr: exec.FutexEmptyAddr, traverseRight: false, activeStackSize: 1, otherStackSize: 0, shouldPreempt: true}, +- {name: "Non-waiting thread", futexAddr: exec.FutexEmptyAddr, traverseRight: true, activeStackSize: 2, otherStackSize: 1, shouldPreempt: true}, +- {name: "Non-waiting thread, last thread", futexAddr: exec.FutexEmptyAddr, traverseRight: true, activeStackSize: 1, otherStackSize: 1, shouldPreempt: true, shouldClearWakeup: true}, ++ {name: "Matching addr, not wakeable, first thread", wakeupAddr: addr, futexAddr: addr, targetVal: wakeupVal, traverseRight: false, activeStackSize: 3, otherStackSize: 0, shouldClearWakeup: true}, ++ {name: "Matching addr, wakeable, first thread", wakeupAddr: addr, futexAddr: addr, targetVal: wakeupVal + 1, traverseRight: false, activeStackSize: 3, otherStackSize: 0, shouldClearWakeup: true}, ++ {name: "Matching addr, not wakeable, last thread", wakeupAddr: addr, futexAddr: addr, targetVal: wakeupVal, traverseRight: true, activeStackSize: 1, otherStackSize: 2, shouldClearWakeup: true}, ++ {name: "Matching addr, wakeable, last thread", wakeupAddr: addr, futexAddr: addr, targetVal: wakeupVal + 1, traverseRight: true, activeStackSize: 1, otherStackSize: 2, shouldClearWakeup: true}, ++ {name: "Matching addr, not wakeable, intermediate thread", wakeupAddr: addr, futexAddr: addr, targetVal: wakeupVal, traverseRight: false, activeStackSize: 2, otherStackSize: 2, shouldClearWakeup: true}, ++ {name: "Matching addr, wakeable, intermediate thread", wakeupAddr: addr, futexAddr: addr, targetVal: wakeupVal + 1, traverseRight: true, activeStackSize: 2, otherStackSize: 2, shouldClearWakeup: true}, ++ {name: "Mismatched addr, last thread", wakeupAddr: addr, futexAddr: addr + 4, traverseRight: true, activeStackSize: 1, otherStackSize: 2, shouldPreempt: true, shouldClearWakeup: true}, ++ {name: "Mismatched addr", wakeupAddr: addr, futexAddr: addr + 4, traverseRight: true, activeStackSize: 2, otherStackSize: 2, shouldPreempt: true}, ++ {name: "Mismatched addr", wakeupAddr: addr, futexAddr: addr + 4, traverseRight: false, activeStackSize: 2, otherStackSize: 0, shouldPreempt: true}, ++ {name: "Mismatched addr", wakeupAddr: addr, futexAddr: addr + 4, traverseRight: false, activeStackSize: 1, otherStackSize: 0, shouldPreempt: true}, ++ {name: "Non-waiting thread", wakeupAddr: addr, futexAddr: exec.FutexEmptyAddr, traverseRight: false, activeStackSize: 1, otherStackSize: 0, shouldPreempt: true}, ++ {name: "Non-waiting thread", wakeupAddr: addr, futexAddr: exec.FutexEmptyAddr, traverseRight: true, activeStackSize: 2, otherStackSize: 1, shouldPreempt: true}, ++ {name: "Non-waiting thread, last thread", wakeupAddr: addr, futexAddr: exec.FutexEmptyAddr, traverseRight: true, activeStackSize: 1, otherStackSize: 1, shouldPreempt: true, shouldClearWakeup: true}, ++ // Check behavior of unaligned addresses - should be the same as aligned addresses (no memory access) ++ {name: "Matching addr, unaligned", wakeupAddr: addr + 1, futexAddr: addr + 1, targetVal: wakeupVal, traverseRight: false, activeStackSize: 3, otherStackSize: 0, shouldClearWakeup: true}, ++ {name: "Mismatched addr, last thread, wakeup unaligned", wakeupAddr: addr + 1, futexAddr: addr + 4, traverseRight: true, activeStackSize: 1, otherStackSize: 2, shouldPreempt: true, shouldClearWakeup: true}, ++ {name: "Mismatched addr, last thread, futex unaligned", wakeupAddr: addr, futexAddr: addr + 5, traverseRight: true, activeStackSize: 1, otherStackSize: 2, shouldPreempt: true, shouldClearWakeup: true}, ++ {name: "Mismatched addr, last thread, wake & futex unaligned", wakeupAddr: addr + 1, futexAddr: addr + 5, traverseRight: true, activeStackSize: 1, otherStackSize: 2, shouldPreempt: true, shouldClearWakeup: true}, ++ {name: "Mismatched addr, wakeup unaligned", wakeupAddr: addr + 3, futexAddr: addr + 4, traverseRight: true, activeStackSize: 2, otherStackSize: 2, shouldPreempt: true}, ++ {name: "Mismatched addr, futex unaligned", wakeupAddr: addr, futexAddr: addr + 6, traverseRight: true, activeStackSize: 2, otherStackSize: 2, shouldPreempt: true}, ++ {name: "Mismatched addr, wakeup & futex unaligned", wakeupAddr: addr + 2, futexAddr: addr + 6, traverseRight: true, activeStackSize: 2, otherStackSize: 2, shouldPreempt: true}, ++ {name: "Non-waiting thread, last thread, unaligned wakeup", wakeupAddr: addr + 3, futexAddr: exec.FutexEmptyAddr, traverseRight: true, activeStackSize: 1, otherStackSize: 1, shouldPreempt: true, shouldClearWakeup: true}, + } +  + for i, c := range cases { + t.Run(c.name, func(t *testing.T) { +- goVm, state, contracts := setup(t, i*2000) ++ goVm, state, contracts := setup(t, i*2000, nil) + mttestutil.SetupThreads(int64(i*101), state, c.traverseRight, c.activeStackSize, c.otherStackSize) + step := state.Step +  +- state.Wakeup = wakeupAddr +- state.GetMemory().SetMemory(wakeupAddr, wakeupVal) ++ state.Wakeup = c.wakeupAddr ++ state.GetMemory().SetMemory(c.wakeupAddr&0xFF_FF_FF_FC, wakeupVal) + activeThread := state.GetCurrentThread() + activeThread.FutexAddr = c.futexAddr + activeThread.FutexVal = c.targetVal +@@ -870,7 +1416,7 @@ } + for i, c := range cases { + t.Run(c.name, func(t *testing.T) { + // Setup +- goVm, state, contracts := setup(t, i*789) ++ goVm, state, contracts := setup(t, i*789, nil) + mttestutil.SetupThreads(int64(i*2947), state, false, c.threadCount, 0) + state.Wakeup = 0x08 + step := state.Step +@@ -924,7 +1470,7 @@ } +  + for i, c := range cases { + t.Run(c.name, func(t *testing.T) { +- goVm, state, contracts := setup(t, i*789) ++ goVm, state, contracts := setup(t, i*789, nil) + // Setup basic getThreadId syscall instruction + state.Memory.SetMemory(state.GetPC(), syscallInsn) + state.GetRegistersRef()[2] = exec.SysGetTID // Set syscall number +@@ -956,9 +1502,9 @@ }) + } + } +  +-func setup(t require.TestingT, randomSeed int) (mipsevm.FPVM, *multithreaded.State, *testutil.ContractMetadata) { ++func setup(t require.TestingT, randomSeed int, preimageOracle mipsevm.PreimageOracle) (mipsevm.FPVM, *multithreaded.State, *testutil.ContractMetadata) { + v := GetMultiThreadedTestCase(t) +- vm := v.VMFactory(nil, os.Stdout, os.Stderr, testutil.CreateLogger(), testutil.WithRandomization(int64(randomSeed))) ++ vm := v.VMFactory(preimageOracle, os.Stdout, os.Stderr, testutil.CreateLogger(), testutil.WithRandomization(int64(randomSeed))) + state := mttestutil.GetMtState(t, vm) +  + return vm, state, v.Contracts
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+196
+
-0
+ +
+ +
+
+
diff --git OP/cannon/mipsevm/tests/evm_singlethreaded_test.go CELO/cannon/mipsevm/tests/evm_singlethreaded_test.go +new file mode 100644 +index 0000000000000000000000000000000000000000..32cad32cc00e25b2e71ac12454b0026eecd7fa4f +--- /dev/null ++++ CELO/cannon/mipsevm/tests/evm_singlethreaded_test.go +@@ -0,0 +1,196 @@ ++package tests ++ ++import ( ++ "encoding/binary" ++ "os" ++ "testing" ++ ++ "github.com/ethereum/go-ethereum/core/tracing" ++ "github.com/ethereum/go-ethereum/crypto" ++ "github.com/stretchr/testify/require" ++ ++ "github.com/ethereum-optimism/optimism/cannon/mipsevm/exec" ++ "github.com/ethereum-optimism/optimism/cannon/mipsevm/memory" ++ "github.com/ethereum-optimism/optimism/cannon/mipsevm/testutil" ++ preimage "github.com/ethereum-optimism/optimism/op-preimage" ++) ++ ++func TestEVM_LL(t *testing.T) { ++ var tracer *tracing.Hooks ++ ++ cases := []struct { ++ name string ++ base uint32 ++ offset int ++ value uint32 ++ effAddr uint32 ++ rtReg int ++ }{ ++ {name: "Aligned effAddr", base: 0x00_00_00_01, offset: 0x0133, value: 0xABCD, effAddr: 0x00_00_01_34, rtReg: 5}, ++ {name: "Aligned effAddr, signed extended", base: 0x00_00_00_01, offset: 0xFF33, value: 0xABCD, effAddr: 0xFF_FF_FF_34, rtReg: 5}, ++ {name: "Unaligned effAddr", base: 0xFF_12_00_01, offset: 0x3401, value: 0xABCD, effAddr: 0xFF_12_34_00, rtReg: 5}, ++ {name: "Unaligned effAddr, sign extended w overflow", base: 0xFF_12_00_01, offset: 0x8401, value: 0xABCD, effAddr: 0xFF_11_84_00, rtReg: 5}, ++ {name: "Return register set to 0", base: 0x00_00_00_01, offset: 0x0133, value: 0xABCD, effAddr: 0x00_00_01_34, rtReg: 0}, ++ } ++ v := GetSingleThreadedTestCase(t) ++ for i, c := range cases { ++ t.Run(c.name, func(t *testing.T) { ++ rtReg := c.rtReg ++ baseReg := 6 ++ pc := uint32(0x44) ++ insn := uint32((0b11_0000 << 26) | (baseReg & 0x1F << 21) | (rtReg & 0x1F << 16) | (0xFFFF & c.offset)) ++ goVm := v.VMFactory(nil, os.Stdout, os.Stderr, testutil.CreateLogger(), testutil.WithRandomization(int64(i)), testutil.WithPC(pc), testutil.WithNextPC(pc+4)) ++ state := goVm.GetState() ++ state.GetMemory().SetMemory(pc, insn) ++ state.GetMemory().SetMemory(c.effAddr, c.value) ++ state.GetRegistersRef()[baseReg] = c.base ++ step := state.GetStep() ++ ++ // Setup expectations ++ expected := testutil.NewExpectedState(state) ++ expected.Step += 1 ++ expected.PC = pc + 4 ++ expected.NextPC = pc + 8 ++ if rtReg != 0 { ++ expected.Registers[rtReg] = c.value ++ } ++ ++ stepWitness, err := goVm.Step(true) ++ require.NoError(t, err) ++ ++ // Check expectations ++ expected.Validate(t, state) ++ testutil.ValidateEVM(t, stepWitness, step, goVm, v.StateHashFn, v.Contracts, tracer) ++ }) ++ } ++} ++ ++func TestEVM_SC(t *testing.T) { ++ var tracer *tracing.Hooks ++ ++ cases := []struct { ++ name string ++ base uint32 ++ offset int ++ value uint32 ++ effAddr uint32 ++ rtReg int ++ }{ ++ {name: "Aligned effAddr", base: 0x00_00_00_01, offset: 0x0133, value: 0xABCD, effAddr: 0x00_00_01_34, rtReg: 5}, ++ {name: "Aligned effAddr, signed extended", base: 0x00_00_00_01, offset: 0xFF33, value: 0xABCD, effAddr: 0xFF_FF_FF_34, rtReg: 5}, ++ {name: "Unaligned effAddr", base: 0xFF_12_00_01, offset: 0x3401, value: 0xABCD, effAddr: 0xFF_12_34_00, rtReg: 5}, ++ {name: "Unaligned effAddr, sign extended w overflow", base: 0xFF_12_00_01, offset: 0x8401, value: 0xABCD, effAddr: 0xFF_11_84_00, rtReg: 5}, ++ {name: "Return register set to 0", base: 0xFF_12_00_01, offset: 0x8401, value: 0xABCD, effAddr: 0xFF_11_84_00, rtReg: 0}, ++ } ++ v := GetSingleThreadedTestCase(t) ++ for i, c := range cases { ++ t.Run(c.name, func(t *testing.T) { ++ rtReg := c.rtReg ++ baseReg := 6 ++ pc := uint32(0x44) ++ insn := uint32((0b11_1000 << 26) | (baseReg & 0x1F << 21) | (rtReg & 0x1F << 16) | (0xFFFF & c.offset)) ++ goVm := v.VMFactory(nil, os.Stdout, os.Stderr, testutil.CreateLogger(), testutil.WithRandomization(int64(i)), testutil.WithPC(pc), testutil.WithNextPC(pc+4)) ++ state := goVm.GetState() ++ state.GetMemory().SetMemory(pc, insn) ++ state.GetRegistersRef()[baseReg] = c.base ++ state.GetRegistersRef()[rtReg] = c.value ++ step := state.GetStep() ++ ++ // Setup expectations ++ expected := testutil.NewExpectedState(state) ++ expected.Step += 1 ++ expected.PC = pc + 4 ++ expected.NextPC = pc + 8 ++ expectedMemory := memory.NewMemory() ++ expectedMemory.SetMemory(pc, insn) ++ expectedMemory.SetMemory(c.effAddr, c.value) ++ expected.MemoryRoot = expectedMemory.MerkleRoot() ++ if rtReg != 0 { ++ expected.Registers[rtReg] = 1 // 1 for success ++ } ++ ++ stepWitness, err := goVm.Step(true) ++ require.NoError(t, err) ++ ++ // Check expectations ++ expected.Validate(t, state) ++ testutil.ValidateEVM(t, stepWitness, step, goVm, v.StateHashFn, v.Contracts, tracer) ++ }) ++ } ++} ++ ++func TestEVM_SysRead_Preimage(t *testing.T) { ++ var tracer *tracing.Hooks ++ ++ preimageValue := make([]byte, 0, 8) ++ preimageValue = binary.BigEndian.AppendUint32(preimageValue, 0x12_34_56_78) ++ preimageValue = binary.BigEndian.AppendUint32(preimageValue, 0x98_76_54_32) ++ ++ v := GetSingleThreadedTestCase(t) ++ ++ cases := []struct { ++ name string ++ addr uint32 ++ count uint32 ++ writeLen uint32 ++ preimageOffset uint32 ++ prestateMem uint32 ++ postateMem uint32 ++ shouldPanic bool ++ }{ ++ {name: "Aligned addr, write 1 byte", addr: 0x00_00_FF_00, count: 1, writeLen: 1, preimageOffset: 8, prestateMem: 0xFF_FF_FF_FF, postateMem: 0x12_FF_FF_FF}, ++ {name: "Aligned addr, write 2 byte", addr: 0x00_00_FF_00, count: 2, writeLen: 2, preimageOffset: 8, prestateMem: 0xFF_FF_FF_FF, postateMem: 0x12_34_FF_FF}, ++ {name: "Aligned addr, write 3 byte", addr: 0x00_00_FF_00, count: 3, writeLen: 3, preimageOffset: 8, prestateMem: 0xFF_FF_FF_FF, postateMem: 0x12_34_56_FF}, ++ {name: "Aligned addr, write 4 byte", addr: 0x00_00_FF_00, count: 4, writeLen: 4, preimageOffset: 8, prestateMem: 0xFF_FF_FF_FF, postateMem: 0x12_34_56_78}, ++ {name: "1-byte misaligned addr, write 1 byte", addr: 0x00_00_FF_01, count: 1, writeLen: 1, preimageOffset: 8, prestateMem: 0xFF_FF_FF_FF, postateMem: 0xFF_12_FF_FF}, ++ {name: "1-byte misaligned addr, write 2 byte", addr: 0x00_00_FF_01, count: 2, writeLen: 2, preimageOffset: 9, prestateMem: 0xFF_FF_FF_FF, postateMem: 0xFF_34_56_FF}, ++ {name: "1-byte misaligned addr, write 3 byte", addr: 0x00_00_FF_01, count: 3, writeLen: 3, preimageOffset: 8, prestateMem: 0xFF_FF_FF_FF, postateMem: 0xFF_12_34_56}, ++ {name: "2-byte misaligned addr, write 1 byte", addr: 0x00_00_FF_02, count: 1, writeLen: 1, preimageOffset: 8, prestateMem: 0xFF_FF_FF_FF, postateMem: 0xFF_FF_12_FF}, ++ {name: "2-byte misaligned addr, write 2 byte", addr: 0x00_00_FF_02, count: 2, writeLen: 2, preimageOffset: 12, prestateMem: 0xFF_FF_FF_FF, postateMem: 0xFF_FF_98_76}, ++ {name: "3-byte misaligned addr, write 1 byte", addr: 0x00_00_FF_03, count: 1, writeLen: 1, preimageOffset: 8, prestateMem: 0xFF_FF_FF_FF, postateMem: 0xFF_FF_FF_12}, ++ {name: "Count of 0", addr: 0x00_00_FF_03, count: 0, writeLen: 0, preimageOffset: 8, prestateMem: 0xFF_FF_FF_FF, postateMem: 0xFF_FF_FF_FF}, ++ {name: "Count greater than 4", addr: 0x00_00_FF_00, count: 15, writeLen: 4, preimageOffset: 8, prestateMem: 0xFF_FF_FF_FF, postateMem: 0x12_34_56_78}, ++ {name: "Count greater than 4, unaligned", addr: 0x00_00_FF_01, count: 15, writeLen: 3, preimageOffset: 8, prestateMem: 0xFF_FF_FF_FF, postateMem: 0xFF_12_34_56}, ++ {name: "Offset at last byte", addr: 0x00_00_FF_00, count: 4, writeLen: 1, preimageOffset: 15, prestateMem: 0xFF_FF_FF_FF, postateMem: 0x32_FF_FF_FF}, ++ {name: "Offset just out of bounds", addr: 0x00_00_FF_00, count: 4, writeLen: 0, preimageOffset: 16, prestateMem: 0xFF_FF_FF_FF, postateMem: 0xFF_FF_FF_FF, shouldPanic: true}, ++ {name: "Offset out of bounds", addr: 0x00_00_FF_00, count: 4, writeLen: 0, preimageOffset: 17, prestateMem: 0xFF_FF_FF_FF, postateMem: 0xFF_FF_FF_FF, shouldPanic: true}, ++ } ++ for i, c := range cases { ++ t.Run(c.name, func(t *testing.T) { ++ effAddr := 0xFFffFFfc & c.addr ++ preimageKey := preimage.Keccak256Key(crypto.Keccak256Hash(preimageValue)).PreimageKey() ++ oracle := testutil.StaticOracle(t, preimageValue) ++ goVm := v.VMFactory(oracle, os.Stdout, os.Stderr, testutil.CreateLogger(), testutil.WithRandomization(int64(i)), testutil.WithPreimageKey(preimageKey), testutil.WithPreimageOffset(c.preimageOffset)) ++ state := goVm.GetState() ++ step := state.GetStep() ++ ++ // Set up state ++ state.GetRegistersRef()[2] = exec.SysRead ++ state.GetRegistersRef()[4] = exec.FdPreimageRead ++ state.GetRegistersRef()[5] = c.addr ++ state.GetRegistersRef()[6] = c.count ++ state.GetMemory().SetMemory(state.GetPC(), syscallInsn) ++ state.GetMemory().SetMemory(effAddr, c.prestateMem) ++ ++ // Setup expectations ++ expected := testutil.NewExpectedState(state) ++ expected.ExpectStep() ++ expected.Registers[2] = c.writeLen ++ expected.Registers[7] = 0 // no error ++ expected.PreimageOffset += c.writeLen ++ expected.ExpectMemoryWrite(effAddr, c.postateMem) ++ ++ if c.shouldPanic { ++ require.Panics(t, func() { _, _ = goVm.Step(true) }) ++ testutil.AssertPreimageOracleReverts(t, preimageKey, preimageValue, c.preimageOffset, v.Contracts, tracer) ++ } else { ++ stepWitness, err := goVm.Step(true) ++ require.NoError(t, err) ++ ++ // Check expectations ++ expected.Validate(t, state) ++ testutil.ValidateEVM(t, stepWitness, step, goVm, v.StateHashFn, v.Contracts, tracer) ++ } ++ }) ++ } ++}
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+91
+
-32
+ +
+ +
+
+
diff --git OP/cannon/mipsevm/tests/fuzz_evm_common_test.go CELO/cannon/mipsevm/tests/fuzz_evm_common_test.go +index 2f68706b60d35d82b222f604dbdd64f89ebafdad..2b85727679b1772816f3e8feec860e59e845c07d 100644 +--- OP/cannon/mipsevm/tests/fuzz_evm_common_test.go ++++ CELO/cannon/mipsevm/tests/fuzz_evm_common_test.go +@@ -2,10 +2,11 @@ package tests +  + import ( + "bytes" ++ "encoding/binary" ++ "math" + "os" + "testing" +  +- "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + "github.com/stretchr/testify/require" +  +@@ -216,24 +217,29 @@ } +  + func FuzzStatePreimageRead(f *testing.F) { + versions := GetMipsVersionTestCases(f) +- f.Fuzz(func(t *testing.T, addr uint32, count uint32, preimageOffset uint32, seed int64) { ++ f.Fuzz(func(t *testing.T, addr uint32, pc uint32, count uint32, preimageOffset uint32, seed int64) { + for _, v := range versions { + t.Run(v.Name, func(t *testing.T) { ++ effAddr := addr & 0xFF_FF_FF_FC ++ pc = pc & 0xFF_FF_FF_FC ++ preexistingMemoryVal := [4]byte{0xFF, 0xFF, 0xFF, 0xFF} + preimageValue := []byte("hello world") +- if preimageOffset >= uint32(len(preimageValue)) { ++ preimageData := testutil.AddPreimageLengthPrefix(preimageValue) ++ if preimageOffset >= uint32(len(preimageData)) || pc == effAddr { + t.SkipNow() + } + preimageKey := preimage.Keccak256Key(crypto.Keccak256Hash(preimageValue)).PreimageKey() + oracle := testutil.StaticOracle(t, preimageValue) +  + goVm := v.VMFactory(oracle, os.Stdout, os.Stderr, testutil.CreateLogger(), +- testutil.WithRandomization(seed), testutil.WithPreimageKey(preimageKey), testutil.WithPreimageOffset(preimageOffset)) ++ testutil.WithRandomization(seed), testutil.WithPreimageKey(preimageKey), testutil.WithPreimageOffset(preimageOffset), testutil.WithPCAndNextPC(pc)) + state := goVm.GetState() + state.GetRegistersRef()[2] = exec.SysRead + state.GetRegistersRef()[4] = exec.FdPreimageRead + state.GetRegistersRef()[5] = addr + state.GetRegistersRef()[6] = count + state.GetMemory().SetMemory(state.GetPC(), syscallInsn) ++ state.GetMemory().SetMemory(effAddr, binary.BigEndian.Uint32(preexistingMemoryVal[:])) + step := state.GetStep() +  + alignment := addr & 3 +@@ -242,7 +248,7 @@ if count < writeLen { + writeLen = count + } + // Cap write length to remaining bytes of the preimage +- preimageDataLen := uint32(len(preimageValue) + 8) // Data len includes a length prefix ++ preimageDataLen := uint32(len(preimageData)) + if preimageOffset+writeLen > preimageDataLen { + writeLen = preimageDataLen - preimageOffset + } +@@ -254,18 +260,18 @@ expected.NextPC = state.GetCpu().NextPC + 4 + expected.Registers[2] = writeLen + expected.Registers[7] = 0 // no error + expected.PreimageOffset += writeLen ++ if writeLen > 0 { ++ // Expect a memory write ++ expectedMemory := preexistingMemoryVal ++ copy(expectedMemory[alignment:], preimageData[preimageOffset:preimageOffset+writeLen]) ++ expected.ExpectMemoryWrite(effAddr, binary.BigEndian.Uint32(expectedMemory[:])) ++ } +  + stepWitness, err := goVm.Step(true) + require.NoError(t, err) + require.True(t, stepWitness.HasPreimage()) +  +- // TODO(cp-983) - Do stricter validation of expected memory +- expected.Validate(t, state, testutil.SkipMemoryValidation) +- if writeLen == 0 { +- // Note: We are not asserting a memory root change when writeLen > 0 because we may not necessarily +- // modify memory - it's possible we just write the leading zero bytes of the length prefix +- require.Equal(t, expected.MemoryRoot, common.Hash(state.GetMemory().MerkleRoot())) +- } ++ expected.Validate(t, state) + testutil.ValidateEVM(t, stepWitness, step, goVm, v.StateHashFn, v.Contracts, nil) + }) + } +@@ -274,43 +280,80 @@ } +  + func FuzzStateHintWrite(f *testing.F) { + versions := GetMipsVersionTestCases(f) +- f.Fuzz(func(t *testing.T, addr uint32, count uint32, randSeed int64) { ++ f.Fuzz(func(t *testing.T, addr uint32, count uint32, hint1, hint2, hint3 []byte, randSeed int64) { + for _, v := range versions { + t.Run(v.Name, func(t *testing.T) { +- preimageData := []byte("hello world") +- preimageKey := preimage.Keccak256Key(crypto.Keccak256Hash(preimageData)).PreimageKey() +- // TODO(cp-983) - use testutil.HintTrackingOracle, validate expected hints +- oracle := testutil.StaticOracle(t, preimageData) // only used for hinting ++ // Make sure pc does not overlap with hint data in memory ++ pc := uint32(0) ++ if addr <= 8 { ++ addr += 8 ++ } +  ++ // Set up hint data ++ r := testutil.NewRandHelper(randSeed) ++ hints := [][]byte{hint1, hint2, hint3} ++ hintData := make([]byte, 0) ++ for _, hint := range hints { ++ prefixedHint := testutil.AddHintLengthPrefix(hint) ++ hintData = append(hintData, prefixedHint...) ++ } ++ lastHintLen := math.Round(r.Fraction() * float64(len(hintData))) ++ lastHint := hintData[:int(lastHintLen)] ++ expectedBytesToProcess := int(count) + int(lastHintLen) ++ if expectedBytesToProcess > len(hintData) { ++ // Add an extra hint to span the rest of the hint data ++ randomHint := r.RandomBytes(t, expectedBytesToProcess) ++ prefixedHint := testutil.AddHintLengthPrefix(randomHint) ++ hintData = append(hintData, prefixedHint...) ++ hints = append(hints, randomHint) ++ } ++ ++ // Set up state ++ oracle := &testutil.HintTrackingOracle{} + goVm := v.VMFactory(oracle, os.Stdout, os.Stderr, testutil.CreateLogger(), +- testutil.WithRandomization(randSeed), testutil.WithPreimageKey(preimageKey)) ++ testutil.WithRandomization(randSeed), testutil.WithLastHint(lastHint), testutil.WithPCAndNextPC(pc)) + state := goVm.GetState() + state.GetRegistersRef()[2] = exec.SysWrite + state.GetRegistersRef()[4] = exec.FdHintWrite + state.GetRegistersRef()[5] = addr + state.GetRegistersRef()[6] = count + step := state.GetStep() +- +- // Set random data at the target memory range +- randBytes := testutil.RandomBytes(t, randSeed, count) +- err := state.GetMemory().SetMemoryRange(addr, bytes.NewReader(randBytes)) ++ err := state.GetMemory().SetMemoryRange(addr, bytes.NewReader(hintData[int(lastHintLen):])) + require.NoError(t, err) +- // Set instruction + state.GetMemory().SetMemory(state.GetPC(), syscallInsn) +  ++ // Set up expectations + expected := testutil.NewExpectedState(state) + expected.Step += 1 + expected.PC = state.GetCpu().NextPC + expected.NextPC = state.GetCpu().NextPC + 4 + expected.Registers[2] = count + expected.Registers[7] = 0 // no error ++ // Figure out hint expectations ++ var expectedHints [][]byte ++ expectedLastHint := make([]byte, 0) ++ byteIndex := 0 ++ for _, hint := range hints { ++ hintDataLength := len(hint) + 4 // Hint data + prefix ++ hintLastByteIndex := hintDataLength + byteIndex - 1 ++ if hintLastByteIndex < expectedBytesToProcess { ++ expectedHints = append(expectedHints, hint) ++ } else { ++ expectedLastHint = hintData[byteIndex:expectedBytesToProcess] ++ break ++ } ++ byteIndex += hintDataLength ++ } ++ expected.LastHint = expectedLastHint +  ++ // Run state transition + stepWitness, err := goVm.Step(true) + require.NoError(t, err) + require.False(t, stepWitness.HasPreimage()) +  +- // TODO(cp-983) - validate expected hints +- expected.Validate(t, state, testutil.SkipHintValidation) ++ // Validate ++ require.Equal(t, expectedHints, oracle.Hints()) ++ expected.Validate(t, state) + testutil.ValidateEVM(t, stepWitness, step, goVm, v.StateHashFn, v.Contracts, nil) + }) + } +@@ -322,23 +365,33 @@ versions := GetMipsVersionTestCases(f) + f.Fuzz(func(t *testing.T, addr uint32, count uint32, seed int64) { + for _, v := range versions { + t.Run(v.Name, func(t *testing.T) { ++ // Make sure pc does not overlap with preimage data in memory ++ pc := uint32(0) ++ if addr <= 8 { ++ addr += 8 ++ } ++ effAddr := addr & 0xFF_FF_FF_FC ++ preexistingMemoryVal := [4]byte{0x12, 0x34, 0x56, 0x78} + preimageData := []byte("hello world") + preimageKey := preimage.Keccak256Key(crypto.Keccak256Hash(preimageData)).PreimageKey() + oracle := testutil.StaticOracle(t, preimageData) +  + goVm := v.VMFactory(oracle, os.Stdout, os.Stderr, testutil.CreateLogger(), +- testutil.WithRandomization(seed), testutil.WithPreimageKey(preimageKey), testutil.WithPreimageOffset(128)) ++ testutil.WithRandomization(seed), testutil.WithPreimageKey(preimageKey), testutil.WithPreimageOffset(128), testutil.WithPCAndNextPC(pc)) + state := goVm.GetState() + state.GetRegistersRef()[2] = exec.SysWrite + state.GetRegistersRef()[4] = exec.FdPreimageWrite + state.GetRegistersRef()[5] = addr + state.GetRegistersRef()[6] = count + state.GetMemory().SetMemory(state.GetPC(), syscallInsn) ++ state.GetMemory().SetMemory(effAddr, binary.BigEndian.Uint32(preexistingMemoryVal[:])) + step := state.GetStep() +  +- sz := 4 - (addr & 0x3) +- if sz < count { +- count = sz ++ expectBytesWritten := count ++ alignment := addr & 0x3 ++ sz := 4 - alignment ++ if sz < expectBytesWritten { ++ expectBytesWritten = sz + } +  + expected := testutil.NewExpectedState(state) +@@ -346,15 +399,21 @@ expected.Step += 1 + expected.PC = state.GetCpu().NextPC + expected.NextPC = state.GetCpu().NextPC + 4 + expected.PreimageOffset = 0 +- expected.Registers[2] = count ++ expected.Registers[2] = expectBytesWritten + expected.Registers[7] = 0 // No error ++ expected.PreimageKey = preimageKey ++ if expectBytesWritten > 0 { ++ // Copy original preimage key, but shift it left by expectBytesWritten ++ copy(expected.PreimageKey[:], preimageKey[expectBytesWritten:]) ++ // Copy memory data to rightmost expectedBytesWritten ++ copy(expected.PreimageKey[32-expectBytesWritten:], preexistingMemoryVal[alignment:]) ++ } +  + stepWitness, err := goVm.Step(true) + require.NoError(t, err) + require.False(t, stepWitness.HasPreimage()) +  +- // TODO(cp-983) - validate preimage key +- expected.Validate(t, state, testutil.SkipPreimageKeyValidation) ++ expected.Validate(t, state) + testutil.ValidateEVM(t, stepWitness, step, goVm, v.StateHashFn, v.Contracts, nil) + }) + }
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+3
+
-3
+ +
+ +
+
+
diff --git OP/cannon/mipsevm/tests/helpers.go CELO/cannon/mipsevm/tests/helpers.go +index 5b75a03c6bc4b8dadf368adf1a287258cba8535c..d96940972a65e66f713ab3e6f3f06e0103151359 100644 +--- OP/cannon/mipsevm/tests/helpers.go ++++ CELO/cannon/mipsevm/tests/helpers.go +@@ -31,7 +31,7 @@ mutator := mttestutil.NewStateMutatorMultiThreaded(state) + for _, opt := range opts { + opt(mutator) + } +- return multithreaded.NewInstrumentedState(state, po, stdOut, stdErr, log) ++ return multithreaded.NewInstrumentedState(state, po, stdOut, stdErr, log, nil) + } +  + type ElfVMFactory func(t require.TestingT, elfFile string, po mipsevm.PreimageOracle, stdOut, stdErr io.Writer, log log.Logger) mipsevm.FPVM +@@ -45,8 +45,8 @@ } +  + func multiThreadElfVmFactory(t require.TestingT, elfFile string, po mipsevm.PreimageOracle, stdOut, stdErr io.Writer, log log.Logger) mipsevm.FPVM { + state, meta := testutil.LoadELFProgram(t, elfFile, multithreaded.CreateInitialState, false) +- fpvm := multithreaded.NewInstrumentedState(state, po, stdOut, stdErr, log) +- require.NoError(t, fpvm.InitDebug(meta)) ++ fpvm := multithreaded.NewInstrumentedState(state, po, stdOut, stdErr, log, meta) ++ require.NoError(t, fpvm.InitDebug()) + return fpvm + } +
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+3
+
-3
+ +
+ +
+
+
diff --git OP/cannon/mipsevm/testutil/elf.go CELO/cannon/mipsevm/testutil/elf.go +index 683f9870265377a820b114387544d7da75f3eeaf..b5b63cdeb1d39e7896f2e5b8afbe3ff5ee2c353b 100644 +--- OP/cannon/mipsevm/testutil/elf.go ++++ CELO/cannon/mipsevm/testutil/elf.go +@@ -9,7 +9,7 @@ "github.com/ethereum-optimism/optimism/cannon/mipsevm" + "github.com/ethereum-optimism/optimism/cannon/mipsevm/program" + ) +  +-func LoadELFProgram[T mipsevm.FPVMState](t require.TestingT, name string, initState program.CreateInitialFPVMState[T], doPatchGo bool) (T, *program.Metadata) { ++func LoadELFProgram[T mipsevm.FPVMState](t require.TestingT, name string, initState program.CreateInitialFPVMState[T], doPatchGoGC bool) (T, *program.Metadata) { + elfProgram, err := elf.Open(name) + require.NoError(t, err, "open ELF file") + meta, err := program.MakeMetadata(elfProgram) +@@ -18,8 +18,8 @@ + state, err := program.LoadELF(elfProgram, initState) + require.NoError(t, err, "load ELF into state") +  +- if doPatchGo { +- err = program.PatchGo(elfProgram, state) ++ if doPatchGoGC { ++ err = program.PatchGoGC(elfProgram, state) + require.NoError(t, err, "apply Go runtime patches") + } +
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+48
+
-25
+ +
+ +
+
+
diff --git OP/cannon/mipsevm/testutil/mips.go CELO/cannon/mipsevm/testutil/mips.go +index f596e0e4de7bbd494d22b14c47b486f814bc5152..33ada41869d76e694ef4d8fe50cdc95253287d1e 100644 +--- OP/cannon/mipsevm/testutil/mips.go ++++ CELO/cannon/mipsevm/testutil/mips.go +@@ -21,19 +21,24 @@ preimage "github.com/ethereum-optimism/optimism/op-preimage" + ) +  + type MIPSEVM struct { ++ sender vm.AccountRef ++ startingGas uint64 + env *vm.EVM + evmState *state.StateDB + addrs *Addresses + localOracle mipsevm.PreimageOracle + artifacts *Artifacts + // Track step execution for logging purposes +- lastStep uint64 +- lastStepInput []byte ++ lastStep uint64 ++ lastStepInput []byte ++ lastPreimageOracleInput []byte + } +  + func NewMIPSEVM(contracts *ContractMetadata) *MIPSEVM { + env, evmState := NewEVMEnv(contracts) +- return &MIPSEVM{env, evmState, contracts.Addresses, nil, contracts.Artifacts, math.MaxUint64, nil} ++ sender := vm.AccountRef{0x13, 0x37} ++ startingGas := uint64(30_000_000) ++ return &MIPSEVM{sender, startingGas, env, evmState, contracts.Addresses, nil, contracts.Artifacts, math.MaxUint64, nil, nil} + } +  + func (m *MIPSEVM) SetTracer(tracer *tracing.Hooks) { +@@ -52,23 +57,23 @@ // Step is a pure function that computes the poststate from the VM state encoded in the StepWitness. + func (m *MIPSEVM) Step(t *testing.T, stepWitness *mipsevm.StepWitness, step uint64, stateHashFn mipsevm.HashFn) []byte { + m.lastStep = step + m.lastStepInput = nil +- sender := common.Address{0x13, 0x37} +- startingGas := uint64(30_000_000) ++ m.lastPreimageOracleInput = nil +  + // we take a snapshot so we can clean up the state, and isolate the logs of this instruction run. + snap := m.env.StateDB.Snapshot() +  + if stepWitness.HasPreimage() { + t.Logf("reading preimage key %x at offset %d", stepWitness.PreimageKey, stepWitness.PreimageOffset) +- poInput, err := EncodePreimageOracleInput(t, stepWitness, mipsevm.LocalContext{}, m.localOracle, m.artifacts.Oracle) ++ poInput, err := m.encodePreimageOracleInput(t, stepWitness.PreimageKey, stepWitness.PreimageValue, stepWitness.PreimageOffset, mipsevm.LocalContext{}) ++ m.lastPreimageOracleInput = poInput + require.NoError(t, err, "encode preimage oracle input") +- _, leftOverGas, err := m.env.Call(vm.AccountRef(sender), m.addrs.Oracle, poInput, startingGas, common.U2560) +- require.NoErrorf(t, err, "evm should not fail, took %d gas", startingGas-leftOverGas) ++ _, leftOverGas, err := m.env.Call(m.sender, m.addrs.Oracle, poInput, m.startingGas, common.U2560) ++ require.NoErrorf(t, err, "evm should not fail, took %d gas", m.startingGas-leftOverGas) + } +  + input := EncodeStepInput(t, stepWitness, mipsevm.LocalContext{}, m.artifacts.MIPS) + m.lastStepInput = input +- ret, leftOverGas, err := m.env.Call(vm.AccountRef(sender), m.addrs.MIPS, input, startingGas, common.U2560) ++ ret, leftOverGas, err := m.env.Call(m.sender, m.addrs.MIPS, input, m.startingGas, common.U2560) + require.NoError(t, err, "evm should not fail") + require.Len(t, ret, 32, "expecting 32-byte state hash") + // remember state hash, to check it against state +@@ -82,7 +87,7 @@ require.NoError(t, err, "state hash could not be computed") + require.Equal(t, stateHash, postHash, "logged state must be accurate") +  + m.env.StateDB.RevertToSnapshot(snap) +- t.Logf("EVM step %d took %d gas, and returned stateHash %s", step, startingGas-leftOverGas, postHash) ++ t.Logf("EVM step %d took %d gas, and returned stateHash %s", step, m.startingGas-leftOverGas, postHash) + return evmPost + } +  +@@ -92,46 +97,48 @@ require.NoError(t, err) + return input + } +  +-func EncodePreimageOracleInput(t *testing.T, wit *mipsevm.StepWitness, localContext mipsevm.LocalContext, localOracle mipsevm.PreimageOracle, oracle *foundry.Artifact) ([]byte, error) { +- if wit.PreimageKey == ([32]byte{}) { ++func (m *MIPSEVM) encodePreimageOracleInput(t *testing.T, preimageKey [32]byte, preimageValue []byte, preimageOffset uint32, localContext mipsevm.LocalContext) ([]byte, error) { ++ if preimageKey == ([32]byte{}) { + return nil, errors.New("cannot encode pre-image oracle input, witness has no pre-image to proof") + } ++ localOracle := m.localOracle ++ oracle := m.artifacts.Oracle +  +- switch preimage.KeyType(wit.PreimageKey[0]) { ++ switch preimage.KeyType(preimageKey[0]) { + case preimage.LocalKeyType: +- if len(wit.PreimageValue) > 32+8 { +- return nil, fmt.Errorf("local pre-image exceeds maximum size of 32 bytes with key 0x%x", wit.PreimageKey) ++ if len(preimageValue) > 32+8 { ++ return nil, fmt.Errorf("local pre-image exceeds maximum size of 32 bytes with key 0x%x", preimageKey) + } +- preimagePart := wit.PreimageValue[8:] ++ preimagePart := preimageValue[8:] + var tmp [32]byte + copy(tmp[:], preimagePart) + input, err := oracle.ABI.Pack("loadLocalData", +- new(big.Int).SetBytes(wit.PreimageKey[1:]), ++ new(big.Int).SetBytes(preimageKey[1:]), + localContext, + tmp, + new(big.Int).SetUint64(uint64(len(preimagePart))), +- new(big.Int).SetUint64(uint64(wit.PreimageOffset)), ++ new(big.Int).SetUint64(uint64(preimageOffset)), + ) + require.NoError(t, err) + return input, nil + case preimage.Keccak256KeyType: + input, err := oracle.ABI.Pack( + "loadKeccak256PreimagePart", +- new(big.Int).SetUint64(uint64(wit.PreimageOffset)), +- wit.PreimageValue[8:]) ++ new(big.Int).SetUint64(uint64(preimageOffset)), ++ preimageValue[8:]) + require.NoError(t, err) + return input, nil + case preimage.PrecompileKeyType: + if localOracle == nil { +- return nil, fmt.Errorf("local oracle is required for precompile preimages") ++ return nil, errors.New("local oracle is required for precompile preimages") + } +- preimage := localOracle.GetPreimage(preimage.Keccak256Key(wit.PreimageKey).PreimageKey()) ++ preimage := localOracle.GetPreimage(preimage.Keccak256Key(preimageKey).PreimageKey()) + precompile := common.BytesToAddress(preimage[:20]) + requiredGas := binary.BigEndian.Uint64(preimage[20:28]) + callInput := preimage[28:] + input, err := oracle.ABI.Pack( + "loadPrecompilePreimagePart", +- new(big.Int).SetUint64(uint64(wit.PreimageOffset)), ++ new(big.Int).SetUint64(uint64(preimageOffset)), + precompile, + requiredGas, + callInput, +@@ -140,15 +147,23 @@ require.NoError(t, err) + return input, nil + default: + return nil, fmt.Errorf("unsupported pre-image type %d, cannot prepare preimage with key %x offset %d for oracle", +- wit.PreimageKey[0], wit.PreimageKey, wit.PreimageOffset) ++ preimageKey[0], preimageKey, preimageOffset) + } + } +  ++func (m *MIPSEVM) assertPreimageOracleReverts(t *testing.T, preimageKey [32]byte, preimageValue []byte, preimageOffset uint32) { ++ poInput, err := m.encodePreimageOracleInput(t, preimageKey, preimageValue, preimageOffset, mipsevm.LocalContext{}) ++ require.NoError(t, err, "encode preimage oracle input") ++ _, _, evmErr := m.env.Call(m.sender, m.addrs.Oracle, poInput, m.startingGas, common.U2560) ++ ++ require.ErrorContains(t, evmErr, "execution reverted") ++} ++ + func LogStepFailureAtCleanup(t *testing.T, mipsEvm *MIPSEVM) { + t.Cleanup(func() { + if t.Failed() { + // Note: For easier debugging of a failing step, see MIPS.t.sol#test_step_debug_succeeds() +- t.Logf("Failed while executing step %d with input: %x", mipsEvm.lastStep, mipsEvm.lastStepInput) ++ t.Logf("Failed while executing step %d with\n\tstep input: %x\n\tpreimageOracle input: %x", mipsEvm.lastStep, mipsEvm.lastStepInput, mipsEvm.lastPreimageOracleInput) + } + }) + } +@@ -184,3 +199,11 @@ require.EqualValues(t, err, vm.ErrExecutionReverted) + logs := evmState.Logs() + require.Equal(t, 0, len(logs)) + } ++ ++func AssertPreimageOracleReverts(t *testing.T, preimageKey [32]byte, preimageValue []byte, preimageOffset uint32, contracts *ContractMetadata, tracer *tracing.Hooks) { ++ evm := NewMIPSEVM(contracts) ++ evm.SetTracer(tracer) ++ LogStepFailureAtCleanup(t, evm) ++ ++ evm.assertPreimageOracleReverts(t, preimageKey, preimageValue, preimageOffset) ++}
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+8
+
-3
+ +
+ +
+
+
diff --git OP/cannon/mipsevm/testutil/oracle.go CELO/cannon/mipsevm/testutil/oracle.go +index e0cd9baf6dff54ef30776cd693e89a8a8bea7fc8..64b0f31a897c9fd65a3a4f75dca49317d2409302 100644 +--- OP/cannon/mipsevm/testutil/oracle.go ++++ CELO/cannon/mipsevm/testutil/oracle.go +@@ -120,14 +120,19 @@ + return oracle, fmt.Sprintf("computing %d * %d + %d\nclaim %d is good!\n", s, a, b, s*a+b), "started!" + } +  +-func AllocOracle(t *testing.T, numAllocs int) *TestOracle { ++func AllocOracle(t *testing.T, numAllocs int, allocSize int) *TestOracle { + return &TestOracle{ + hint: func(v []byte) {}, + getPreimage: func(k [32]byte) []byte { +- if k != preimage.LocalIndexKey(0).PreimageKey() { ++ switch k { ++ case preimage.LocalIndexKey(0).PreimageKey(): ++ return binary.LittleEndian.AppendUint64(nil, uint64(numAllocs)) ++ case preimage.LocalIndexKey(1).PreimageKey(): ++ return binary.LittleEndian.AppendUint64(nil, uint64(allocSize)) ++ default: + t.Fatalf("invalid preimage request for %x", k) + } +- return binary.LittleEndian.AppendUint64(nil, uint64(numAllocs)) ++ panic("unreachable") + }, + } + }
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+46
+
-17
+ +
+ +
+
+
diff --git OP/cannon/mipsevm/testutil/rand.go CELO/cannon/mipsevm/testutil/rand.go +index 2364c7ad5e92ab74353d1fc8fcaffebe60a9de12..96ff0eb6318b9439c5c782c03dbc6d110cfd3c6d 100644 +--- OP/cannon/mipsevm/testutil/rand.go ++++ CELO/cannon/mipsevm/testutil/rand.go +@@ -1,53 +1,82 @@ + package testutil +  + import ( ++ "encoding/binary" + "math/rand" +  + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" + ) +  +-func RandHash(r *rand.Rand) common.Hash { ++type RandHelper struct { ++ r *rand.Rand ++} ++ ++func NewRandHelper(seed int64) *RandHelper { ++ r := rand.New(rand.NewSource(seed)) ++ return &RandHelper{r: r} ++} ++ ++func (h *RandHelper) Uint32() uint32 { ++ return h.r.Uint32() ++} ++ ++func (h *RandHelper) Fraction() float64 { ++ return h.r.Float64() ++} ++ ++func (h *RandHelper) Intn(n int) int { ++ return h.r.Intn(n) ++} ++ ++func (h *RandHelper) RandHash() common.Hash { + var bytes [32]byte +- _, err := r.Read(bytes[:]) ++ _, err := h.r.Read(bytes[:]) + if err != nil { + panic(err) + } + return bytes + } +  +-func RandHint(r *rand.Rand) []byte { +- count := r.Intn(10) ++func (h *RandHelper) RandHint() []byte { ++ ++ bytesCount := h.r.Intn(24) ++ bytes := make([]byte, bytesCount) ++ ++ if bytesCount >= 8 { ++ // Set up a reasonable length prefix ++ nextHintLen := uint64(h.r.Intn(30)) ++ binary.BigEndian.PutUint64(bytes, nextHintLen) +  +- bytes := make([]byte, count) +- _, err := r.Read(bytes[:]) +- if err != nil { +- panic(err) ++ _, err := h.r.Read(bytes[8:]) ++ if err != nil { ++ panic(err) ++ } + } ++ + return bytes + } +  +-func RandRegisters(r *rand.Rand) *[32]uint32 { ++func (h *RandHelper) RandRegisters() *[32]uint32 { + registers := new([32]uint32) + for i := 0; i < 32; i++ { +- registers[i] = r.Uint32() ++ registers[i] = h.r.Uint32() + } + return registers + } +  +-func RandomBytes(t require.TestingT, seed int64, length uint32) []byte { +- r := rand.New(rand.NewSource(seed)) ++func (h *RandHelper) RandomBytes(t require.TestingT, length int) []byte { + randBytes := make([]byte, length) +- if _, err := r.Read(randBytes); err != nil { ++ if _, err := h.r.Read(randBytes); err != nil { + require.NoError(t, err) + } + return randBytes + } +  +-func RandPC(r *rand.Rand) uint32 { +- return AlignPC(r.Uint32()) ++func (h *RandHelper) RandPC() uint32 { ++ return AlignPC(h.r.Uint32()) + } +  +-func RandStep(r *rand.Rand) uint64 { +- return BoundStep(r.Uint64()) ++func (h *RandHelper) RandStep() uint64 { ++ return BoundStep(h.r.Uint64()) + }
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+41
+
-22
+ +
+ +
+
+
diff --git OP/cannon/mipsevm/testutil/state.go CELO/cannon/mipsevm/testutil/state.go +index 3b912c8dd0674cb0644e3fab63fe9725708a2969..86d5cfb2b6adfb532b46240a9085c1c20c651e1b 100644 +--- OP/cannon/mipsevm/testutil/state.go ++++ CELO/cannon/mipsevm/testutil/state.go +@@ -1,8 +1,8 @@ + package testutil +  + import ( ++ "encoding/binary" + "fmt" +- "slices" + "testing" +  + "github.com/ethereum/go-ethereum/common" +@@ -10,12 +10,25 @@ "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/stretchr/testify/require" +  + "github.com/ethereum-optimism/optimism/cannon/mipsevm" ++ "github.com/ethereum-optimism/optimism/cannon/mipsevm/memory" + ) +  +-func CopyRegisters(state mipsevm.FPVMState) *[32]uint32 { +- copy := new([32]uint32) +- *copy = *state.GetRegistersRef() +- return copy ++func AddHintLengthPrefix(data []byte) []byte { ++ dataLen := len(data) ++ prefixed := make([]byte, 0, dataLen+4) ++ prefixed = binary.BigEndian.AppendUint32(prefixed, uint32(dataLen)) ++ prefixed = append(prefixed, data...) ++ ++ return prefixed ++} ++ ++func AddPreimageLengthPrefix(data []byte) []byte { ++ dataLen := len(data) ++ prefixed := make([]byte, 0, dataLen+8) ++ prefixed = binary.BigEndian.AppendUint64(prefixed, uint64(dataLen)) ++ prefixed = append(prefixed, data...) ++ ++ return prefixed + } +  + type StateMutator interface { +@@ -44,6 +57,13 @@ + func WithNextPC(nextPC uint32) StateOption { + return func(state StateMutator) { + state.SetNextPC(nextPC) ++ } ++} ++ ++func WithPCAndNextPC(pc uint32) StateOption { ++ return func(state StateMutator) { ++ state.SetPC(pc) ++ state.SetNextPC(pc + 4) + } + } +  +@@ -115,6 +135,7 @@ Step uint64 + LastHint hexutil.Bytes + Registers [32]uint32 + MemoryRoot common.Hash ++ expectedMemory *memory.Memory + } +  + func NewExpectedState(fromState mipsevm.FPVMState) *ExpectedState { +@@ -132,22 +153,24 @@ Step: fromState.GetStep(), + LastHint: fromState.GetLastHint(), + Registers: *fromState.GetRegistersRef(), + MemoryRoot: fromState.GetMemory().MerkleRoot(), ++ expectedMemory: fromState.GetMemory().Copy(), + } + } +  +-type StateValidationFlags int ++func (e *ExpectedState) ExpectStep() { ++ // Set some standard expectations for a normal step ++ e.Step += 1 ++ e.PC += 4 ++ e.NextPC += 4 ++} +  +-// TODO(cp-983) - Remove these validation hacks +-const ( +- SkipMemoryValidation StateValidationFlags = iota +- SkipHintValidation +- SkipPreimageKeyValidation +-) ++func (e *ExpectedState) ExpectMemoryWrite(addr uint32, val uint32) { ++ e.expectedMemory.SetMemory(addr, val) ++ e.MemoryRoot = e.expectedMemory.MerkleRoot() ++} +  +-func (e *ExpectedState) Validate(t testing.TB, actualState mipsevm.FPVMState, flags ...StateValidationFlags) { +- if !slices.Contains(flags, SkipPreimageKeyValidation) { +- require.Equal(t, e.PreimageKey, actualState.GetPreimageKey(), fmt.Sprintf("Expect preimageKey = %v", e.PreimageKey)) +- } ++func (e *ExpectedState) Validate(t testing.TB, actualState mipsevm.FPVMState) { ++ require.Equal(t, e.PreimageKey, actualState.GetPreimageKey(), fmt.Sprintf("Expect preimageKey = %v", e.PreimageKey)) + require.Equal(t, e.PreimageOffset, actualState.GetPreimageOffset(), fmt.Sprintf("Expect preimageOffset = %v", e.PreimageOffset)) + require.Equal(t, e.PC, actualState.GetCpu().PC, fmt.Sprintf("Expect PC = 0x%x", e.PC)) + require.Equal(t, e.NextPC, actualState.GetCpu().NextPC, fmt.Sprintf("Expect nextPC = 0x%x", e.NextPC)) +@@ -157,11 +180,7 @@ require.Equal(t, e.Heap, actualState.GetHeap(), fmt.Sprintf("Expect heap = 0x%x", e.Heap)) + require.Equal(t, e.ExitCode, actualState.GetExitCode(), fmt.Sprintf("Expect exitCode = 0x%x", e.ExitCode)) + require.Equal(t, e.Exited, actualState.GetExited(), fmt.Sprintf("Expect exited = %v", e.Exited)) + require.Equal(t, e.Step, actualState.GetStep(), fmt.Sprintf("Expect step = %d", e.Step)) +- if !slices.Contains(flags, SkipHintValidation) { +- require.Equal(t, e.LastHint, actualState.GetLastHint(), fmt.Sprintf("Expect lastHint = %v", e.LastHint)) +- } ++ require.Equal(t, e.LastHint, actualState.GetLastHint(), fmt.Sprintf("Expect lastHint = %v", e.LastHint)) + require.Equal(t, e.Registers, *actualState.GetRegistersRef(), fmt.Sprintf("Expect registers = %v", e.Registers)) +- if !slices.Contains(flags, SkipMemoryValidation) { +- require.Equal(t, e.MemoryRoot, common.Hash(actualState.GetMemory().MerkleRoot()), fmt.Sprintf("Expect memory root = %v", e.MemoryRoot)) +- } ++ require.Equal(t, e.MemoryRoot, common.Hash(actualState.GetMemory().MerkleRoot()), fmt.Sprintf("Expect memory root = %v", e.MemoryRoot)) + }
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+35
+
-0
+ +
+ +
+
+
diff --git OP/cannon/mipsevm/versions/detect.go CELO/cannon/mipsevm/versions/detect.go +new file mode 100644 +index 0000000000000000000000000000000000000000..ca4b9be9c51d5d30ea5f445373b07e8461de0706 +--- /dev/null ++++ CELO/cannon/mipsevm/versions/detect.go +@@ -0,0 +1,35 @@ ++package versions ++ ++import ( ++ "fmt" ++ "io" ++ ++ "github.com/ethereum-optimism/optimism/cannon/serialize" ++ "github.com/ethereum-optimism/optimism/op-service/ioutil" ++) ++ ++func DetectVersion(path string) (StateVersion, error) { ++ if !serialize.IsBinaryFile(path) { ++ return VersionSingleThreaded, nil ++ } ++ ++ var f io.ReadCloser ++ f, err := ioutil.OpenDecompressed(path) ++ if err != nil { ++ return 0, fmt.Errorf("failed to open file %q: %w", path, err) ++ } ++ defer f.Close() ++ ++ var ver StateVersion ++ bin := serialize.NewBinaryReader(f) ++ if err := bin.ReadUInt(&ver); err != nil { ++ return 0, err ++ } ++ ++ switch ver { ++ case VersionSingleThreaded, VersionMultiThreaded: ++ return ver, nil ++ default: ++ return 0, fmt.Errorf("%w: %d", ErrUnknownVersion, ver) ++ } ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+65
+
-0
+ +
+ +
+
+
diff --git OP/cannon/mipsevm/versions/detect_test.go CELO/cannon/mipsevm/versions/detect_test.go +new file mode 100644 +index 0000000000000000000000000000000000000000..38a90f1786948a566162f5c5eb0101b90c714da7 +--- /dev/null ++++ CELO/cannon/mipsevm/versions/detect_test.go +@@ -0,0 +1,65 @@ ++package versions ++ ++import ( ++ "os" ++ "path/filepath" ++ "testing" ++ ++ "github.com/ethereum-optimism/optimism/cannon/mipsevm/multithreaded" ++ "github.com/ethereum-optimism/optimism/cannon/mipsevm/singlethreaded" ++ "github.com/ethereum-optimism/optimism/op-service/ioutil" ++ "github.com/stretchr/testify/require" ++) ++ ++func TestDetectVersion(t *testing.T) { ++ t.Run("SingleThreadedJSON", func(t *testing.T) { ++ state, err := NewFromState(singlethreaded.CreateEmptyState()) ++ require.NoError(t, err) ++ path := writeToFile(t, "state.json", state) ++ version, err := DetectVersion(path) ++ require.NoError(t, err) ++ require.Equal(t, VersionSingleThreaded, version) ++ }) ++ ++ t.Run("SingleThreadedBinary", func(t *testing.T) { ++ state, err := NewFromState(singlethreaded.CreateEmptyState()) ++ require.NoError(t, err) ++ path := writeToFile(t, "state.bin.gz", state) ++ version, err := DetectVersion(path) ++ require.NoError(t, err) ++ require.Equal(t, VersionSingleThreaded, version) ++ }) ++ ++ t.Run("MultiThreadedBinary", func(t *testing.T) { ++ state, err := NewFromState(multithreaded.CreateEmptyState()) ++ require.NoError(t, err) ++ path := writeToFile(t, "state.bin.gz", state) ++ version, err := DetectVersion(path) ++ require.NoError(t, err) ++ require.Equal(t, VersionMultiThreaded, version) ++ }) ++} ++ ++func TestDetectVersionInvalid(t *testing.T) { ++ t.Run("bad gzip", func(t *testing.T) { ++ dir := t.TempDir() ++ filename := "state.bin.gz" ++ path := filepath.Join(dir, filename) ++ require.NoError(t, os.WriteFile(path, []byte("ekans"), 0o644)) ++ ++ _, err := DetectVersion(path) ++ require.ErrorContains(t, err, "failed to open file") ++ }) ++ ++ t.Run("unknown version", func(t *testing.T) { ++ dir := t.TempDir() ++ filename := "state.bin.gz" ++ path := filepath.Join(dir, filename) ++ const badVersion = 0xFF ++ err := ioutil.WriteCompressedBytes(path, []byte{badVersion}, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0o644) ++ require.NoError(t, err) ++ ++ _, err = DetectVersion(path) ++ require.ErrorIs(t, err, ErrUnknownVersion) ++ }) ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+130
+
-0
+ +
+ +
+
+
diff --git OP/cannon/mipsevm/versions/state.go CELO/cannon/mipsevm/versions/state.go +new file mode 100644 +index 0000000000000000000000000000000000000000..afd2a94204b3905cd56e1084785c00dcdbb3c049 +--- /dev/null ++++ CELO/cannon/mipsevm/versions/state.go +@@ -0,0 +1,130 @@ ++package versions ++ ++import ( ++ "encoding/json" ++ "errors" ++ "fmt" ++ "io" ++ ++ "github.com/ethereum-optimism/optimism/cannon/mipsevm" ++ "github.com/ethereum-optimism/optimism/cannon/mipsevm/multithreaded" ++ "github.com/ethereum-optimism/optimism/cannon/mipsevm/singlethreaded" ++ "github.com/ethereum-optimism/optimism/cannon/serialize" ++ "github.com/ethereum-optimism/optimism/op-service/jsonutil" ++) ++ ++type StateVersion uint8 ++ ++const ( ++ // VersionSingleThreaded is the version of the Cannon STF found in op-contracts/v1.6.0 - https://github.com/ethereum-optimism/optimism/blob/op-contracts/v1.6.0/packages/contracts-bedrock/src/cannon/MIPS.sol ++ VersionSingleThreaded StateVersion = iota ++ VersionMultiThreaded ++) ++ ++var ( ++ ErrUnknownVersion = errors.New("unknown version") ++ ErrJsonNotSupported = errors.New("json not supported") ++) ++ ++var StateVersionTypes = []StateVersion{VersionSingleThreaded, VersionMultiThreaded} ++ ++func LoadStateFromFile(path string) (*VersionedState, error) { ++ if !serialize.IsBinaryFile(path) { ++ // Always use singlethreaded for JSON states ++ state, err := jsonutil.LoadJSON[singlethreaded.State](path) ++ if err != nil { ++ return nil, err ++ } ++ return NewFromState(state) ++ } ++ return serialize.LoadSerializedBinary[VersionedState](path) ++} ++ ++func NewFromState(state mipsevm.FPVMState) (*VersionedState, error) { ++ switch state := state.(type) { ++ case *singlethreaded.State: ++ return &VersionedState{ ++ Version: VersionSingleThreaded, ++ FPVMState: state, ++ }, nil ++ case *multithreaded.State: ++ return &VersionedState{ ++ Version: VersionMultiThreaded, ++ FPVMState: state, ++ }, nil ++ default: ++ return nil, fmt.Errorf("%w: %T", ErrUnknownVersion, state) ++ } ++} ++ ++// VersionedState deserializes a FPVMState and implements VersionedState based on the version of that state. ++// It does this based on the version byte read in Deserialize ++type VersionedState struct { ++ Version StateVersion ++ mipsevm.FPVMState ++} ++ ++func (s *VersionedState) Serialize(w io.Writer) error { ++ bout := serialize.NewBinaryWriter(w) ++ if err := bout.WriteUInt(s.Version); err != nil { ++ return err ++ } ++ return s.FPVMState.Serialize(w) ++} ++ ++func (s *VersionedState) Deserialize(in io.Reader) error { ++ bin := serialize.NewBinaryReader(in) ++ if err := bin.ReadUInt(&s.Version); err != nil { ++ return err ++ } ++ ++ switch s.Version { ++ case VersionSingleThreaded: ++ state := &singlethreaded.State{} ++ if err := state.Deserialize(in); err != nil { ++ return err ++ } ++ s.FPVMState = state ++ return nil ++ case VersionMultiThreaded: ++ state := &multithreaded.State{} ++ if err := state.Deserialize(in); err != nil { ++ return err ++ } ++ s.FPVMState = state ++ return nil ++ default: ++ return fmt.Errorf("%w: %d", ErrUnknownVersion, s.Version) ++ } ++} ++ ++// MarshalJSON marshals the underlying state without adding version prefix. ++// JSON states are always assumed to be single threaded ++func (s *VersionedState) MarshalJSON() ([]byte, error) { ++ if s.Version != VersionSingleThreaded { ++ return nil, fmt.Errorf("%w for type %T", ErrJsonNotSupported, s.FPVMState) ++ } ++ return json.Marshal(s.FPVMState) ++} ++ ++func (s StateVersion) String() string { ++ switch s { ++ case VersionSingleThreaded: ++ return "singlethreaded" ++ case VersionMultiThreaded: ++ return "multithreaded" ++ default: ++ return "unknown" ++ } ++} ++ ++func ParseStateVersion(ver string) (StateVersion, error) { ++ switch ver { ++ case "singlethreaded": ++ return VersionSingleThreaded, nil ++ case "multithreaded": ++ return VersionMultiThreaded, nil ++ default: ++ return StateVersion(0), errors.New("unknown state version") ++ } ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+76
+
-0
+ +
+ +
+
+
diff --git OP/cannon/mipsevm/versions/state_test.go CELO/cannon/mipsevm/versions/state_test.go +new file mode 100644 +index 0000000000000000000000000000000000000000..7fb36cd5734c11510487a164c27c7b0732e9172d +--- /dev/null ++++ CELO/cannon/mipsevm/versions/state_test.go +@@ -0,0 +1,76 @@ ++package versions ++ ++import ( ++ "path/filepath" ++ "testing" ++ ++ "github.com/ethereum-optimism/optimism/cannon/mipsevm/multithreaded" ++ "github.com/ethereum-optimism/optimism/cannon/mipsevm/singlethreaded" ++ "github.com/ethereum-optimism/optimism/cannon/serialize" ++ "github.com/stretchr/testify/require" ++) ++ ++func TestNewFromState(t *testing.T) { ++ t.Run("singlethreaded", func(t *testing.T) { ++ actual, err := NewFromState(singlethreaded.CreateEmptyState()) ++ require.NoError(t, err) ++ require.IsType(t, &singlethreaded.State{}, actual.FPVMState) ++ require.Equal(t, VersionSingleThreaded, actual.Version) ++ }) ++ ++ t.Run("multithreaded", func(t *testing.T) { ++ actual, err := NewFromState(multithreaded.CreateEmptyState()) ++ require.NoError(t, err) ++ require.IsType(t, &multithreaded.State{}, actual.FPVMState) ++ require.Equal(t, VersionMultiThreaded, actual.Version) ++ }) ++} ++ ++func TestLoadStateFromFile(t *testing.T) { ++ t.Run("SinglethreadedFromJSON", func(t *testing.T) { ++ expected, err := NewFromState(singlethreaded.CreateEmptyState()) ++ require.NoError(t, err) ++ ++ path := writeToFile(t, "state.json", expected) ++ actual, err := LoadStateFromFile(path) ++ require.NoError(t, err) ++ require.Equal(t, expected, actual) ++ }) ++ ++ t.Run("SinglethreadedFromBinary", func(t *testing.T) { ++ expected, err := NewFromState(singlethreaded.CreateEmptyState()) ++ require.NoError(t, err) ++ ++ path := writeToFile(t, "state.bin.gz", expected) ++ actual, err := LoadStateFromFile(path) ++ require.NoError(t, err) ++ require.Equal(t, expected, actual) ++ }) ++ ++ t.Run("MultithreadedFromBinary", func(t *testing.T) { ++ expected, err := NewFromState(multithreaded.CreateEmptyState()) ++ require.NoError(t, err) ++ ++ path := writeToFile(t, "state.bin.gz", expected) ++ actual, err := LoadStateFromFile(path) ++ require.NoError(t, err) ++ require.Equal(t, expected, actual) ++ }) ++} ++ ++func TestMultithreadedDoesNotSupportJSON(t *testing.T) { ++ state, err := NewFromState(multithreaded.CreateEmptyState()) ++ require.NoError(t, err) ++ ++ dir := t.TempDir() ++ path := filepath.Join(dir, "test.json") ++ err = serialize.Write(path, state, 0o644) ++ require.ErrorIs(t, err, ErrJsonNotSupported) ++} ++ ++func writeToFile(t *testing.T, filename string, data serialize.Serializable) string { ++ dir := t.TempDir() ++ path := filepath.Join(dir, filename) ++ require.NoError(t, serialize.Write(path, data, 0o644)) ++ return path ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ + (binary file) + +
+
+
diff --git OP/cannon/multicannon/embeds/.gitkeep CELO/cannon/multicannon/embeds/.gitkeep +new file mode 100644 +index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 +Binary files /dev/null and CELO/cannon/multicannon/embeds/.gitkeep differ
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+83
+
-0
+ +
+ +
+
+
diff --git OP/cannon/multicannon/exec.go CELO/cannon/multicannon/exec.go +new file mode 100644 +index 0000000000000000000000000000000000000000..1372c035f5604d264b1324e81153fd9df0ee744b +--- /dev/null ++++ CELO/cannon/multicannon/exec.go +@@ -0,0 +1,83 @@ ++package main ++ ++import ( ++ "context" ++ "embed" ++ "errors" ++ "fmt" ++ "os" ++ "os/exec" ++ "path/filepath" ++ ++ "github.com/ethereum-optimism/optimism/cannon/mipsevm/versions" ++) ++ ++// use the all directive to ensure the .gitkeep file is retained and avoid compiler errors ++ ++//go:embed all:embeds ++var vmFS embed.FS ++ ++const baseDir = "embeds" ++ ++func ExecuteCannon(ctx context.Context, args []string, ver versions.StateVersion) error { ++ switch ver { ++ case versions.VersionSingleThreaded, versions.VersionMultiThreaded: ++ default: ++ return errors.New("unsupported version") ++ } ++ ++ cannonProgramName := vmFilename(ver) ++ cannonProgramBin, err := vmFS.ReadFile(cannonProgramName) ++ if err != nil { ++ return err ++ } ++ cannonProgramPath, err := extractTempFile(filepath.Base(cannonProgramName), cannonProgramBin) ++ if err != nil { ++ fmt.Fprintf(os.Stderr, "Error extracting %s: %v\n", cannonProgramName, err) ++ os.Exit(1) ++ } ++ defer os.Remove(cannonProgramPath) ++ ++ if err := os.Chmod(cannonProgramPath, 0755); err != nil { ++ fmt.Fprintf(os.Stderr, "Error setting execute permission for %s: %v\n", cannonProgramName, err) ++ os.Exit(1) ++ } ++ ++ // nosemgrep: go.lang.security.audit.dangerous-exec-command.dangerous-exec-command ++ cmd := exec.CommandContext(ctx, cannonProgramPath, args...) ++ cmd.Stdout = os.Stdout ++ cmd.Stderr = os.Stderr ++ err = cmd.Start() ++ if err != nil { ++ return fmt.Errorf("unable to launch cannon-impl program: %w", err) ++ } ++ if err := cmd.Wait(); err != nil { ++ var exitErr *exec.ExitError ++ if errors.As(err, &exitErr) { ++ // relay exit code to the parent process ++ os.Exit(exitErr.ExitCode()) ++ } else { ++ return fmt.Errorf("failed to wait for cannon-impl program: %w", err) ++ } ++ } ++ return nil ++} ++ ++func extractTempFile(name string, data []byte) (string, error) { ++ tempDir := os.TempDir() ++ tempFile, err := os.CreateTemp(tempDir, name+"-*") ++ if err != nil { ++ return "", err ++ } ++ defer tempFile.Close() ++ ++ if _, err := tempFile.Write(data); err != nil { ++ return "", err ++ } ++ ++ return tempFile.Name(), nil ++} ++ ++func vmFilename(ver versions.StateVersion) string { ++ return fmt.Sprintf("%s/cannon-%d", baseDir, ver) ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+73
+
-0
+ +
+ +
+
+
diff --git OP/cannon/multicannon/list.go CELO/cannon/multicannon/list.go +new file mode 100644 +index 0000000000000000000000000000000000000000..6e9e8a68b65a90a34d73f5cad68430903ed8e15a +--- /dev/null ++++ CELO/cannon/multicannon/list.go +@@ -0,0 +1,73 @@ ++package main ++ ++import ( ++ "fmt" ++ "math" ++ "strconv" ++ "strings" ++ ++ "github.com/urfave/cli/v2" ++ ++ "github.com/ethereum-optimism/optimism/cannon/mipsevm/versions" ++) ++ ++func List(ctx *cli.Context) error { ++ return list() ++} ++ ++func list() error { ++ fmt.Println("Available cannon versions:") ++ artifacts, err := getArtifacts() ++ if err != nil { ++ return err ++ } ++ for _, art := range artifacts { ++ if art.isValid() { ++ fmt.Printf("filename: %s\tversion: %s (%d)\n", art.filename, versions.StateVersion(art.ver), art.ver) ++ } else { ++ fmt.Printf("filename: %s\tversion: %s\n", art.filename, "unknown") ++ } ++ } ++ return nil ++} ++ ++func getArtifacts() ([]artifact, error) { ++ var ret []artifact ++ entries, err := vmFS.ReadDir(baseDir) ++ if err != nil { ++ return nil, err ++ } ++ for _, entry := range entries { ++ filename := entry.Name() ++ toks := strings.Split(filename, "-") ++ if len(toks) != 2 { ++ continue ++ } ++ if toks[0] != "cannon" { ++ continue ++ } ++ ver, err := strconv.ParseUint(toks[1], 10, 8) ++ if err != nil { ++ ret = append(ret, artifact{filename, math.MaxUint64}) ++ continue ++ } ++ ret = append(ret, artifact{filename, ver}) ++ } ++ return ret, nil ++} ++ ++type artifact struct { ++ filename string ++ ver uint64 ++} ++ ++func (a artifact) isValid() bool { ++ return a.ver != math.MaxUint64 ++} ++ ++var ListCommand = &cli.Command{ ++ Name: "list", ++ Usage: "List embedded Cannon VM implementations", ++ Description: "List embedded Cannon VM implementations", ++ Action: List, ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+31
+
-0
+ +
+ +
+
+
diff --git OP/cannon/multicannon/load_elf.go CELO/cannon/multicannon/load_elf.go +new file mode 100644 +index 0000000000000000000000000000000000000000..cbe1fda463039de255fd7a794e1d5578844b6b5a +--- /dev/null ++++ CELO/cannon/multicannon/load_elf.go +@@ -0,0 +1,31 @@ ++package main ++ ++import ( ++ "fmt" ++ "os" ++ ++ "github.com/ethereum-optimism/optimism/cannon/cmd" ++ "github.com/ethereum-optimism/optimism/cannon/mipsevm/versions" ++ "github.com/urfave/cli/v2" ++) ++ ++func LoadELF(ctx *cli.Context) error { ++ if len(os.Args) == 2 && os.Args[2] == "--help" { ++ if err := list(); err != nil { ++ return err ++ } ++ fmt.Println("use `--type <vm type> --help` to get more detailed help") ++ } ++ ++ typ, err := parseFlag(os.Args[1:], "--type") ++ if err != nil { ++ return err ++ } ++ ver, err := versions.ParseStateVersion(typ) ++ if err != nil { ++ return err ++ } ++ return ExecuteCannon(ctx.Context, os.Args[1:], ver) ++} ++ ++var LoadELFCommand = cmd.CreateLoadELFCommand(LoadELF)
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+46
+
-0
+ +
+ +
+
+
diff --git OP/cannon/multicannon/main.go CELO/cannon/multicannon/main.go +new file mode 100644 +index 0000000000000000000000000000000000000000..e496eba880ba7fc401f462507ec0ae59597f09d8 +--- /dev/null ++++ CELO/cannon/multicannon/main.go +@@ -0,0 +1,46 @@ ++package main ++ ++import ( ++ "context" ++ "errors" ++ "fmt" ++ "os" ++ ++ "github.com/ethereum-optimism/optimism/cannon/multicannon/version" ++ opservice "github.com/ethereum-optimism/optimism/op-service" ++ "github.com/ethereum-optimism/optimism/op-service/ctxinterrupt" ++ "github.com/urfave/cli/v2" ++) ++ ++var ( ++ GitCommit = "" ++ GitDate = "" ++) ++ ++// VersionWithMeta holds the textual version string including the metadata. ++var VersionWithMeta = opservice.FormatVersion(version.Version, GitCommit, GitDate, version.Meta) ++ ++func main() { ++ app := cli.NewApp() ++ app.Name = "multicannon" ++ app.Usage = "MIPS Fault Proof tool" ++ app.Description = "MIPS Fault Proof tool" ++ app.Version = VersionWithMeta ++ app.Commands = []*cli.Command{ ++ LoadELFCommand, ++ WitnessCommand, ++ RunCommand, ++ ListCommand, ++ } ++ ctx := ctxinterrupt.WithCancelOnInterrupt(context.Background()) ++ err := app.RunContext(ctx, os.Args) ++ if err != nil { ++ if errors.Is(err, ctx.Err()) { ++ _, _ = fmt.Fprintf(os.Stderr, "command interrupted") ++ os.Exit(130) ++ } else { ++ _, _ = fmt.Fprintf(os.Stderr, "error: %v", err) ++ os.Exit(1) ++ } ++ } ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+39
+
-0
+ +
+ +
+
+
diff --git OP/cannon/multicannon/run.go CELO/cannon/multicannon/run.go +new file mode 100644 +index 0000000000000000000000000000000000000000..532cf317fb21c15f77b3a0b99ee6cf024ce6b118 +--- /dev/null ++++ CELO/cannon/multicannon/run.go +@@ -0,0 +1,39 @@ ++package main ++ ++import ( ++ "fmt" ++ "os" ++ ++ "github.com/urfave/cli/v2" ++ ++ "github.com/ethereum-optimism/optimism/cannon/mipsevm/versions" ++) ++ ++func Run(ctx *cli.Context) error { ++ fmt.Printf("args %v\n", os.Args[:]) ++ if len(os.Args) == 3 && os.Args[2] == "--help" { ++ if err := list(); err != nil { ++ return err ++ } ++ fmt.Println("use `--input <valid input file> --help` to get more detailed help") ++ } ++ ++ inputPath, err := parsePathFlag(os.Args[1:], "--input") ++ if err != nil { ++ return err ++ } ++ version, err := versions.DetectVersion(inputPath) ++ if err != nil { ++ return err ++ } ++ return ExecuteCannon(ctx.Context, os.Args[1:], version) ++} ++ ++// var RunCommand = cmd.CreateRunCommand(Run) ++var RunCommand = &cli.Command{ ++ Name: "run", ++ Usage: "Run VM step(s) and generate proof data to replicate onchain.", ++ Description: "Run VM step(s) and generate proof data to replicate onchain. See flags to match when to output a proof, a snapshot, or to stop early.", ++ Action: Run, ++ SkipFlagParsing: true, ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+37
+
-0
+ +
+ +
+
+
diff --git OP/cannon/multicannon/util.go CELO/cannon/multicannon/util.go +new file mode 100644 +index 0000000000000000000000000000000000000000..ea484c6ce2d2f51f12b585f43fb2231f6b93f165 +--- /dev/null ++++ CELO/cannon/multicannon/util.go +@@ -0,0 +1,37 @@ ++package main ++ ++import ( ++ "errors" ++ "fmt" ++ "os" ++ "strings" ++) ++ ++// parseFlag reads a flag argument. It assumes the flag has an argument ++func parseFlag(args []string, flag string) (string, error) { ++ for i := 0; i < len(args); i++ { ++ arg := args[i] ++ if strings.HasPrefix(arg, flag) { ++ toks := strings.Split(arg, "=") ++ if len(toks) == 2 { ++ return toks[1], nil ++ } else if i+1 == len(args) { ++ return "", fmt.Errorf("flag needs an argument: %s", flag) ++ } else { ++ return args[i+1], nil ++ } ++ } ++ } ++ return "", fmt.Errorf("missing flag: %s", flag) ++} ++ ++func parsePathFlag(args []string, flag string) (string, error) { ++ path, err := parseFlag(args, flag) ++ if err != nil { ++ return "", err ++ } ++ if _, err := os.Stat(path); errors.Is(err, os.ErrNotExist) { ++ return "", fmt.Errorf("file `%s` does not exist", path) ++ } ++ return path, nil ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+68
+
-0
+ +
+ +
+
+
diff --git OP/cannon/multicannon/util_test.go CELO/cannon/multicannon/util_test.go +new file mode 100644 +index 0000000000000000000000000000000000000000..9997b1315a8f1c5077577b20c22acf5b68f0370c +--- /dev/null ++++ CELO/cannon/multicannon/util_test.go +@@ -0,0 +1,68 @@ ++package main ++ ++import ( ++ "strings" ++ "testing" ++ ++ "github.com/stretchr/testify/require" ++) ++ ++func TestParseFlag(t *testing.T) { ++ cases := []struct { ++ name string ++ args string ++ flag string ++ expect string ++ expectErr string ++ }{ ++ { ++ name: "bar=one", ++ args: "--foo --bar=one --baz", ++ flag: "--bar", ++ expect: "one", ++ }, ++ { ++ name: "bar one", ++ args: "--foo --bar one --baz", ++ flag: "--bar", ++ expect: "one", ++ }, ++ { ++ name: "bar one first flag", ++ args: "--bar one --foo two --baz three", ++ flag: "--bar", ++ expect: "one", ++ }, ++ { ++ name: "bar one last flag", ++ args: "--foo --baz --bar one", ++ flag: "--bar", ++ expect: "one", ++ }, ++ { ++ name: "non-existent flag", ++ args: "--foo one", ++ flag: "--bar", ++ expectErr: "missing flag", ++ }, ++ { ++ name: "empty args", ++ args: "", ++ flag: "--foo", ++ expectErr: "missing flag", ++ }, ++ } ++ for _, tt := range cases { ++ tt := tt ++ t.Run(tt.name, func(t *testing.T) { ++ args := strings.Split(tt.args, " ") ++ result, err := parseFlag(args, tt.flag) ++ if tt.expectErr != "" { ++ require.ErrorContains(t, err, tt.expectErr) ++ } else { ++ require.NoError(t, err) ++ require.Equal(t, tt.expect, result) ++ } ++ }) ++ } ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+6
+
-0
+ +
+ +
+
+
diff --git OP/cannon/multicannon/version/version.go CELO/cannon/multicannon/version/version.go +new file mode 100644 +index 0000000000000000000000000000000000000000..2456f656d45c15c1df43d737ad62344ff5d84081 +--- /dev/null ++++ CELO/cannon/multicannon/version/version.go +@@ -0,0 +1,6 @@ ++package version ++ ++var ( ++ Version = "v0.0.0" ++ Meta = "dev" ++)
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+32
+
-0
+ +
+ +
+
+
diff --git OP/cannon/multicannon/witness.go CELO/cannon/multicannon/witness.go +new file mode 100644 +index 0000000000000000000000000000000000000000..077d0d3f1aed58e7809ffa2caa15f10799e1b991 +--- /dev/null ++++ CELO/cannon/multicannon/witness.go +@@ -0,0 +1,32 @@ ++package main ++ ++import ( ++ "fmt" ++ "os" ++ ++ "github.com/urfave/cli/v2" ++ ++ "github.com/ethereum-optimism/optimism/cannon/cmd" ++ "github.com/ethereum-optimism/optimism/cannon/mipsevm/versions" ++) ++ ++func Witness(ctx *cli.Context) error { ++ if len(os.Args) == 3 && os.Args[2] == "--help" { ++ if err := list(); err != nil { ++ return err ++ } ++ fmt.Println("use `--input <valid input file> --help` to get more detailed help") ++ } ++ ++ inputPath, err := parsePathFlag(os.Args[1:], "--input") ++ if err != nil { ++ return err ++ } ++ version, err := versions.DetectVersion(inputPath) ++ if err != nil { ++ return err ++ } ++ return ExecuteCannon(ctx.Context, os.Args[1:], version) ++} ++ ++var WitnessCommand = cmd.CreateWitnessCommand(Witness)
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+64
+
-0
+ +
+ +
+
+
diff --git OP/cannon/serialize/binary.go CELO/cannon/serialize/binary.go +new file mode 100644 +index 0000000000000000000000000000000000000000..aeaf14c5b4930795f1f2e9bc5ede8cbee7ae6d04 +--- /dev/null ++++ CELO/cannon/serialize/binary.go +@@ -0,0 +1,64 @@ ++package serialize ++ ++import ( ++ "errors" ++ "fmt" ++ "io" ++ "reflect" ++ ++ "github.com/ethereum-optimism/optimism/op-service/ioutil" ++) ++ ++// Deserializable defines functionality for a type that may be deserialized from raw bytes. ++type Deserializable interface { ++ // Deserialize decodes raw bytes into the type. ++ Deserialize(in io.Reader) error ++} ++ ++// Serializable defines functionality for a type that may be serialized to raw bytes. ++type Serializable interface { ++ // Serialize encodes the type as raw bytes. ++ Serialize(out io.Writer) error ++} ++ ++func LoadSerializedBinary[X any](inputPath string) (*X, error) { ++ if inputPath == "" { ++ return nil, errors.New("no path specified") ++ } ++ var f io.ReadCloser ++ f, err := ioutil.OpenDecompressed(inputPath) ++ if err != nil { ++ return nil, fmt.Errorf("failed to open file %q: %w", inputPath, err) ++ } ++ defer f.Close() ++ ++ var x X ++ serializable, ok := reflect.ValueOf(&x).Interface().(Deserializable) ++ if !ok { ++ return nil, fmt.Errorf("%T is not a Serializable", x) ++ } ++ err = serializable.Deserialize(f) ++ if err != nil { ++ return nil, err ++ } ++ return &x, nil ++} ++ ++func WriteSerializedBinary(value Serializable, target ioutil.OutputTarget) error { ++ out, closer, abort, err := target() ++ if err != nil { ++ return err ++ } ++ if out == nil { ++ return nil // Nothing to write to so skip generating content entirely ++ } ++ defer abort() ++ err = value.Serialize(out) ++ if err != nil { ++ return fmt.Errorf("failed to write binary: %w", err) ++ } ++ if err := closer.Close(); err != nil { ++ return fmt.Errorf("failed to finish write: %w", err) ++ } ++ return nil ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+94
+
-0
+ +
+ +
+
+
diff --git OP/cannon/serialize/binary_test.go CELO/cannon/serialize/binary_test.go +new file mode 100644 +index 0000000000000000000000000000000000000000..95700b537c4056300a311fc19e66ad44a39cd0b3 +--- /dev/null ++++ CELO/cannon/serialize/binary_test.go +@@ -0,0 +1,94 @@ ++package serialize ++ ++import ( ++ "encoding/binary" ++ "io" ++ "os" ++ "path/filepath" ++ "testing" ++ ++ "github.com/ethereum-optimism/optimism/op-service/ioutil" ++ "github.com/stretchr/testify/require" ++) ++ ++func TestRoundTripBinary(t *testing.T) { ++ dir := t.TempDir() ++ file := filepath.Join(dir, "test.bin") ++ data := &serializableTestData{A: []byte{0xde, 0xad}, B: 3} ++ err := WriteSerializedBinary(data, ioutil.ToAtomicFile(file, 0644)) ++ require.NoError(t, err) ++ ++ hasGzip, err := hasGzipHeader(file) ++ require.NoError(t, err) ++ require.False(t, hasGzip) ++ ++ result, err := LoadSerializedBinary[serializableTestData](file) ++ require.NoError(t, err) ++ require.EqualValues(t, data, result) ++} ++ ++func TestRoundTripBinaryWithGzip(t *testing.T) { ++ dir := t.TempDir() ++ file := filepath.Join(dir, "test.bin.gz") ++ data := &serializableTestData{A: []byte{0xde, 0xad}, B: 3} ++ err := WriteSerializedBinary(data, ioutil.ToAtomicFile(file, 0644)) ++ require.NoError(t, err) ++ ++ hasGzip, err := hasGzipHeader(file) ++ require.NoError(t, err) ++ require.True(t, hasGzip) ++ ++ result, err := LoadSerializedBinary[serializableTestData](file) ++ require.NoError(t, err) ++ require.EqualValues(t, data, result) ++} ++ ++func hasGzipHeader(filename string) (bool, error) { ++ file, err := os.Open(filename) ++ if err != nil { ++ return false, err ++ } ++ defer file.Close() ++ ++ header := make([]byte, 2) ++ _, err = file.Read(header) ++ if err != nil { ++ return false, err ++ } ++ ++ // Gzip header magic numbers: 1F 8B ++ return header[0] == 0x1F && header[1] == 0x8B, nil ++} ++ ++type serializableTestData struct { ++ A []byte ++ B uint8 ++} ++ ++func (s *serializableTestData) Serialize(w io.Writer) error { ++ if err := binary.Write(w, binary.BigEndian, uint64(len(s.A))); err != nil { ++ return err ++ } ++ if _, err := w.Write(s.A); err != nil { ++ return err ++ } ++ if err := binary.Write(w, binary.BigEndian, s.B); err != nil { ++ return err ++ } ++ return nil ++} ++ ++func (s *serializableTestData) Deserialize(in io.Reader) error { ++ var lenA uint64 ++ if err := binary.Read(in, binary.BigEndian, &lenA); err != nil { ++ return err ++ } ++ s.A = make([]byte, lenA) ++ if _, err := io.ReadFull(in, s.A); err != nil { ++ return err ++ } ++ if err := binary.Read(in, binary.BigEndian, &s.B); err != nil { ++ return err ++ } ++ return nil ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+20
+
-0
+ +
+ +
+
+
diff --git OP/cannon/serialize/detect.go CELO/cannon/serialize/detect.go +new file mode 100644 +index 0000000000000000000000000000000000000000..13cf3aef849ea738040133ec694a6bccdb54d0b2 +--- /dev/null ++++ CELO/cannon/serialize/detect.go +@@ -0,0 +1,20 @@ ++package serialize ++ ++import ( ++ "os" ++ "strings" ++ ++ "github.com/ethereum-optimism/optimism/op-service/ioutil" ++ "github.com/ethereum-optimism/optimism/op-service/jsonutil" ++) ++ ++func Write[X Serializable](outputPath string, x X, perm os.FileMode) error { ++ if IsBinaryFile(outputPath) { ++ return WriteSerializedBinary(x, ioutil.ToStdOutOrFileOrNoop(outputPath, perm)) ++ } ++ return jsonutil.WriteJSON[X](x, ioutil.ToStdOutOrFileOrNoop(outputPath, perm)) ++} ++ ++func IsBinaryFile(path string) bool { ++ return strings.HasSuffix(path, ".bin") || strings.HasSuffix(path, ".bin.gz") ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+60
+
-0
+ +
+ +
+
+
diff --git OP/cannon/serialize/detect_test.go CELO/cannon/serialize/detect_test.go +new file mode 100644 +index 0000000000000000000000000000000000000000..22ac747a10447a4ff1984047a3b70889acabe719 +--- /dev/null ++++ CELO/cannon/serialize/detect_test.go +@@ -0,0 +1,60 @@ ++package serialize ++ ++import ( ++ "io" ++ "path/filepath" ++ "testing" ++ ++ "github.com/ethereum-optimism/optimism/op-service/ioutil" ++ "github.com/ethereum-optimism/optimism/op-service/jsonutil" ++ "github.com/stretchr/testify/require" ++) ++ ++func TestRoundtrip(t *testing.T) { ++ tests := []struct { ++ filename string ++ expectJSON bool ++ expectGzip bool ++ }{ ++ {filename: "test.json", expectJSON: true, expectGzip: false}, ++ {filename: "test.json.gz", expectJSON: true, expectGzip: true}, ++ {filename: "test.foo", expectJSON: true, expectGzip: false}, ++ {filename: "test.foo.gz", expectJSON: true, expectGzip: true}, ++ {filename: "test.bin", expectJSON: false, expectGzip: false}, ++ {filename: "test.bin.gz", expectJSON: false, expectGzip: true}, ++ } ++ ++ for _, test := range tests { ++ test := test ++ t.Run(test.filename, func(t *testing.T) { ++ path := filepath.Join(t.TempDir(), test.filename) ++ ++ data := &serializableTestData{A: []byte{0xde, 0xad}, B: 3} ++ err := Write[*serializableTestData](path, data, 0644) ++ require.NoError(t, err) ++ ++ hasGzip, err := hasGzipHeader(path) ++ require.NoError(t, err) ++ require.Equal(t, test.expectGzip, hasGzip) ++ ++ decompressed, err := ioutil.OpenDecompressed(path) ++ require.NoError(t, err) ++ defer decompressed.Close() ++ start := make([]byte, 1) ++ _, err = io.ReadFull(decompressed, start) ++ require.NoError(t, err) ++ var load func(path string) (*serializableTestData, error) ++ if test.expectJSON { ++ load = jsonutil.LoadJSON[serializableTestData] ++ require.Equal(t, "{", string(start)) ++ } else { ++ load = LoadSerializedBinary[serializableTestData] ++ require.NotEqual(t, "{", string(start)) ++ } ++ ++ result, err := load(path) ++ require.NoError(t, err) ++ require.EqualValues(t, data, result) ++ }) ++ } ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+60
+
-0
+ +
+ +
+
+
diff --git OP/cannon/serialize/reader.go CELO/cannon/serialize/reader.go +new file mode 100644 +index 0000000000000000000000000000000000000000..53f4440659a4161d67925753cded5b4061cc5d9b +--- /dev/null ++++ CELO/cannon/serialize/reader.go +@@ -0,0 +1,60 @@ ++package serialize ++ ++import ( ++ "encoding/binary" ++ "fmt" ++ "io" ++ ++ "github.com/ethereum/go-ethereum/common" ++) ++ ++// BinaryReader provides methods to decode content written by BinaryWriter. ++type BinaryReader struct { ++ in io.Reader ++} ++ ++func NewBinaryReader(in io.Reader) *BinaryReader { ++ return &BinaryReader{in: in} ++} ++ ++func (r *BinaryReader) ReadUInt(target any) error { ++ return binary.Read(r.in, binary.BigEndian, target) ++} ++ ++func (r *BinaryReader) ReadHash(target *common.Hash) error { ++ _, err := io.ReadFull(r.in, target[:]) ++ return err ++} ++ ++func (r *BinaryReader) ReadBool(target *bool) error { ++ var v uint8 ++ if err := r.ReadUInt(&v); err != nil { ++ return err ++ } ++ switch v { ++ case 0: ++ *target = false ++ case 1: ++ *target = true ++ default: ++ return fmt.Errorf("invalid boolean value: %v", v) ++ } ++ return nil ++} ++ ++func (r *BinaryReader) ReadBytes(target *[]byte) error { ++ var size uint32 ++ if err := r.ReadUInt(&size); err != nil { ++ return err ++ } ++ if size == 0 { ++ *target = nil ++ return nil ++ } ++ data := make([]byte, size) ++ if _, err := io.ReadFull(r.in, data); err != nil { ++ return err ++ } ++ *target = data ++ return nil ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+48
+
-0
+ +
+ +
+
+
diff --git OP/cannon/serialize/reader_test.go CELO/cannon/serialize/reader_test.go +new file mode 100644 +index 0000000000000000000000000000000000000000..0d6b8678c59264ff4fa9a2b45b19934ed00aed02 +--- /dev/null ++++ CELO/cannon/serialize/reader_test.go +@@ -0,0 +1,48 @@ ++package serialize ++ ++import ( ++ "bytes" ++ "testing" ++ ++ "github.com/ethereum/go-ethereum/common" ++ "github.com/stretchr/testify/require" ++) ++ ++func TestRoundTripWithReader(t *testing.T) { ++ // Test that reader can read the data written by BinaryWriter. ++ // The writer tests check that the generated data is what is expected, so simply check that the reader correctly ++ // parses a range of data here rather than duplicating the expected binary serialization. ++ buf := new(bytes.Buffer) ++ out := NewBinaryWriter(buf) ++ require.NoError(t, out.WriteBool(true)) ++ require.NoError(t, out.WriteBool(false)) ++ require.NoError(t, out.WriteUInt(uint8(5))) ++ require.NoError(t, out.WriteUInt(uint32(76))) ++ require.NoError(t, out.WriteUInt(uint64(24824424))) ++ expectedHash := common.HexToHash("0x5a8f75b8e1c1529d1d1c596464d17b99763604f4c00b280436fc0dffacc60efd") ++ require.NoError(t, out.WriteHash(expectedHash)) ++ expectedBytes := []byte{1, 2, 3, 4, 5, 6, 7, 8, 9} ++ require.NoError(t, out.WriteBytes(expectedBytes)) ++ ++ in := NewBinaryReader(buf) ++ var b bool ++ require.NoError(t, in.ReadBool(&b)) ++ require.True(t, b) ++ require.NoError(t, in.ReadBool(&b)) ++ require.False(t, b) ++ var vUInt8 uint8 ++ require.NoError(t, in.ReadUInt(&vUInt8)) ++ require.Equal(t, uint8(5), vUInt8) ++ var vUInt32 uint32 ++ require.NoError(t, in.ReadUInt(&vUInt32)) ++ require.Equal(t, uint32(76), vUInt32) ++ var vUInt64 uint64 ++ require.NoError(t, in.ReadUInt(&vUInt64)) ++ require.Equal(t, uint64(24824424), vUInt64) ++ var hash common.Hash ++ require.NoError(t, in.ReadHash(&hash)) ++ require.Equal(t, expectedHash, hash) ++ var data []byte ++ require.NoError(t, in.ReadBytes(&data)) ++ require.Equal(t, expectedBytes, data) ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+44
+
-0
+ +
+ +
+
+
diff --git OP/cannon/serialize/writer.go CELO/cannon/serialize/writer.go +new file mode 100644 +index 0000000000000000000000000000000000000000..a8790115a11c3c247d121ce0093b49191c86644e +--- /dev/null ++++ CELO/cannon/serialize/writer.go +@@ -0,0 +1,44 @@ ++package serialize ++ ++import ( ++ "encoding/binary" ++ "io" ++ ++ "github.com/ethereum/go-ethereum/common" ++) ++ ++// BinaryWriter writes a simple binary format which can be read again using BinaryReader. ++// The format is a simple concatenation of values, with prefixed length for variable length items. ++// All numbers are encoded using big endian. ++type BinaryWriter struct { ++ out io.Writer ++} ++ ++func NewBinaryWriter(out io.Writer) *BinaryWriter { ++ return &BinaryWriter{out: out} ++} ++ ++func (w *BinaryWriter) WriteUInt(v any) error { ++ return binary.Write(w.out, binary.BigEndian, v) ++} ++ ++func (w *BinaryWriter) WriteHash(v common.Hash) error { ++ _, err := w.out.Write(v[:]) ++ return err ++} ++ ++func (w *BinaryWriter) WriteBool(v bool) error { ++ if v { ++ return w.WriteUInt(uint8(1)) ++ } else { ++ return w.WriteUInt(uint8(0)) ++ } ++} ++ ++func (w *BinaryWriter) WriteBytes(v []byte) error { ++ if err := w.WriteUInt(uint32(len(v))); err != nil { ++ return err ++ } ++ _, err := w.out.Write(v) ++ return err ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+102
+
-0
+ +
+ +
+
+
diff --git OP/cannon/serialize/writer_test.go CELO/cannon/serialize/writer_test.go +new file mode 100644 +index 0000000000000000000000000000000000000000..d37b18da094f2941184276f4706a744bdbd4f80f +--- /dev/null ++++ CELO/cannon/serialize/writer_test.go +@@ -0,0 +1,102 @@ ++package serialize ++ ++import ( ++ "bytes" ++ "fmt" ++ "math" ++ "testing" ++ ++ "github.com/ethereum/go-ethereum/common" ++ "github.com/stretchr/testify/require" ++) ++ ++func TestUInt(t *testing.T) { ++ tests := []struct { ++ name string ++ val any ++ expected []byte ++ }{ ++ {name: "uint8-zero", val: uint8(0), expected: []byte{0}}, ++ {name: "uint8-one", val: uint8(1), expected: []byte{1}}, ++ {name: "uint8-big", val: uint8(156), expected: []byte{156}}, ++ {name: "uint8-max", val: uint8(math.MaxUint8), expected: []byte{255}}, ++ ++ {name: "uint16-zero", val: uint16(0), expected: []byte{0, 0}}, ++ {name: "uint16-one", val: uint16(1), expected: []byte{0, 1}}, ++ {name: "uint16-big", val: uint16(1283), expected: []byte{5, 3}}, ++ {name: "uint16-max", val: uint16(math.MaxUint16), expected: []byte{255, 255}}, ++ ++ {name: "uint32-zero", val: uint32(0), expected: []byte{0, 0, 0, 0}}, ++ {name: "uint32-one", val: uint32(1), expected: []byte{0, 0, 0, 1}}, ++ {name: "uint32-big", val: uint32(1283424245), expected: []byte{0x4c, 0x7f, 0x7f, 0xf5}}, ++ {name: "uint32-max", val: uint32(math.MaxUint32), expected: []byte{255, 255, 255, 255}}, ++ ++ {name: "uint64-zero", val: uint64(0), expected: []byte{0, 0, 0, 0, 0, 0, 0, 0}}, ++ {name: "uint64-one", val: uint64(1), expected: []byte{0, 0, 0, 0, 0, 0, 0, 1}}, ++ {name: "uint64-big", val: uint64(1283424245242429284), expected: []byte{0x11, 0xcf, 0xa3, 0x8d, 0x19, 0xcc, 0x7f, 0x64}}, ++ {name: "uint64-max", val: uint64(math.MaxUint64), expected: []byte{255, 255, 255, 255, 255, 255, 255, 255}}, ++ } ++ ++ for _, test := range tests { ++ test := test ++ t.Run(test.name, func(t *testing.T) { ++ out := new(bytes.Buffer) ++ bout := NewBinaryWriter(out) ++ require.NoError(t, bout.WriteUInt(test.val)) ++ result := out.Bytes() ++ require.Equal(t, test.expected, result) ++ }) ++ } ++} ++ ++func TestWriteHash(t *testing.T) { ++ out := new(bytes.Buffer) ++ bout := NewBinaryWriter(out) ++ hash := common.HexToHash("0x5a8f75b8e1c1529d1d1c596464d17b99763604f4c00b280436fc0dffacc60efd") ++ require.NoError(t, bout.WriteHash(hash)) ++ ++ result := out.Bytes() ++ require.Equal(t, hash[:], result) ++} ++ ++func TestWriteBool(t *testing.T) { ++ for _, val := range []bool{true, false} { ++ val := val ++ t.Run(fmt.Sprintf("%t", val), func(t *testing.T) { ++ out := new(bytes.Buffer) ++ bout := NewBinaryWriter(out) ++ require.NoError(t, bout.WriteBool(val)) ++ ++ result := out.Bytes() ++ require.Len(t, result, 1) ++ if val { ++ require.Equal(t, result[0], uint8(1)) ++ } else { ++ require.Equal(t, result[0], uint8(0)) ++ } ++ }) ++ } ++} ++ ++func TestWriteBytes(t *testing.T) { ++ tests := []struct { ++ name string ++ val []byte ++ expected []byte ++ }{ ++ {name: "nil", val: nil, expected: []byte{0, 0, 0, 0}}, ++ {name: "empty", val: []byte{}, expected: []byte{0, 0, 0, 0}}, ++ {name: "non-empty", val: []byte{1, 2, 3, 4, 5}, expected: []byte{0, 0, 0, 5, 1, 2, 3, 4, 5}}, ++ } ++ for _, test := range tests { ++ test := test ++ t.Run(test.name, func(t *testing.T) { ++ out := new(bytes.Buffer) ++ bout := NewBinaryWriter(out) ++ require.NoError(t, bout.WriteBytes(test.val)) ++ ++ result := out.Bytes() ++ require.Equal(t, test.expected, result) ++ }) ++ } ++}
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+2
+
-2
+ +
+ +
+
+
diff --git OP/cannon/testdata/example/alloc/go.mod CELO/cannon/testdata/example/alloc/go.mod +index 4068cbf1ddf61c5b41e5c435271cdb6e45560b42..d4d3c23faf2d96b3f5615b7102eb810aca9018c5 100644 +--- OP/cannon/testdata/example/alloc/go.mod ++++ CELO/cannon/testdata/example/alloc/go.mod +@@ -7,8 +7,8 @@ + require github.com/ethereum-optimism/optimism v0.0.0 +  + require ( +- golang.org/x/crypto v0.26.0 // indirect +- golang.org/x/sys v0.24.0 // indirect ++ golang.org/x/crypto v0.27.0 // indirect ++ golang.org/x/sys v0.25.0 // indirect + ) +  + replace github.com/ethereum-optimism/optimism v0.0.0 => ../../../..
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+4
+
-4
+ +
+ +
+
+
diff --git OP/cannon/testdata/example/alloc/go.sum CELO/cannon/testdata/example/alloc/go.sum +index 7fb6c4a685ae2ffeab07c5650c070bbf09c56097..c319c56516338d96350bc8b0e10707b4b2e76114 100644 +--- OP/cannon/testdata/example/alloc/go.sum ++++ CELO/cannon/testdata/example/alloc/go.sum +@@ -4,9 +4,9 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= + github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= + github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +-golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= +-golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= +-golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= +-golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= ++golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= ++golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= ++golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= ++golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= + gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= + gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+11
+
-4
+ +
+ +
+
+
diff --git OP/cannon/testdata/example/alloc/main.go CELO/cannon/testdata/example/alloc/main.go +index 41bc67000d2bbcb30e085430ea082a981585d005..3c7af2f165f504da2b2e172f9648005ef619e14d 100644 +--- OP/cannon/testdata/example/alloc/main.go ++++ CELO/cannon/testdata/example/alloc/main.go +@@ -12,20 +12,27 @@ func main() { + var mem []byte + po := preimage.NewOracleClient(preimage.ClientPreimageChannel()) + numAllocs := binary.LittleEndian.Uint64(po.Get(preimage.LocalIndexKey(0))) ++ allocSize := binary.LittleEndian.Uint64(po.Get(preimage.LocalIndexKey(1))) +  +- fmt.Printf("alloc program. numAllocs=%d\n", numAllocs) ++ fmt.Printf("alloc program. numAllocs=%d allocSize=%d\n", numAllocs, allocSize) + var alloc int + for i := 0; i < int(numAllocs); i++ { +- mem = make([]byte, 32*1024*1024) ++ mem = make([]byte, allocSize) + alloc += len(mem) + // touch a couple pages to prevent the runtime from overcommitting memory + for j := 0; j < len(mem); j += 1024 { + mem[j] = 0xFF + } +- fmt.Printf("allocated %d bytes\n", alloc) ++ printGCStats(alloc) + } +  ++ fmt.Println("alloc program exit") ++ printGCStats(alloc) ++} ++ ++func printGCStats(alloc int) { + var m runtime.MemStats + runtime.ReadMemStats(&m) +- fmt.Printf("alloc program exit. memstats: heap_alloc=%d frees=%d mallocs=%d\n", m.HeapAlloc, m.Frees, m.Mallocs) ++ fmt.Printf("allocated %d bytes. memstats: heap_alloc=%d next_gc=%d frees=%d mallocs=%d num_gc=%d\n", ++ alloc, m.HeapAlloc, m.NextGC, m.Frees, m.Mallocs, m.NumGC) + }
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+2
+
-2
+ +
+ +
+
+
diff --git OP/cannon/testdata/example/claim/go.mod CELO/cannon/testdata/example/claim/go.mod +index 8b88d2cf5c32e257ab1eb00f865e36bc9ad24464..c70d9906f06ca87c8e99e32757cfa10e93712168 100644 +--- OP/cannon/testdata/example/claim/go.mod ++++ CELO/cannon/testdata/example/claim/go.mod +@@ -7,8 +7,8 @@ + require github.com/ethereum-optimism/optimism v0.0.0 +  + require ( +- golang.org/x/crypto v0.26.0 // indirect +- golang.org/x/sys v0.24.0 // indirect ++ golang.org/x/crypto v0.27.0 // indirect ++ golang.org/x/sys v0.25.0 // indirect + ) +  + replace github.com/ethereum-optimism/optimism v0.0.0 => ../../../..
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+4
+
-4
+ +
+ +
+
+
diff --git OP/cannon/testdata/example/claim/go.sum CELO/cannon/testdata/example/claim/go.sum +index 7fb6c4a685ae2ffeab07c5650c070bbf09c56097..c319c56516338d96350bc8b0e10707b4b2e76114 100644 +--- OP/cannon/testdata/example/claim/go.sum ++++ CELO/cannon/testdata/example/claim/go.sum +@@ -4,9 +4,9 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= + github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= + github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +-golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= +-golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= +-golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= +-golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= ++golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= ++golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= ++golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= ++golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= + gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= + gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+29
+
-0
+ +
+ +
+
+
diff --git OP/docker-bake.hcl CELO/docker-bake.hcl +index 47509616416ab24f2c604c23abc5096c7277c0bb..b0949594874580765d0264bd4d7f7c64997c275d 100644 +--- OP/docker-bake.hcl ++++ CELO/docker-bake.hcl +@@ -69,6 +69,9 @@ variable "OP_CONDUCTOR_VERSION" { + default = "${GIT_VERSION}" + } +  ++variable "OP_DEPLOYER_VERSION" { ++ default = "${GIT_VERSION}" ++} +  + target "op-node" { + dockerfile = "ops/docker/op-stack-go/Dockerfile" +@@ -199,6 +202,19 @@ platforms = split(",", PLATFORMS) + tags = [for tag in split(",", IMAGE_TAGS) : "${REGISTRY}/${REPOSITORY}/cannon:${tag}"] + } +  ++target "proofs-tools" { ++ dockerfile = "./ops/docker/proofs-tools/Dockerfile" ++ context = "." ++ args = { ++ CHALLENGER_VERSION="90700b9bb37080961747420882b14578577d47cc" ++ KONA_VERSION="kona-client-v0.1.0-alpha.3" ++ ASTERISC_VERSION="v1.0.2" ++ } ++ target="proofs-tools" ++ platforms = split(",", PLATFORMS) ++ tags = [for tag in split(",", IMAGE_TAGS) : "${REGISTRY}/${REPOSITORY}/proofs-tools:${tag}"] ++} ++ + target "ci-builder" { + dockerfile = "./ops/docker/ci-builder/Dockerfile" + context = "." +@@ -223,3 +239,16 @@ # See comment in Dockerfile.packages for why we only build for linux/amd64. + platforms = ["linux/amd64"] + tags = [for tag in split(",", IMAGE_TAGS) : "${REGISTRY}/${REPOSITORY}/contracts-bedrock:${tag}"] + } ++ ++target "op-deployer" { ++ dockerfile = "ops/docker/op-stack-go/Dockerfile" ++ context = "." ++ args = { ++ GIT_COMMIT = "${GIT_COMMIT}" ++ GIT_DATE = "${GIT_DATE}" ++ OP_DEPLOYER_VERSION = "${OP_DEPLOYER_VERSION}" ++ } ++ target = "op-deployer-target" ++ platforms = split(",", PLATFORMS) ++ tags = [for tag in split(",", IMAGE_TAGS) : "${REGISTRY}/${REPOSITORY}/op-deployer:${tag}"] ++}
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+0
+
-1
+ +
+ +
+
+
diff --git OP/docs/README.md CELO/docs/README.md +index da82e0a7f6aa645d5f8d15bc934a3667266382c6..cabb2506b084fe9965108cd75e7680cc73e76a6d 100644 +--- OP/docs/README.md ++++ CELO/docs/README.md +@@ -6,4 +6,3 @@ The directory layout is divided into the following sub-directories. +  + - [`postmortems/`](./postmortems/): Timestamped post-mortem documents. + - [`security-reviews`](./security-reviews/): Audit summaries and other security review documents. +-- [`fault-proof-alpha`](./fault-proof-alpha): Information on the alpha version of the fault proof system.
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+5
+
-0
+ +
+ +
+
+
diff --git OP/funding.json CELO/funding.json +new file mode 100644 +index 0000000000000000000000000000000000000000..a6b4c73180af2b2b92704b87bb978936a832cbbe +--- /dev/null ++++ CELO/funding.json +@@ -0,0 +1,5 @@ ++{ ++ "opRetro": { ++ "projectId": "0x839f24397fbcd261408f074eaf35aee98f500f5185a27e6c470c5307e967c017" + } +}
@@ -23314,9 +103605,1923 @@
+ +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+42
+
-14
+ +
+ +
+
+
diff --git OP/op-alt-da/cli.go CELO/op-alt-da/cli.go +index e931707b67f50f0e0fbe3c66a6980e59465bed1c..30ce2168f5702f2945597c90f4418f8af0abdb65 100644 +--- OP/op-alt-da/cli.go ++++ CELO/op-alt-da/cli.go +@@ -3,15 +3,19 @@ + import ( + "fmt" + "net/url" ++ "time" +  + "github.com/urfave/cli/v2" + ) +  + var ( +- EnabledFlagName = altDAFlags("enabled") +- DaServerAddressFlagName = altDAFlags("da-server") +- VerifyOnReadFlagName = altDAFlags("verify-on-read") +- DaServiceFlag = altDAFlags("da-service") ++ EnabledFlagName = altDAFlags("enabled") ++ DaServerAddressFlagName = altDAFlags("da-server") ++ VerifyOnReadFlagName = altDAFlags("verify-on-read") ++ DaServiceFlagName = altDAFlags("da-service") ++ PutTimeoutFlagName = altDAFlags("put-timeout") ++ GetTimeoutFlagName = altDAFlags("get-timeout") ++ MaxConcurrentRequestsFlagName = altDAFlags("max-concurrent-da-requests") + ) +  + // altDAFlags returns the flag names for altDA +@@ -46,20 +50,41 @@ EnvVars: altDAEnvs(envPrefix, "VERIFY_ON_READ"), + Category: category, + }, + &cli.BoolFlag{ +- Name: DaServiceFlag, ++ Name: DaServiceFlagName, + Usage: "Use DA service type where commitments are generated by Alt-DA server", + Value: false, + EnvVars: altDAEnvs(envPrefix, "DA_SERVICE"), + Category: category, + }, ++ &cli.DurationFlag{ ++ Name: PutTimeoutFlagName, ++ Usage: "Timeout for put requests. 0 means no timeout.", ++ Value: time.Duration(0), ++ EnvVars: altDAEnvs(envPrefix, "PUT_TIMEOUT"), ++ }, ++ &cli.DurationFlag{ ++ Name: GetTimeoutFlagName, ++ Usage: "Timeout for get requests. 0 means no timeout.", ++ Value: time.Duration(0), ++ EnvVars: altDAEnvs(envPrefix, "GET_TIMEOUT"), ++ }, ++ &cli.Uint64Flag{ ++ Name: MaxConcurrentRequestsFlagName, ++ Usage: "Maximum number of concurrent requests to the DA server", ++ Value: 1, ++ EnvVars: altDAEnvs(envPrefix, "MAX_CONCURRENT_DA_REQUESTS"), ++ }, + } + } +  + type CLIConfig struct { +- Enabled bool +- DAServerURL string +- VerifyOnRead bool +- GenericDA bool ++ Enabled bool ++ DAServerURL string ++ VerifyOnRead bool ++ GenericDA bool ++ PutTimeout time.Duration ++ GetTimeout time.Duration ++ MaxConcurrentRequests uint64 + } +  + func (c CLIConfig) Check() error { +@@ -75,14 +100,17 @@ return nil + } +  + func (c CLIConfig) NewDAClient() *DAClient { +- return &DAClient{url: c.DAServerURL, verify: c.VerifyOnRead, precompute: !c.GenericDA} ++ return &DAClient{url: c.DAServerURL, verify: c.VerifyOnRead, precompute: !c.GenericDA, getTimeout: c.GetTimeout, putTimeout: c.PutTimeout} + } +  + func ReadCLIConfig(c *cli.Context) CLIConfig { + return CLIConfig{ +- Enabled: c.Bool(EnabledFlagName), +- DAServerURL: c.String(DaServerAddressFlagName), +- VerifyOnRead: c.Bool(VerifyOnReadFlagName), +- GenericDA: c.Bool(DaServiceFlag), ++ Enabled: c.Bool(EnabledFlagName), ++ DAServerURL: c.String(DaServerAddressFlagName), ++ VerifyOnRead: c.Bool(VerifyOnReadFlagName), ++ GenericDA: c.Bool(DaServiceFlagName), ++ PutTimeout: c.Duration(PutTimeoutFlagName), ++ GetTimeout: c.Duration(GetTimeoutFlagName), ++ MaxConcurrentRequests: c.Uint64(MaxConcurrentRequestsFlagName), + } + }
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+14
+
-4
+ +
+ +
+
+
diff --git OP/op-alt-da/daclient.go CELO/op-alt-da/daclient.go +index db9c66ce5c216e7f2d928cab55b1ab714395ebb8..269b71f3c1043fcf5a3e761eb4d73743ec6e7323 100644 +--- OP/op-alt-da/daclient.go ++++ CELO/op-alt-da/daclient.go +@@ -7,6 +7,7 @@ "errors" + "fmt" + "io" + "net/http" ++ "time" + ) +  + // ErrNotFound is returned when the server could not find the input. +@@ -23,10 +24,16 @@ // verify sets the client to verify a Keccak256 commitment on read. + verify bool + // whether commitment is precomputable (only applicable to keccak256) + precompute bool ++ getTimeout time.Duration ++ putTimeout time.Duration + } +  + func NewDAClient(url string, verify bool, pc bool) *DAClient { +- return &DAClient{url, verify, pc} ++ return &DAClient{ ++ url: url, ++ verify: verify, ++ precompute: pc, ++ } + } +  + // GetInput returns the input data for the given encoded commitment bytes. +@@ -35,7 +42,8 @@ req, err := http.NewRequestWithContext(ctx, http.MethodGet, fmt.Sprintf("%s/get/0x%x", c.url, comm.Encode()), nil) + if err != nil { + return nil, fmt.Errorf("failed to create HTTP request: %w", err) + } +- resp, err := http.DefaultClient.Do(req) ++ client := &http.Client{Timeout: c.getTimeout} ++ resp, err := client.Do(req) + if err != nil { + return nil, err + } +@@ -91,7 +99,8 @@ if err != nil { + return fmt.Errorf("failed to create HTTP request: %w", err) + } + req.Header.Set("Content-Type", "application/octet-stream") +- resp, err := http.DefaultClient.Do(req) ++ client := &http.Client{Timeout: c.putTimeout} ++ resp, err := client.Do(req) + if err != nil { + return err + } +@@ -116,7 +125,8 @@ if err != nil { + return nil, fmt.Errorf("failed to create HTTP request: %w", err) + } + req.Header.Set("Content-Type", "application/octet-stream") +- resp, err := http.DefaultClient.Do(req) ++ client := &http.Client{Timeout: c.putTimeout} ++ resp, err := client.Do(req) + if err != nil { + return nil, err + }
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+2
+
-36
+ +
+ +
+
+
diff --git OP/op-alt-da/daclient_test.go CELO/op-alt-da/daclient_test.go +index 02a9611ae276d055efc019ad99b36503699ad72c..d9f7902aadee131b38a099bd61616f55e3ad4dfb 100644 +--- OP/op-alt-da/daclient_test.go ++++ CELO/op-alt-da/daclient_test.go +@@ -2,48 +2,14 @@ package altda +  + import ( + "context" +- "fmt" + "math/rand" +- "sync" + "testing" +  + "github.com/ethereum-optimism/optimism/op-service/testlog" +- "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/log" + "github.com/stretchr/testify/require" + ) +  +-type MemStore struct { +- db map[string][]byte +- lock sync.RWMutex +-} +- +-func NewMemStore() *MemStore { +- return &MemStore{ +- db: make(map[string][]byte), +- } +-} +- +-// Get retrieves the given key if it's present in the key-value store. +-func (s *MemStore) Get(ctx context.Context, key []byte) ([]byte, error) { +- s.lock.RLock() +- defer s.lock.RUnlock() +- +- if entry, ok := s.db[string(key)]; ok { +- return common.CopyBytes(entry), nil +- } +- return nil, ErrNotFound +-} +- +-// Put inserts the given value into the key-value store. +-func (s *MemStore) Put(ctx context.Context, key []byte, value []byte) error { +- s.lock.Lock() +- defer s.lock.Unlock() +- +- s.db[string(key)] = common.CopyBytes(value) +- return nil +-} +- + func TestDAClientPrecomputed(t *testing.T) { + store := NewMemStore() + logger := testlog.Logger(t, log.LevelDebug) +@@ -56,7 +22,7 @@ require.NoError(t, server.Start()) +  + cfg := CLIConfig{ + Enabled: true, +- DAServerURL: fmt.Sprintf("http://%s", server.Endpoint()), ++ DAServerURL: server.HttpEndpoint(), + VerifyOnRead: true, + } + require.NoError(t, cfg.Check()) +@@ -113,7 +79,7 @@ require.NoError(t, server.Start()) +  + cfg := CLIConfig{ + Enabled: true, +- DAServerURL: fmt.Sprintf("http://%s", server.Endpoint()), ++ DAServerURL: server.HttpEndpoint(), + VerifyOnRead: false, + GenericDA: false, + }
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+85
+
-0
+ +
+ +
+
+
diff --git OP/op-alt-da/damock.go CELO/op-alt-da/damock.go +index b56b73fdfcc90519bcd4fad6290f0868d3ee9ec9..0db129171a82232b45a1e8c256d663fa4eba67d5 100644 +--- OP/op-alt-da/damock.go ++++ CELO/op-alt-da/damock.go +@@ -4,8 +4,12 @@ import ( + "context" + "errors" + "io" ++ "net/http" ++ "sync" ++ "time" +  + "github.com/ethereum-optimism/optimism/op-service/eth" ++ "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/ethdb/memorydb" + "github.com/ethereum/go-ethereum/log" +@@ -99,3 +103,84 @@ + func (d *AltDADisabled) AdvanceL1Origin(ctx context.Context, l1 L1Fetcher, blockId eth.BlockID) error { + return ErrNotEnabled + } ++ ++// FakeDAServer is a fake DA server for e2e tests. ++// It is a small wrapper around DAServer that allows for setting request latencies, ++// to mimic a DA service with slow responses (eg. eigenDA with 10 min batching interval). ++type FakeDAServer struct { ++ *DAServer ++ putRequestLatency time.Duration ++ getRequestLatency time.Duration ++} ++ ++func NewFakeDAServer(host string, port int, log log.Logger) *FakeDAServer { ++ store := NewMemStore() ++ fakeDAServer := &FakeDAServer{ ++ DAServer: NewDAServer(host, port, store, log, true), ++ putRequestLatency: 0, ++ getRequestLatency: 0, ++ } ++ return fakeDAServer ++} ++ ++func (s *FakeDAServer) HandleGet(w http.ResponseWriter, r *http.Request) { ++ time.Sleep(s.getRequestLatency) ++ s.DAServer.HandleGet(w, r) ++} ++ ++func (s *FakeDAServer) HandlePut(w http.ResponseWriter, r *http.Request) { ++ time.Sleep(s.putRequestLatency) ++ s.DAServer.HandlePut(w, r) ++} ++ ++func (s *FakeDAServer) Start() error { ++ err := s.DAServer.Start() ++ if err != nil { ++ return err ++ } ++ // Override the HandleGet/Put method registrations ++ mux := http.NewServeMux() ++ mux.HandleFunc("/get/", s.HandleGet) ++ mux.HandleFunc("/put/", s.HandlePut) ++ s.httpServer.Handler = mux ++ return nil ++} ++ ++func (s *FakeDAServer) SetPutRequestLatency(latency time.Duration) { ++ s.putRequestLatency = latency ++} ++ ++func (s *FakeDAServer) SetGetRequestLatency(latency time.Duration) { ++ s.getRequestLatency = latency ++} ++ ++type MemStore struct { ++ db map[string][]byte ++ lock sync.RWMutex ++} ++ ++func NewMemStore() *MemStore { ++ return &MemStore{ ++ db: make(map[string][]byte), ++ } ++} ++ ++// Get retrieves the given key if it's present in the key-value store. ++func (s *MemStore) Get(ctx context.Context, key []byte) ([]byte, error) { ++ s.lock.RLock() ++ defer s.lock.RUnlock() ++ ++ if entry, ok := s.db[string(key)]; ok { ++ return common.CopyBytes(entry), nil ++ } ++ return nil, ErrNotFound ++} ++ ++// Put inserts the given value into the key-value store. ++func (s *MemStore) Put(ctx context.Context, key []byte, value []byte) error { ++ s.lock.Lock() ++ defer s.lock.Unlock() ++ ++ s.db[string(key)] = common.CopyBytes(value) ++ return nil ++}
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+2
+
-2
+ +
+ +
+
+
diff --git OP/op-alt-da/daserver.go CELO/op-alt-da/daserver.go +index ef43fd27fef3c8cfbff2b08795c16be3088ed078..94446944b5430fbc3026da31196e23ccee169ad2 100644 +--- OP/op-alt-da/daserver.go ++++ CELO/op-alt-da/daserver.go +@@ -187,8 +187,8 @@ w.WriteHeader(http.StatusOK) + } + } +  +-func (b *DAServer) Endpoint() string { +- return b.listener.Addr().String() ++func (b *DAServer) HttpEndpoint() string { ++ return fmt.Sprintf("http://%s", b.listener.Addr().String()) + } +  + func (b *DAServer) Stop() error {
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+7
+
-6
+ +
+ +
+
+
diff --git OP/op-batcher/batcher/channel.go CELO/op-batcher/batcher/channel.go +index 9a5e6b4c6a2eb15cd4ce0c6418f0031e2e0e0fe1..de68fa588a0a6e211e8d698c175cf922b01cef85 100644 +--- OP/op-batcher/batcher/channel.go ++++ CELO/op-batcher/batcher/channel.go +@@ -35,7 +35,7 @@ maxInclusionBlock uint64 + } +  + func newChannel(log log.Logger, metr metrics.Metricer, cfg ChannelConfig, rollupCfg *rollup.Config, latestL1OriginBlockNum uint64) (*channel, error) { +- cb, err := NewChannelBuilder(cfg, *rollupCfg, latestL1OriginBlockNum) ++ cb, err := NewChannelBuilder(cfg, rollupCfg, latestL1OriginBlockNum) + if err != nil { + return nil, fmt.Errorf("creating new channel: %w", err) + } +@@ -155,9 +155,9 @@ func (s *channel) ID() derive.ChannelID { + return s.channelBuilder.ID() + } +  +-// NextTxData returns the next tx data packet. +-// If cfg.MultiFrameTxs is false, it returns txData with a single frame. +-// If cfg.MultiFrameTxs is true, it will read frames from its channel builder ++// NextTxData dequeues the next frames from the channel and returns them encoded in a tx data packet. ++// If cfg.UseBlobs is false, it returns txData with a single frame. ++// If cfg.UseBlobs is true, it will read frames from its channel builder + // until it either doesn't have more frames or the target number of frames is reached. + // + // NextTxData should only be called after HasTxData returned true. +@@ -177,10 +177,11 @@ return txdata + } +  + func (s *channel) HasTxData() bool { +- if s.IsFull() || !s.cfg.UseBlobs { ++ if s.IsFull() || // If the channel is full, we should start to submit it ++ !s.cfg.UseBlobs { // If using calldata, we only send one frame per tx + return s.channelBuilder.HasFrame() + } +- // collect enough frames if channel is not full yet ++ // Collect enough frames if channel is not full yet + return s.channelBuilder.PendingFrames() >= int(s.cfg.MaxFramesPerTx()) + } +
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+21
+
-20
+ +
+ +
+
+
diff --git OP/op-batcher/batcher/channel_builder.go CELO/op-batcher/batcher/channel_builder.go +index 4cdcba8325c22420f8080ae82822b4e51c77de14..0c16f3156d9b7eb4a28e834ba10ac73af7121535 100644 +--- OP/op-batcher/batcher/channel_builder.go ++++ CELO/op-batcher/batcher/channel_builder.go +@@ -48,7 +48,7 @@ // ChannelBuilder uses a ChannelOut to create a channel with output frame + // size approximation. + type ChannelBuilder struct { + cfg ChannelConfig +- rollupCfg rollup.Config ++ rollupCfg *rollup.Config +  + // L1 block number timeout of combined + // - channel duration timeout, +@@ -85,22 +85,8 @@ + // NewChannelBuilder creates a new channel builder or returns an error if the + // channel out could not be created. + // it acts as a factory for either a span or singular channel out +-func NewChannelBuilder(cfg ChannelConfig, rollupCfg rollup.Config, latestL1OriginBlockNum uint64) (*ChannelBuilder, error) { +- c, err := cfg.CompressorConfig.NewCompressor() +- if err != nil { +- return nil, err +- } +- +- chainSpec := rollup.NewChainSpec(&rollupCfg) +- var co derive.ChannelOut +- if cfg.BatchType == derive.SpanBatchType { +- co, err = derive.NewSpanChannelOut( +- rollupCfg.Genesis.L2Time, rollupCfg.L2ChainID, +- cfg.CompressorConfig.TargetOutputSize, cfg.CompressorConfig.CompressionAlgo, +- chainSpec, derive.WithMaxBlocksPerSpanBatch(cfg.MaxBlocksPerSpanBatch)) +- } else { +- co, err = derive.NewSingularChannelOut(c, chainSpec) +- } ++func NewChannelBuilder(cfg ChannelConfig, rollupCfg *rollup.Config, latestL1OriginBlockNum uint64) (*ChannelBuilder, error) { ++ co, err := newChannelOut(cfg, rollupCfg) + if err != nil { + return nil, fmt.Errorf("creating channel out: %w", err) + } +@@ -114,6 +100,21 @@ + cb.updateDurationTimeout(latestL1OriginBlockNum) +  + return cb, nil ++} ++ ++// newChannelOut creates a new channel out based on the given configuration. ++func newChannelOut(cfg ChannelConfig, rollupCfg *rollup.Config) (derive.ChannelOut, error) { ++ spec := rollup.NewChainSpec(rollupCfg) ++ if cfg.BatchType == derive.SpanBatchType { ++ return derive.NewSpanChannelOut( ++ cfg.CompressorConfig.TargetOutputSize, cfg.CompressorConfig.CompressionAlgo, ++ spec, derive.WithMaxBlocksPerSpanBatch(cfg.MaxBlocksPerSpanBatch)) ++ } ++ comp, err := cfg.CompressorConfig.NewCompressor() ++ if err != nil { ++ return nil, err ++ } ++ return derive.NewSingularChannelOut(comp, spec) + } +  + func (c *ChannelBuilder) ID() derive.ChannelID { +@@ -177,7 +178,7 @@ if c.IsFull() { + return nil, c.FullErr() + } +  +- batch, l1info, err := derive.BlockToSingularBatch(&c.rollupCfg, block) ++ batch, l1info, err := derive.BlockToSingularBatch(c.rollupCfg, block) + if err != nil { + return l1info, fmt.Errorf("converting block to batch: %w", err) + } +@@ -416,12 +417,12 @@ return len(c.frames) > 0 + } +  + // PendingFrames returns the number of pending frames in the frames queue. +-// It is larger zero iff HasFrames() returns true. ++// It is larger zero iff HasFrame() returns true. + func (c *ChannelBuilder) PendingFrames() int { + return len(c.frames) + } +  +-// NextFrame returns the next available frame. ++// NextFrame dequeues the next available frame. + // HasFrame must be called prior to check if there's a next frame available. + // Panics if called when there's no next frame. + func (c *ChannelBuilder) NextFrame() frameData {
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+9
+
-9
+ +
+ +
+
+
diff --git OP/op-batcher/batcher/channel_builder_test.go CELO/op-batcher/batcher/channel_builder_test.go +index 85edbef5def5d865a8ace133fb1eb162a48d3c84..1c25f06d81c05bb40a680cc29ab5c424457c9681 100644 +--- OP/op-batcher/batcher/channel_builder_test.go ++++ CELO/op-batcher/batcher/channel_builder_test.go +@@ -22,7 +22,7 @@ ) +  + const latestL1BlockOrigin = 10 +  +-var defaultTestRollupConfig = rollup.Config{ ++var defaultTestRollupConfig = &rollup.Config{ + Genesis: rollup.Genesis{L2: eth.BlockID{Number: 0}}, + L2ChainID: big.NewInt(1234), + } +@@ -63,7 +63,7 @@ Difficulty: common.Big0, + Number: big.NewInt(l1Number), + Time: blockTime, + }, nil, nil, trie.NewStackTrie(nil)) +- l1InfoTx, err := derive.L1InfoDeposit(&defaultTestRollupConfig, eth.SystemConfig{}, 0, eth.BlockToInfo(l1Block), blockTime) ++ l1InfoTx, err := derive.L1InfoDeposit(defaultTestRollupConfig, eth.SystemConfig{}, 0, eth.BlockToInfo(l1Block), blockTime) + if err != nil { + panic(err) + } +@@ -369,7 +369,7 @@ // to construct a single frame + // the type of batch does not matter here because we are using it to construct a broken frame + c, err := channelConfig.CompressorConfig.NewCompressor() + require.NoError(t, err) +- co, err := derive.NewSingularChannelOut(c, rollup.NewChainSpec(&defaultTestRollupConfig)) ++ co, err := derive.NewSingularChannelOut(c, rollup.NewChainSpec(defaultTestRollupConfig)) + require.NoError(t, err) + var buf bytes.Buffer + fn, err := co.OutputFrame(&buf, channelConfig.MaxFrameSize) +@@ -503,7 +503,7 @@ // function errors when the max RLP bytes per channel is reached. + func ChannelBuilder_MaxRLPBytesPerChannel(t *testing.T, batchType uint) { + t.Parallel() + channelConfig := defaultTestChannelConfig() +- chainSpec := rollup.NewChainSpec(&defaultTestRollupConfig) ++ chainSpec := rollup.NewChainSpec(defaultTestRollupConfig) + channelConfig.MaxFrameSize = chainSpec.MaxRLPBytesPerChannel(latestL1BlockOrigin) * 2 + channelConfig.InitNoneCompressor() + channelConfig.BatchType = batchType +@@ -525,7 +525,7 @@ // then check postFjord w/ double the amount of blocks + func ChannelBuilder_MaxRLPBytesPerChannelFjord(t *testing.T, batchType uint) { + t.Parallel() + channelConfig := defaultTestChannelConfig() +- chainSpec := rollup.NewChainSpec(&defaultTestRollupConfig) ++ chainSpec := rollup.NewChainSpec(defaultTestRollupConfig) + channelConfig.MaxFrameSize = chainSpec.MaxRLPBytesPerChannel(latestL1BlockOrigin) * 2 + channelConfig.InitNoneCompressor() + channelConfig.BatchType = batchType +@@ -541,13 +541,13 @@ + // Create a new channel builder with fjord fork + now := time.Now() + fjordTime := uint64(now.Add(-1 * time.Second).Unix()) +- rollupConfig := rollup.Config{ ++ rollupConfig := &rollup.Config{ + Genesis: rollup.Genesis{L2: eth.BlockID{Number: 0}}, + L2ChainID: big.NewInt(1234), + FjordTime: &fjordTime, + } +  +- chainSpec = rollup.NewChainSpec(&rollupConfig) ++ chainSpec = rollup.NewChainSpec(rollupConfig) + channelConfig.MaxFrameSize = chainSpec.MaxRLPBytesPerChannel(uint64(now.Unix())) * 2 + channelConfig.InitNoneCompressor() + channelConfig.BatchType = batchType +@@ -887,7 +887,7 @@ block := dtest.RandomL2BlockWithChainIdAndTime(rng, rng.Intn(32), defaultTestRollupConfig.L2ChainID, ti.Add(time.Duration(i)*time.Second)) + if batchType == derive.SingularBatchType { + l += blockBatchRlpSize(t, block) + } else { +- singularBatch, l1Info, err := derive.BlockToSingularBatch(&defaultTestRollupConfig, block) ++ singularBatch, l1Info, err := derive.BlockToSingularBatch(defaultTestRollupConfig, block) + require.NoError(err) + err = spanBatch.AppendSingularBatch(singularBatch, l1Info.SequenceNumber) + require.NoError(err) +@@ -942,7 +942,7 @@ } +  + func blockBatchRlpSize(t *testing.T, b *types.Block) int { + t.Helper() +- singularBatch, _, err := derive.BlockToSingularBatch(&defaultTestRollupConfig, b) ++ singularBatch, _, err := derive.BlockToSingularBatch(defaultTestRollupConfig, b) + batch := derive.NewBatchData(singularBatch) + require.NoError(t, err) + var buf bytes.Buffer
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+2
+
-2
+ +
+ +
+
+
diff --git OP/op-batcher/batcher/channel_config.go CELO/op-batcher/batcher/channel_config.go +index 63e0d5d5deef0d39dd1bdd404d815e2f9383eee3..45dc1d4dcfa4a4e96e9868c968277a31ee37244f 100644 +--- OP/op-batcher/batcher/channel_config.go ++++ CELO/op-batcher/batcher/channel_config.go +@@ -51,8 +51,8 @@ // transaction with one blob per frame. + UseBlobs bool + } +  +-// ChannelConfig returns a copy of itself. This makes a ChannelConfig a static +-// ChannelConfigProvider of itself. ++// ChannelConfig returns a copy of the receiver. ++// This allows the receiver to be a static ChannelConfigProvider of itself. + func (cc ChannelConfig) ChannelConfig() ChannelConfig { + return cc + }
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+4
+
-0
+ +
+ +
+
+
diff --git OP/op-batcher/batcher/channel_config_provider.go CELO/op-batcher/batcher/channel_config_provider.go +index c65e83b8289fa52dc068a55abde382d3cad08e00..6cf5b0db6863334317fc96a52809f02d3e30f147 100644 +--- OP/op-batcher/batcher/channel_config_provider.go ++++ CELO/op-batcher/batcher/channel_config_provider.go +@@ -48,6 +48,10 @@ dec.lastConfig = &dec.blobConfig + return dec + } +  ++// ChannelConfig will perform an estimate of the cost per byte for ++// calldata and for blobs, given current market conditions: it will return ++// the appropriate ChannelConfig depending on which is cheaper. It makes ++// assumptions about the typical makeup of channel data. + func (dec *DynamicEthChannelConfig) ChannelConfig() ChannelConfig { + ctx, cancel := context.WithTimeout(context.Background(), dec.timeout) + defer cancel()
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+97
+
-14
+ +
+ +
+
+
diff --git OP/op-batcher/batcher/channel_manager.go CELO/op-batcher/batcher/channel_manager.go +index 1f22565c94c504fe0c09ce4dd617ff70f986d8a5..23e8f7843696fc98ab77545c8e303977520ff69b 100644 +--- OP/op-batcher/batcher/channel_manager.go ++++ CELO/op-batcher/batcher/channel_manager.go +@@ -35,6 +35,8 @@ // All blocks since the last request for new tx data. + blocks []*types.Block + // The latest L1 block from all the L2 blocks in the most recently closed channel + l1OriginLastClosedChannel eth.BlockID ++ // The default ChannelConfig to use for the next channel ++ defaultCfg ChannelConfig + // last block hash - for reorg detection + tip common.Hash +  +@@ -54,6 +56,7 @@ return &channelManager{ + log: log, + metr: metr, + cfgProvider: cfgProvider, ++ defaultCfg: cfgProvider.ChannelConfig(), + rollupCfg: rollupCfg, + txChannels: make(map[string]*channel), + } +@@ -133,7 +136,8 @@ } + s.channelQueue = append(s.channelQueue[:index], s.channelQueue[index+1:]...) + } +  +-// nextTxData pops off s.datas & handles updating the internal state ++// nextTxData dequeues frames from the channel and returns them encoded in a transaction. ++// It also updates the internal tx -> channels mapping + func (s *channelManager) nextTxData(channel *channel) (txData, error) { + if channel == nil || !channel.HasTxData() { + s.log.Trace("no next tx data") +@@ -146,12 +150,55 @@ } +  + // TxData returns the next tx data that should be submitted to L1. + // +-// If the pending channel is ++// If the current channel is + // full, it only returns the remaining frames of this channel until it got + // successfully fully sent to L1. It returns io.EOF if there's no pending tx data. ++// ++// It will decide whether to switch DA type automatically. ++// When switching DA type, the channelManager state will be rebuilt ++// with a new ChannelConfig. + func (s *channelManager) TxData(l1Head eth.BlockID) (txData, error) { + s.mu.Lock() + defer s.mu.Unlock() ++ channel, err := s.getReadyChannel(l1Head) ++ if err != nil { ++ return emptyTxData, err ++ } ++ // If the channel has already started being submitted, ++ // return now and ensure no requeueing happens ++ if !channel.NoneSubmitted() { ++ return s.nextTxData(channel) ++ } ++ ++ // Call provider method to reassess optimal DA type ++ newCfg := s.cfgProvider.ChannelConfig() ++ ++ // No change: ++ if newCfg.UseBlobs == s.defaultCfg.UseBlobs { ++ s.log.Debug("Recomputing optimal ChannelConfig: no need to switch DA type", ++ "useBlobs", s.defaultCfg.UseBlobs) ++ return s.nextTxData(channel) ++ } ++ ++ // Change: ++ s.log.Info("Recomputing optimal ChannelConfig: changing DA type and requeing blocks...", ++ "useBlobsBefore", s.defaultCfg.UseBlobs, ++ "useBlobsAfter", newCfg.UseBlobs) ++ s.Requeue(newCfg) ++ channel, err = s.getReadyChannel(l1Head) ++ if err != nil { ++ return emptyTxData, err ++ } ++ return s.nextTxData(channel) ++} ++ ++// getReadyChannel returns the next channel ready to submit data, or an error. ++// It will create a new channel if necessary. ++// If there is no data ready to send, it adds blocks from the block queue ++// to the current channel and generates frames for it. ++// Always returns nil and the io.EOF sentinel error when ++// there is no channel with txData ++func (s *channelManager) getReadyChannel(l1Head eth.BlockID) (*channel, error) { + var firstWithTxData *channel + for _, ch := range s.channelQueue { + if ch.HasTxData() { +@@ -160,27 +207,31 @@ break + } + } +  +- dataPending := firstWithTxData != nil && firstWithTxData.HasTxData() ++ dataPending := firstWithTxData != nil + s.log.Debug("Requested tx data", "l1Head", l1Head, "txdata_pending", dataPending, "blocks_pending", len(s.blocks)) +  +- // Short circuit if there is pending tx data or the channel manager is closed. +- if dataPending || s.closed { +- return s.nextTxData(firstWithTxData) ++ // Short circuit if there is pending tx data or the channel manager is closed ++ if dataPending { ++ return firstWithTxData, nil ++ } ++ ++ if s.closed { ++ return nil, io.EOF + } +  + // No pending tx data, so we have to add new blocks to the channel +  + // If we have no saved blocks, we will not be able to create valid frames + if len(s.blocks) == 0 { +- return txData{}, io.EOF ++ return nil, io.EOF + } +  + if err := s.ensureChannelWithSpace(l1Head); err != nil { +- return txData{}, err ++ return nil, err + } +  + if err := s.processBlocks(); err != nil { +- return txData{}, err ++ return nil, err + } +  + // Register current L1 head only after all pending blocks have been +@@ -189,10 +240,14 @@ // all pending blocks be included in this channel for submission. + s.registerL1Block(l1Head) +  + if err := s.outputFrames(); err != nil { +- return txData{}, err ++ return nil, err + } +  +- return s.nextTxData(s.currentChannel) ++ if s.currentChannel.HasTxData() { ++ return s.currentChannel, nil ++ } ++ ++ return nil, io.EOF + } +  + // ensureChannelWithSpace ensures currentChannel is populated with a channel that has +@@ -203,7 +258,10 @@ if s.currentChannel != nil && !s.currentChannel.IsFull() { + return nil + } +  +- cfg := s.cfgProvider.ChannelConfig() ++ // We reuse the ChannelConfig from the last channel. ++ // This will be reassessed at channel submission-time, ++ // but this is our best guess at the appropriate values for now. ++ cfg := s.defaultCfg + pc, err := newChannel(s.log, s.metr, cfg, s.rollupCfg, s.l1OriginLastClosedChannel.Number) + if err != nil { + return fmt.Errorf("creating new channel: %w", err) +@@ -228,7 +286,7 @@ + return nil + } +  +-// registerL1Block registers the given block at the pending channel. ++// registerL1Block registers the given block at the current channel. + func (s *channelManager) registerL1Block(l1Head eth.BlockID) { + s.currentChannel.CheckTimeout(l1Head.Number) + s.log.Debug("new L1-block registered at channel builder", +@@ -238,7 +296,7 @@ "full_reason", s.currentChannel.FullErr(), + ) + } +  +-// processBlocks adds blocks from the blocks queue to the pending channel until ++// processBlocks adds blocks from the blocks queue to the current channel until + // either the queue got exhausted or the channel is full. + func (s *channelManager) processBlocks() error { + var ( +@@ -288,6 +346,7 @@ ) + return nil + } +  ++// outputFrames generates frames for the current channel, and computes and logs the compression ratio + func (s *channelManager) outputFrames() error { + if err := s.currentChannel.OutputFrames(); err != nil { + return fmt.Errorf("creating frames with channel builder: %w", err) +@@ -339,6 +398,7 @@ // blocks were added yet, the parent hash check is skipped. + func (s *channelManager) AddL2Block(block *types.Block) error { + s.mu.Lock() + defer s.mu.Unlock() ++ + if s.tip != (common.Hash{}) && s.tip != block.ParentHash() { + return ErrReorg + } +@@ -414,3 +474,26 @@ return ErrPendingAfterClose + } + return nil + } ++ ++// Requeue rebuilds the channel manager state by ++// rewinding blocks back from the channel queue, and setting the defaultCfg. ++func (s *channelManager) Requeue(newCfg ChannelConfig) { ++ newChannelQueue := []*channel{} ++ blocksToRequeue := []*types.Block{} ++ for _, channel := range s.channelQueue { ++ if !channel.NoneSubmitted() { ++ newChannelQueue = append(newChannelQueue, channel) ++ continue ++ } ++ blocksToRequeue = append(blocksToRequeue, channel.channelBuilder.Blocks()...) ++ } ++ ++ // We put the blocks back at the front of the queue: ++ s.blocks = append(blocksToRequeue, s.blocks...) ++ // Channels which where already being submitted are put back ++ s.channelQueue = newChannelQueue ++ s.currentChannel = nil ++ // Setting the defaultCfg will cause new channels ++ // to pick up the new ChannelConfig ++ s.defaultCfg = newCfg ++}
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+191
+
-8
+ +
+ +
+
+
diff --git OP/op-batcher/batcher/channel_manager_test.go CELO/op-batcher/batcher/channel_manager_test.go +index 474942ce5e879047e46779a4053ed061595ac403..c129cd9cde9911f2098448eccfb5ffe14b730d14 100644 +--- OP/op-batcher/batcher/channel_manager_test.go ++++ CELO/op-batcher/batcher/channel_manager_test.go +@@ -1,6 +1,7 @@ + package batcher +  + import ( ++ "errors" + "io" + "math/big" + "math/rand" +@@ -124,7 +125,7 @@ // channels on confirmation. This would result in [TxConfirmed] + // clearing confirmed transactions, and resetting the pendingChannels map + cfg.ChannelTimeout = 10 + cfg.InitRatioCompressor(1, derive.Zlib) +- m := NewChannelManager(log, metrics.NoopMetrics, cfg, &defaultTestRollupConfig) ++ m := NewChannelManager(log, metrics.NoopMetrics, cfg, defaultTestRollupConfig) +  + // Channel Manager state should be empty by default + require.Empty(m.blocks) +@@ -195,7 +196,7 @@ rng := rand.New(rand.NewSource(time.Now().UnixNano())) + log := testlog.Logger(t, log.LevelError) + cfg := channelManagerTestConfig(120_000, batchType) + cfg.CompressorConfig.TargetOutputSize = 1 // full on first block +- m := NewChannelManager(log, metrics.NoopMetrics, cfg, &defaultTestRollupConfig) ++ m := NewChannelManager(log, metrics.NoopMetrics, cfg, defaultTestRollupConfig) + m.Clear(eth.BlockID{}) +  + a := derivetest.RandomL2BlockWithChainId(rng, 4, defaultTestRollupConfig.L2ChainID) +@@ -234,7 +235,7 @@ rng := rand.New(rand.NewSource(time.Now().UnixNano())) + log := testlog.Logger(t, log.LevelCrit) + m := NewChannelManager(log, metrics.NoopMetrics, + channelManagerTestConfig(10000, batchType), +- &defaultTestRollupConfig, ++ defaultTestRollupConfig, + ) + m.Clear(eth.BlockID{}) +  +@@ -258,7 +259,7 @@ log := testlog.Logger(t, log.LevelCrit) + cfg := channelManagerTestConfig(10000, batchType) + cfg.CompressorConfig.TargetOutputSize = 1 // full on first block + cfg.ChannelTimeout = 1000 +- m := NewChannelManager(log, metrics.NoopMetrics, cfg, &defaultTestRollupConfig) ++ m := NewChannelManager(log, metrics.NoopMetrics, cfg, defaultTestRollupConfig) + m.Clear(eth.BlockID{}) + a := newMiniL2Block(0) + b := newMiniL2BlockWithNumberParent(0, big.NewInt(1), a.Hash()) +@@ -294,7 +295,7 @@ rng := rand.New(rand.NewSource(123)) + log := testlog.Logger(t, log.LevelError) + cfg := channelManagerTestConfig(10_000, batchType) + cfg.ChannelTimeout = 1000 +- m := NewChannelManager(log, metrics.NoopMetrics, cfg, &defaultTestRollupConfig) ++ m := NewChannelManager(log, metrics.NoopMetrics, cfg, defaultTestRollupConfig) + m.Clear(eth.BlockID{}) +  + numTx := 20 // Adjust number of txs to make 2 frames +@@ -346,7 +347,7 @@ ChannelTimeout: 1000, + TargetNumFrames: 100, + } + cfg.InitNoneCompressor() +- m := NewChannelManager(log, metrics.NoopMetrics, cfg, &defaultTestRollupConfig) ++ m := NewChannelManager(log, metrics.NoopMetrics, cfg, defaultTestRollupConfig) + m.Clear(eth.BlockID{}) +  + numTx := 3 // Adjust number of txs to make 2 frames +@@ -398,7 +399,7 @@ log := testlog.Logger(t, log.LevelCrit) + cfg := channelManagerTestConfig(100, batchType) + cfg.TargetNumFrames = 1000 + cfg.InitNoneCompressor() +- m := NewChannelManager(log, metrics.NoopMetrics, cfg, &defaultTestRollupConfig) ++ m := NewChannelManager(log, metrics.NoopMetrics, cfg, defaultTestRollupConfig) + m.Clear(eth.BlockID{}) +  + a := derivetest.RandomL2BlockWithChainId(rng, 1000, defaultTestRollupConfig.L2ChainID) +@@ -471,7 +472,7 @@ }, + } { + test := tt + t.Run(test.name, func(t *testing.T) { +- m := NewChannelManager(l, metrics.NoopMetrics, cfg, &defaultTestRollupConfig) ++ m := NewChannelManager(l, metrics.NoopMetrics, cfg, defaultTestRollupConfig) +  + m.l1OriginLastClosedChannel = test.safeL1Block + require.Nil(t, m.currentChannel) +@@ -483,3 +484,185 @@ require.Equal(t, test.expectedChannelTimeout, m.currentChannel.Timeout()) + }) + } + } ++ ++// FakeDynamicEthChannelConfig is a ChannelConfigProvider which always returns ++// either a blob- or calldata-based config depending on its internal chooseBlob ++// switch. ++type FakeDynamicEthChannelConfig struct { ++ DynamicEthChannelConfig ++ chooseBlobs bool ++ assessments int ++} ++ ++func (f *FakeDynamicEthChannelConfig) ChannelConfig() ChannelConfig { ++ f.assessments++ ++ if f.chooseBlobs { ++ return f.blobConfig ++ } ++ return f.calldataConfig ++} ++ ++func newFakeDynamicEthChannelConfig(lgr log.Logger, ++ reqTimeout time.Duration) *FakeDynamicEthChannelConfig { ++ ++ calldataCfg := ChannelConfig{ ++ MaxFrameSize: 120_000 - 1, ++ TargetNumFrames: 1, ++ } ++ blobCfg := ChannelConfig{ ++ MaxFrameSize: eth.MaxBlobDataSize - 1, ++ TargetNumFrames: 3, // gets closest to amortized fixed tx costs ++ UseBlobs: true, ++ } ++ calldataCfg.InitNoneCompressor() ++ blobCfg.InitNoneCompressor() ++ ++ return &FakeDynamicEthChannelConfig{ ++ chooseBlobs: false, ++ DynamicEthChannelConfig: *NewDynamicEthChannelConfig( ++ lgr, ++ reqTimeout, ++ &mockGasPricer{}, ++ blobCfg, ++ calldataCfg), ++ } ++} ++ ++// TestChannelManager_TxData seeds the channel manager with blocks and triggers the ++// blocks->channels pipeline multiple times. Values are chosen such that a channel ++// is created under one set of market conditions, and then submitted under a different ++// set of market conditions. The test asserts that the DA type is changed at channel ++// submission time. ++func TestChannelManager_TxData(t *testing.T) { ++ ++ type TestCase struct { ++ name string ++ chooseBlobsWhenChannelCreated bool ++ chooseBlobsWhenChannelSubmitted bool ++ ++ // * One when the channelManager was created ++ // * One when the channel is about to be submitted ++ // * Potentially one more if the replacement channel is about to be submitted, ++ // this only happens when going from calldata->blobs because ++ // the channel is no longer ready to send until more data ++ // is added. ++ numExpectedAssessments int ++ } ++ ++ tt := []TestCase{ ++ {"blobs->blobs", true, true, 2}, ++ {"calldata->calldata", false, false, 2}, ++ {"blobs->calldata", true, false, 2}, ++ {"calldata->blobs", false, true, 3}, ++ } ++ ++ for _, tc := range tt { ++ t.Run(tc.name, func(t *testing.T) { ++ l := testlog.Logger(t, log.LevelCrit) ++ ++ cfg := newFakeDynamicEthChannelConfig(l, 1000) ++ ++ cfg.chooseBlobs = tc.chooseBlobsWhenChannelCreated ++ m := NewChannelManager(l, metrics.NoopMetrics, cfg, defaultTestRollupConfig) ++ require.Equal(t, tc.chooseBlobsWhenChannelCreated, m.defaultCfg.UseBlobs) ++ ++ // Seed channel manager with a block ++ rng := rand.New(rand.NewSource(time.Now().UnixNano())) ++ blockA := derivetest.RandomL2BlockWithChainId(rng, 200, defaultTestRollupConfig.L2ChainID) ++ m.blocks = []*types.Block{blockA} ++ ++ // Call TxData a first time to trigger blocks->channels pipeline ++ _, err := m.TxData(eth.BlockID{}) ++ require.ErrorIs(t, err, io.EOF) ++ ++ // The test requires us to have something in the channel queue ++ // at this point, but not yet ready to send and not full ++ require.NotEmpty(t, m.channelQueue) ++ require.False(t, m.channelQueue[0].IsFull()) ++ ++ // Simulate updated market conditions ++ // by possibly flipping the state of the ++ // fake channel provider ++ l.Info("updating market conditions", "chooseBlobs", tc.chooseBlobsWhenChannelSubmitted) ++ cfg.chooseBlobs = tc.chooseBlobsWhenChannelSubmitted ++ ++ // Add a block and call TxData until ++ // we get some data to submit ++ var data txData ++ for { ++ m.blocks = []*types.Block{blockA} ++ data, err = m.TxData(eth.BlockID{}) ++ if err == nil && data.Len() > 0 { ++ break ++ } ++ if !errors.Is(err, io.EOF) { ++ require.NoError(t, err) ++ } ++ } ++ ++ require.Equal(t, tc.numExpectedAssessments, cfg.assessments) ++ require.Equal(t, tc.chooseBlobsWhenChannelSubmitted, data.asBlob) ++ require.Equal(t, tc.chooseBlobsWhenChannelSubmitted, m.defaultCfg.UseBlobs) ++ }) ++ } ++ ++} ++ ++// TestChannelManager_Requeue seeds the channel manager with blocks, ++// takes a state snapshot, triggers the blocks->channels pipeline, ++// and then calls Requeue. Finally, it asserts the channel manager's ++// state is equal to the snapshot. It repeats this for a channel ++// which has a pending transaction and verifies that Requeue is then ++// a noop. ++func TestChannelManager_Requeue(t *testing.T) { ++ l := testlog.Logger(t, log.LevelCrit) ++ cfg := channelManagerTestConfig(100, derive.SingularBatchType) ++ m := NewChannelManager(l, metrics.NoopMetrics, cfg, defaultTestRollupConfig) ++ ++ // Seed channel manager with blocks ++ rng := rand.New(rand.NewSource(99)) ++ blockA := derivetest.RandomL2BlockWithChainId(rng, 10, defaultTestRollupConfig.L2ChainID) ++ blockB := derivetest.RandomL2BlockWithChainId(rng, 10, defaultTestRollupConfig.L2ChainID) ++ ++ // This is the snapshot of channel manager state we want to reinstate ++ // when we requeue ++ stateSnapshot := []*types.Block{blockA, blockB} ++ m.blocks = stateSnapshot ++ require.Empty(t, m.channelQueue) ++ ++ // Trigger the blocks -> channelQueue data pipelining ++ require.NoError(t, m.ensureChannelWithSpace(eth.BlockID{})) ++ require.NotEmpty(t, m.channelQueue) ++ require.NoError(t, m.processBlocks()) ++ ++ // Assert that at least one block was processed into the channel ++ require.NotContains(t, m.blocks, blockA) ++ ++ // Call the function we are testing ++ m.Requeue(m.defaultCfg) ++ ++ // Ensure we got back to the state above ++ require.Equal(t, m.blocks, stateSnapshot) ++ require.Empty(t, m.channelQueue) ++ ++ // Trigger the blocks -> channelQueue data pipelining again ++ require.NoError(t, m.ensureChannelWithSpace(eth.BlockID{})) ++ require.NotEmpty(t, m.channelQueue) ++ require.NoError(t, m.processBlocks()) ++ ++ // Assert that at least one block was processed into the channel ++ require.NotContains(t, m.blocks, blockA) ++ ++ // Now mark the 0th channel in the queue as already ++ // starting to send on chain ++ channel0 := m.channelQueue[0] ++ channel0.pendingTransactions["foo"] = txData{} ++ require.False(t, channel0.NoneSubmitted()) ++ ++ // Call the function we are testing ++ m.Requeue(m.defaultCfg) ++ ++ // The requeue shouldn't affect the pending channel ++ require.Contains(t, m.channelQueue, channel0) ++ require.NotContains(t, m.blocks, blockA) ++}
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+2
+
-2
+ +
+ +
+
+
diff --git OP/op-batcher/batcher/channel_test.go CELO/op-batcher/batcher/channel_test.go +index 7fa8030e771e656b1f45f79b6c1633fe1631bf59..8dec9d9e108be12dc59d927c439a79c2e401ed41 100644 +--- OP/op-batcher/batcher/channel_test.go ++++ CELO/op-batcher/batcher/channel_test.go +@@ -86,8 +86,8 @@ require.ErrorIs(t, err, io.EOF) + require.Equal(t, txData{}, returnedTxData) +  + // Set the pending channel +- // The nextTxData function should still return EOF +- // since the pending channel has no frames ++ // The nextTxData function should still return io.EOF ++ // since the current channel has no frames + require.NoError(t, m.ensureChannelWithSpace(eth.BlockID{})) + channel := m.currentChannel + require.NotNil(t, channel)
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+108
+
-33
+ +
+ +
+
+
diff --git OP/op-batcher/batcher/driver.go CELO/op-batcher/batcher/driver.go +index 0af4c86ca40a98d732b28fa706a297ead85fe49e..6b8b8b5e58060ca32c3fe08986a6cf06d8904932 100644 +--- OP/op-batcher/batcher/driver.go ++++ CELO/op-batcher/batcher/driver.go +@@ -22,6 +22,7 @@ "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/txpool" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/log" ++ "golang.org/x/sync/errgroup" + ) +  + var ( +@@ -41,6 +42,25 @@ isCancel bool + isBlob bool + } +  ++func (r txRef) String() string { ++ return r.string(func(id txID) string { return id.String() }) ++} ++ ++func (r txRef) TerminalString() string { ++ return r.string(func(id txID) string { return id.TerminalString() }) ++} ++ ++func (r txRef) string(txIDStringer func(txID) string) string { ++ if r.isCancel { ++ if r.isBlob { ++ return "blob-cancellation" ++ } else { ++ return "calldata-cancellation" ++ } ++ } ++ return txIDStringer(r.id) ++} ++ + type L1Client interface { + HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) + NonceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (uint64, error) +@@ -60,7 +80,7 @@ Log log.Logger + Metr metrics.Metricer + RollupConfig *rollup.Config + Config BatcherConfig +- Txmgr *txmgr.SimpleTxManager ++ Txmgr txmgr.TxManager + L1Client L1Client + EndpointProvider dial.L2EndpointProvider + ChannelConfig ChannelConfigProvider +@@ -170,10 +190,11 @@ } +  + // loadBlocksIntoState loads all blocks since the previous stored block + // It does the following: +-// 1. Fetch the sync status of the sequencer +-// 2. Check if the sync status is valid or if we are all the way up to date +-// 3. Check if it needs to initialize state OR it is lagging (todo: lagging just means race condition?) +-// 4. Load all new blocks into the local state. ++// 1. Fetch the sync status of the sequencer ++// 2. Check if the sync status is valid or if we are all the way up to date ++// 3. Check if it needs to initialize state OR it is lagging (todo: lagging just means race condition?) ++// 4. Load all new blocks into the local state. ++// + // If there is a reorg, it will reset the last stored block but not clear the internal state so + // the state can be flushed to L1. + func (l *BatchSubmitter) loadBlocksIntoState(ctx context.Context) error { +@@ -266,7 +287,7 @@ } +  + // Check if we should even attempt to load any blocks. TODO: May not need this check + if syncStatus.SafeL2.Number >= syncStatus.UnsafeL2.Number { +- return eth.BlockID{}, eth.BlockID{}, errors.New("L2 safe head ahead of L2 unsafe head") ++ return eth.BlockID{}, eth.BlockID{}, fmt.Errorf("L2 safe head(%d) ahead of L2 unsafe head(%d)", syncStatus.SafeL2.Number, syncStatus.UnsafeL2.Number) + } +  + return l.lastStoredBlock, syncStatus.UnsafeL2.ID(), nil +@@ -302,6 +323,12 @@ defer l.wg.Done() +  + receiptsCh := make(chan txmgr.TxReceipt[txRef]) + queue := txmgr.NewQueue[txRef](l.killCtx, l.Txmgr, l.Config.MaxPendingTransactions) ++ daGroup := &errgroup.Group{} ++ // errgroup with limit of 0 means no goroutine is able to run concurrently, ++ // so we only set the limit if it is greater than 0. ++ if l.Config.MaxConcurrentDARequests > 0 { ++ daGroup.SetLimit(int(l.Config.MaxConcurrentDARequests)) ++ } +  + // start the receipt/result processing loop + receiptLoopDone := make(chan struct{}) +@@ -339,9 +366,20 @@ ticker := time.NewTicker(l.Config.PollInterval) + defer ticker.Stop() +  + publishAndWait := func() { +- l.publishStateToL1(queue, receiptsCh) ++ l.publishStateToL1(queue, receiptsCh, daGroup) + if !l.Txmgr.IsClosed() { +- queue.Wait() ++ if l.Config.UseAltDA { ++ l.Log.Info("Waiting for altDA writes to complete...") ++ err := daGroup.Wait() ++ if err != nil { ++ l.Log.Error("Error returned by one of the altda goroutines waited on", "err", err) ++ } ++ } ++ l.Log.Info("Waiting for L1 txs to be confirmed...") ++ err := queue.Wait() ++ if err != nil { ++ l.Log.Error("Error returned by one of the txmgr goroutines waited on", "err", err) ++ } + } else { + l.Log.Info("Txmgr is closed, remaining channel data won't be sent") + } +@@ -368,7 +406,7 @@ publishAndWait() + l.clearState(l.shutdownCtx) + continue + } +- l.publishStateToL1(queue, receiptsCh) ++ l.publishStateToL1(queue, receiptsCh, daGroup) + case <-l.shutdownCtx.Done(): + if l.Txmgr.IsClosed() { + l.Log.Info("Txmgr is closed, remaining channel data won't be sent") +@@ -425,7 +463,7 @@ } +  + // publishStateToL1 queues up all pending TxData to be published to the L1, returning when there is + // no more data to queue for publishing or if there was an error queing the data. +-func (l *BatchSubmitter) publishStateToL1(queue *txmgr.Queue[txRef], receiptsCh chan txmgr.TxReceipt[txRef]) { ++func (l *BatchSubmitter) publishStateToL1(queue *txmgr.Queue[txRef], receiptsCh chan txmgr.TxReceipt[txRef], daGroup *errgroup.Group) { + for { + // if the txmgr is closed, we stop the transaction sending + if l.Txmgr.IsClosed() { +@@ -436,8 +474,7 @@ if !l.checkTxpool(queue, receiptsCh) { + l.Log.Info("txpool state is not good, aborting state publishing") + return + } +- err := l.publishTxToL1(l.killCtx, queue, receiptsCh) +- ++ err := l.publishTxToL1(l.killCtx, queue, receiptsCh, daGroup) + if err != nil { + if err != io.EOF { + l.Log.Error("Error publishing tx to l1", "err", err) +@@ -487,7 +524,7 @@ } + } +  + // publishTxToL1 submits a single state tx to the L1 +-func (l *BatchSubmitter) publishTxToL1(ctx context.Context, queue *txmgr.Queue[txRef], receiptsCh chan txmgr.TxReceipt[txRef]) error { ++func (l *BatchSubmitter) publishTxToL1(ctx context.Context, queue *txmgr.Queue[txRef], receiptsCh chan txmgr.TxReceipt[txRef], daGroup *errgroup.Group) error { + // send all available transactions + l1tip, err := l.l1Tip(ctx) + if err != nil { +@@ -496,7 +533,8 @@ return err + } + l.recordL1Tip(l1tip) +  +- // Collect next transaction data ++ // Collect next transaction data. This pulls data out of the channel, so we need to make sure ++ // to put it back if ever da or txmgr requests fail, by calling l.recordFailedDARequest/recordFailedTx. + txdata, err := l.state.TxData(l1tip.ID()) +  + if err == io.EOF { +@@ -507,7 +545,7 @@ l.Log.Error("Unable to get tx data", "err", err) + return err + } +  +- if err = l.sendTransaction(ctx, txdata, queue, receiptsCh); err != nil { ++ if err = l.sendTransaction(txdata, queue, receiptsCh, daGroup); err != nil { + return fmt.Errorf("BatchSubmitter.sendTransaction failed: %w", err) + } + return nil +@@ -552,12 +590,56 @@ l.Log.Warn("sending a cancellation transaction to unblock txpool", "blocked_blob", isBlockedBlob) + l.sendTx(txData{}, true, candidate, queue, receiptsCh) + } +  ++// publishToAltDAAndL1 posts the txdata to the DA Provider and then sends the commitment to L1. ++func (l *BatchSubmitter) publishToAltDAAndL1(txdata txData, queue *txmgr.Queue[txRef], receiptsCh chan txmgr.TxReceipt[txRef], daGroup *errgroup.Group) { ++ // sanity checks ++ if nf := len(txdata.frames); nf != 1 { ++ l.Log.Crit("Unexpected number of frames in calldata tx", "num_frames", nf) ++ } ++ if txdata.asBlob { ++ l.Log.Crit("Unexpected blob txdata with AltDA enabled") ++ } ++ ++ // when posting txdata to an external DA Provider, we use a goroutine to avoid blocking the main loop ++ // since it may take a while for the request to return. ++ goroutineSpawned := daGroup.TryGo(func() error { ++ // TODO: probably shouldn't be using the global shutdownCtx here, see https://go.dev/blog/context-and-structs ++ // but sendTransaction receives l.killCtx as an argument, which currently is only canceled after waiting for the main loop ++ // to exit, which would wait on this DA call to finish, which would take a long time. ++ // So we prefer to mimic the behavior of txmgr and cancel all pending DA/txmgr requests when the batcher is stopped. ++ comm, err := l.AltDA.SetInput(l.shutdownCtx, txdata.CallData()) ++ if err != nil { ++ l.Log.Error("Failed to post input to Alt DA", "error", err) ++ // requeue frame if we fail to post to the DA Provider so it can be retried ++ // note: this assumes that the da server caches requests, otherwise it might lead to resubmissions of the blobs ++ l.recordFailedDARequest(txdata.ID(), err) ++ return nil ++ } ++ l.Log.Info("Set altda input", "commitment", comm, "tx", txdata.ID()) ++ candidate := l.calldataTxCandidate(comm.TxData()) ++ l.sendTx(txdata, false, candidate, queue, receiptsCh) ++ return nil ++ }) ++ if !goroutineSpawned { ++ // We couldn't start the goroutine because the errgroup.Group limit ++ // is already reached. Since we can't send the txdata, we have to ++ // return it for later processing. We use nil error to skip error logging. ++ l.recordFailedDARequest(txdata.ID(), nil) ++ } ++} ++ + // sendTransaction creates & queues for sending a transaction to the batch inbox address with the given `txData`. + // This call will block if the txmgr queue is at the max-pending limit. + // The method will block if the queue's MaxPendingTransactions is exceeded. +-func (l *BatchSubmitter) sendTransaction(ctx context.Context, txdata txData, queue *txmgr.Queue[txRef], receiptsCh chan txmgr.TxReceipt[txRef]) error { ++func (l *BatchSubmitter) sendTransaction(txdata txData, queue *txmgr.Queue[txRef], receiptsCh chan txmgr.TxReceipt[txRef], daGroup *errgroup.Group) error { + var err error +- // Do the gas estimation offline. A value of 0 will cause the [txmgr] to estimate the gas limit. ++ ++ // if Alt DA is enabled we post the txdata to the DA Provider and replace it with the commitment. ++ if l.Config.UseAltDA { ++ l.publishToAltDAAndL1(txdata, queue, receiptsCh, daGroup) ++ // we return nil to allow publishStateToL1 to keep processing the next txdata ++ return nil ++ } +  + var candidate *txmgr.TxCandidate + if txdata.asBlob { +@@ -573,21 +655,7 @@ // sanity check + if nf := len(txdata.frames); nf != 1 { + l.Log.Crit("Unexpected number of frames in calldata tx", "num_frames", nf) + } +- data := txdata.CallData() +- // if AltDA is enabled we post the txdata to the DA Provider and replace it with the commitment. +- if l.Config.UseAltDA { +- comm, err := l.AltDA.SetInput(ctx, data) +- if err != nil { +- l.Log.Error("Failed to post input to Alt DA", "error", err) +- // requeue frame if we fail to post to the DA Provider so it can be retried +- l.recordFailedTx(txdata.ID(), err) +- return nil +- } +- l.Log.Info("Set AltDA input", "commitment", comm, "tx", txdata.ID()) +- // signal AltDA commitment tx with TxDataVersion1 +- data = comm.TxData() +- } +- candidate = l.calldataTxCandidate(data) ++ candidate = l.calldataTxCandidate(txdata.CallData()) + } +  + l.sendTx(txdata, false, candidate, queue, receiptsCh) +@@ -597,7 +665,7 @@ + // sendTx uses the txmgr queue to send the given transaction candidate after setting its + // gaslimit. It will block if the txmgr queue has reached its MaxPendingTransactions limit. + func (l *BatchSubmitter) sendTx(txdata txData, isCancel bool, candidate *txmgr.TxCandidate, queue *txmgr.Queue[txRef], receiptsCh chan txmgr.TxReceipt[txRef]) { +- intrinsicGas, err := core.IntrinsicGas(candidate.TxData, nil, false, true, true, false) ++ intrinsicGas, err := core.IntrinsicGas(candidate.TxData, nil, false, true, true, false, nil, nil) + if err != nil { + // we log instead of return an error here because txmgr can do its own gas estimation + l.Log.Error("Failed to calculate intrinsic gas", "err", err) +@@ -647,6 +715,13 @@ return + } + l.lastL1Tip = l1tip + l.Metr.RecordLatestL1Block(l1tip) ++} ++ ++func (l *BatchSubmitter) recordFailedDARequest(id txID, err error) { ++ if err != nil { ++ l.Log.Warn("DA request failed", logFields(id, err)...) ++ } ++ l.state.TxFailed(id) + } +  + func (l *BatchSubmitter) recordFailedTx(id txID, err error) {
+
+ + +
+ @@ -23325,13 +105530,13 @@
- (new) + OP
@@ -23341,52 +105546,36 @@
-
+24
-
-0
+
+2
+
-1
-
diff --git OP/op-e2e/celo/package.json CELO/op-e2e/celo/package.json -new file mode 100644 -index 0000000000000000000000000000000000000000..ee0d66c7a7b5ce71517ccd992b2f81bc48e51f50 ---- /dev/null -+++ CELO/op-e2e/celo/package.json -@@ -0,0 +1,24 @@ -+{ -+ "name": "testsuite", -+ "version": "1.0.0", -+ "description": "", -+ "type": "module", -+ "main": "dist/test.js", -+ "scripts": { -+ "test": "jest tests --detectOpenHandles", -+ "format": "npx prettier . --write" -+ }, -+ "author": "Celo Labs Inc.", -+ "license": "ISC", -+ "dependencies": { -+ "reverse-mirage": "^1.1.0", -+ "viem": "^2.13.1" -+ }, -+ "devDependencies": { -+ "@babel/core": "^7.24.7", -+ "@babel/preset-env": "^7.24.7", -+ "babel-jest": "^29.7.0", -+ "jest": "^29.7.0", -+ "prettier": "3.3.3" -+ } -+}
+
diff --git OP/op-batcher/batcher/driver_test.go CELO/op-batcher/batcher/driver_test.go +index df72fa28d49ac46567746155313c124d6aa05856..5ce0983bfe1a79892bda94c747c61dd84a542ab2 100644 +--- OP/op-batcher/batcher/driver_test.go ++++ CELO/op-batcher/batcher/driver_test.go +@@ -49,7 +49,8 @@ + return NewBatchSubmitter(DriverSetup{ + Log: testlog.Logger(t, log.LevelDebug), + Metr: metrics.NoopMetrics, +- RollupConfig: &cfg, ++ RollupConfig: cfg, ++ ChannelConfig: defaultTestChannelConfig(), + EndpointProvider: ep, + }), ep + }
@@ -23395,13 +105584,13 @@
- (new) + OP
@@ -23411,84 +105600,137 @@
-
+56
-
-0
+
+8
+
-5
-
diff --git OP/op-e2e/celo/run_all_tests.sh CELO/op-e2e/celo/run_all_tests.sh -new file mode 100755 -index 0000000000000000000000000000000000000000..0021e440e032bad1862e8fde8c0ebcce2ccf2b9d ---- /dev/null -+++ CELO/op-e2e/celo/run_all_tests.sh -@@ -0,0 +1,56 @@ -+#!/bin/bash -+#shellcheck disable=SC1091 -+set -eo pipefail -+ -+SCRIPT_DIR=$(readlink -f "$(dirname "$0")") -+TEST_GLOB=$1 -+spawn_devnet=${SPAWN_DEVNET:-true} -+ -+if [[ $spawn_devnet != false ]]; then -+ ## Start geth -+ cd "$SCRIPT_DIR/../.." || exit 1 -+ trap 'cd "$SCRIPT_DIR/../.." && make devnet-down' EXIT # kill bg job at exit -+ DEVNET_CELO=true make devnet-up -+fi -+ -+cd "$SCRIPT_DIR" || exit 1 -+source "$SCRIPT_DIR/shared.sh" -+ -+# Wait for geth to be ready -+for _ in {1..10}; do -+ if cast block &>/dev/null; then -+ echo geth ready -+ break -+ fi -+ sleep 0.2 -+done -+ -+## Run tests -+echo Start tests -+failures=0 -+tests=0 -+for f in test_*"$TEST_GLOB"*; do -+ echo -e "\nRun $f" -+ if "./$f"; then -+ tput setaf 2 || true -+ echo "PASS $f" -+ else -+ tput setaf 1 || true -+ echo "FAIL $f ❌" -+ ((failures++)) || true -+ fi -+ tput sgr0 || true -+ ((tests++)) || true -+done -+ -+## Final summary -+echo -+if [[ $failures -eq 0 ]]; then -+ tput setaf 2 || true -+ echo All tests succeeded! -+else -+ tput setaf 1 || true -+ echo "$failures/$tests" failed. -+fi -+tput sgr0 || true -+exit "$failures"
+
diff --git OP/op-batcher/batcher/service.go CELO/op-batcher/batcher/service.go +index 00d3d32071f7fb89a5ad1c3e75d1a06eb0f8fdec..6ed906af15aa1db3e17791f34f5aa59afa72d2a8 100644 +--- OP/op-batcher/batcher/service.go ++++ CELO/op-batcher/batcher/service.go +@@ -39,6 +39,8 @@ + // UseAltDA is true if the rollup config has a DA challenge address so the batcher + // will post inputs to the DA server and post commitments to blobs or calldata. + UseAltDA bool ++ // maximum number of concurrent blob put requests to the DA server ++ MaxConcurrentDARequests uint64 +  + WaitNodeSync bool + CheckRecentTxsDepth int +@@ -51,7 +53,7 @@ Log log.Logger + Metrics metrics.Metricer + L1Client *ethclient.Client + EndpointProvider dial.L2EndpointProvider +- TxManager *txmgr.SimpleTxManager ++ TxManager txmgr.TxManager + AltDA *altda.DAClient +  + BatcherConfig +@@ -93,6 +95,7 @@ bs.initMetrics(cfg) +  + bs.PollInterval = cfg.PollInterval + bs.MaxPendingTransactions = cfg.MaxPendingTransactions ++ bs.MaxConcurrentDARequests = cfg.AltDA.MaxConcurrentRequests + bs.NetworkTimeout = cfg.TxMgrConfig.NetworkTimeout + bs.CheckRecentTxsDepth = cfg.CheckRecentTxsDepth + bs.WaitNodeSync = cfg.WaitNodeSync +@@ -104,6 +107,10 @@ return fmt.Errorf("failed to load rollup config: %w", err) + } + if err := bs.initTxManager(cfg); err != nil { + return fmt.Errorf("failed to init Tx manager: %w", err) ++ } ++ // must be init before driver and channel config ++ if err := bs.initAltDA(cfg); err != nil { ++ return fmt.Errorf("failed to init AltDA: %w", err) + } + if err := bs.initChannelConfig(cfg); err != nil { + return fmt.Errorf("failed to init channel config: %w", err) +@@ -114,10 +121,6 @@ return fmt.Errorf("failed to start metrics server: %w", err) + } + if err := bs.initPProf(cfg); err != nil { + return fmt.Errorf("failed to init profiling: %w", err) +- } +- // init before driver +- if err := bs.initAltDA(cfg); err != nil { +- return fmt.Errorf("failed to init AltDA: %w", err) + } + bs.initDriver() + if err := bs.initRPCServer(cfg); err != nil {
+ +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+6
+
-2
+ +
+ +
+
+
diff --git OP/op-batcher/batcher/test_batch_submitter.go CELO/op-batcher/batcher/test_batch_submitter.go +index 8814400f06ca7b5082344f6630c475ac34fe7d37..b959a8f3897c112a87b6bad703cdf506aff2d616 100644 +--- OP/op-batcher/batcher/test_batch_submitter.go ++++ CELO/op-batcher/batcher/test_batch_submitter.go +@@ -33,12 +33,16 @@ candidate = l.calldataTxCandidate([]byte{}) + } else if candidate, err = l.blobTxCandidate(emptyTxData); err != nil { + return err + } +- if candidate.GasLimit, err = core.IntrinsicGas(candidate.TxData, nil, false, true, true, false); err != nil { ++ if candidate.GasLimit, err = core.IntrinsicGas(candidate.TxData, nil, false, true, true, false, nil, nil); err != nil { + return err + } +  ++ simpleTxMgr, ok := l.Txmgr.(*txmgr.SimpleTxManager) ++ if !ok { ++ return errors.New("txmgr is not a SimpleTxManager") ++ } + l.ttm = &txmgr.TestTxManager{ +- SimpleTxManager: l.Txmgr, ++ SimpleTxManager: simpleTxMgr, + } + l.Log.Info("sending txpool blocking test tx") + if err := l.ttm.JamTxPool(ctx, *candidate); err != nil {
+
+ + +
@@ -23513,40 +105755,119 @@
-
+12
+
+91
-0
-
diff --git OP/op-e2e/celo/shared.sh CELO/op-e2e/celo/shared.sh +
diff --git OP/op-chain-ops/cmd/celo-migrate/testdata/deploy-config-dango.json CELO/op-chain-ops/cmd/celo-migrate/testdata/deploy-config-dango.json new file mode 100644 -index 0000000000000000000000000000000000000000..92e9be7be28ec1d52cd4b29af0204a1a8fa6791e +index 0000000000000000000000000000000000000000..dd69e13ab4f941e212e767152fdb6e2cfb315cfc --- /dev/null -+++ CELO/op-e2e/celo/shared.sh -@@ -0,0 +1,12 @@ -+#!/bin/bash -+#shellcheck disable=SC2034 # unused vars make sense in a shared file ++++ CELO/op-chain-ops/cmd/celo-migrate/testdata/deploy-config-dango.json +@@ -0,0 +1,91 @@ ++ { ++ "l1StartingBlockTag": "0xe18e94c26beea64e318e25c32303c9a1ee2bfcee4492337bb5ac14181e99bd0c", + -+export ETH_RPC_URL=http://localhost:9545 -+export ETH_RPC_URL_L1=http://localhost:8545 ++ "l1ChainID": 17000, ++ "l2ChainID": 44787, ++ "l2BlockTime": 2, ++ "l1BlockTime": 12, + -+export ACC_PRIVKEY=ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 -+ACC_ADDR=$(cast wallet address $ACC_PRIVKEY) -+export ACC_ADDR -+export REGISTRY_ADDR=0x000000000000000000000000000000000000ce10 -+export TOKEN_ADDR=0x471ece3750da237f93b8e339c536989b8978a438 -+export FEE_CURRENCY_DIRECTORY_ADDR=0x71FFbD48E34bdD5a87c3c683E866dc63b8B2a685
++ "maxSequencerDrift": 600, ++ "sequencerWindowSize": 3600, ++ "channelTimeout": 300, ++ ++ "p2pSequencerAddress": "0x644C82d76A43Fe9c76eda0EEd0f0DC17235c3005", ++ "batchInboxAddress": "0xff00000000000000000000000000000000044787", ++ "batchSenderAddress": "0x1660B1F70De0f32490b50f976e8983213dCF7FD5", ++ ++ "l2OutputOracleSubmissionInterval": 120, ++ "l2OutputOracleStartingBlockNumber": 26216760, ++ "l2OutputOracleStartingTimestamp": 1726651200, ++ ++ "l2OutputOracleProposer": "0x1BA11Ec6581FC8C3e35D6E345aEC977796Ffe89b", ++ "l2OutputOracleChallenger": "0xc07C5A1fBF6c7BC6b4f321E7dd031c0E1E98d32d", ++ ++ "finalizationPeriodSeconds": 12, ++ ++ "proxyAdminOwner": "0xc07C5A1fBF6c7BC6b4f321E7dd031c0E1E98d32d", ++ "baseFeeVaultRecipient": "0xc07C5A1fBF6c7BC6b4f321E7dd031c0E1E98d32d", ++ "l1FeeVaultRecipient": "0xc07C5A1fBF6c7BC6b4f321E7dd031c0E1E98d32d", ++ "sequencerFeeVaultRecipient": "0xc07C5A1fBF6c7BC6b4f321E7dd031c0E1E98d32d", ++ "finalSystemOwner": "0xc07C5A1fBF6c7BC6b4f321E7dd031c0E1E98d32d", ++ "superchainConfigGuardian": "0xc07C5A1fBF6c7BC6b4f321E7dd031c0E1E98d32d", ++ ++ "baseFeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000", ++ "l1FeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000", ++ "sequencerFeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000", ++ "baseFeeVaultWithdrawalNetwork": 0, ++ "l1FeeVaultWithdrawalNetwork": 0, ++ "sequencerFeeVaultWithdrawalNetwork": 0, ++ ++ "gasPriceOracleOverhead": 0, ++ "gasPriceOracleScalar": 1000000, ++ ++ "deployCeloContracts": false, ++ ++ "enableGovernance": false, ++ "governanceTokenSymbol": "OP", ++ "governanceTokenName": "Optimism", ++ "governanceTokenOwner": "0xc07C5A1fBF6c7BC6b4f321E7dd031c0E1E98d32d", ++ ++ "l2GenesisBlockGasLimit": "0x1c9c380", ++ "l2GenesisBlockBaseFeePerGas": "0x3b9aca00", ++ ++ "eip1559Denominator": 50, ++ "eip1559DenominatorCanyon": 250, ++ "eip1559Elasticity": 6, ++ "l2GenesisFjordTimeOffset": "0x0", ++ "l2GenesisRegolithTimeOffset": "0x0", ++ "l2GenesisEcotoneTimeOffset": "0x0", ++ "l2GenesisDeltaTimeOffset": "0x0", ++ "l2GenesisCanyonTimeOffset": "0x0", ++ "systemConfigStartBlock": 0, ++ ++ "requiredProtocolVersion": "0x0000000000000000000000000000000000000000000000000000000000000000", ++ "recommendedProtocolVersion": "0x0000000000000000000000000000000000000000000000000000000000000000", ++ ++ "faultGameAbsolutePrestate": "0x03c7ae758795765c6664a5d39bf63841c71ff191e9189522bad8ebff5d4eca98", ++ "faultGameMaxDepth": 44, ++ "faultGameClockExtension": 0, ++ "faultGameMaxClockDuration": 1200, ++ "faultGameGenesisBlock": 0, ++ "faultGameGenesisOutputRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", ++ "faultGameSplitDepth": 14, ++ "faultGameWithdrawalDelay": 600, ++ ++ "preimageOracleMinProposalSize": 1800000, ++ "preimageOracleChallengePeriod": 300, ++ ++ "fundDevAccounts": false, ++ "useFaultProofs": false, ++ "proofMaturityDelaySeconds": 604800, ++ "disputeGameFinalityDelaySeconds": 302400, ++ "respectedGameType": 0, ++ ++ "useAltDA": true, ++ "daCommitmentType": "GenericCommitment", ++ "daChallengeWindow": 1, ++ "daResolveWindow": 1, ++ ++ "useCustomGasToken": true, ++ "customGasTokenAddress": "0x0000000000000000000000000000000000000000" ++}
@@ -23571,686 +105892,19421 @@
-
+658
-
-0
+
+90
+
-0
+ +
+ +
+
+
diff --git OP/op-chain-ops/cmd/celo-migrate/testdata/deploy-config-holesky-alfajores.json CELO/op-chain-ops/cmd/celo-migrate/testdata/deploy-config-holesky-alfajores.json +new file mode 100644 +index 0000000000000000000000000000000000000000..0c8dee05d9c5b94f42bc97845fdf66da9b255a4c +--- /dev/null ++++ CELO/op-chain-ops/cmd/celo-migrate/testdata/deploy-config-holesky-alfajores.json +@@ -0,0 +1,90 @@ ++{ ++ "l1StartingBlockTag": "0xbbed3612407993e67f8ca7a423b181837ae164a531941e78f5ee48e766d39cad", ++ ++ "l1ChainID": 17000, ++ "l2ChainID": 44787, ++ "l2BlockTime": 2, ++ "l1BlockTime": 12, ++ ++ "maxSequencerDrift": 600, ++ "sequencerWindowSize": 3600, ++ "channelTimeout": 300, ++ ++ "p2pSequencerAddress": "0x644C82d76A43Fe9c76eda0EEd0f0DC17235c3005", ++ "batchInboxAddress": "0xff00000000000000000000000000000000044787", ++ "batchSenderAddress": "0x1660B1F70De0f32490b50f976e8983213dCF7FD5", ++ ++ "l2OutputOracleSubmissionInterval": 120, ++ "l2OutputOracleStartingBlockNumber": 0, ++ "l2OutputOracleStartingTimestamp": 1718312256, ++ ++ "l2OutputOracleProposer": "0x1BA11Ec6581FC8C3e35D6E345aEC977796Ffe89b", ++ "l2OutputOracleChallenger": "0xc07C5A1fBF6c7BC6b4f321E7dd031c0E1E98d32d", ++ ++ "finalizationPeriodSeconds": 12, ++ ++ "proxyAdminOwner": "0xc07C5A1fBF6c7BC6b4f321E7dd031c0E1E98d32d", ++ "baseFeeVaultRecipient": "0xc07C5A1fBF6c7BC6b4f321E7dd031c0E1E98d32d", ++ "l1FeeVaultRecipient": "0xc07C5A1fBF6c7BC6b4f321E7dd031c0E1E98d32d", ++ "sequencerFeeVaultRecipient": "0xc07C5A1fBF6c7BC6b4f321E7dd031c0E1E98d32d", ++ "finalSystemOwner": "0xc07C5A1fBF6c7BC6b4f321E7dd031c0E1E98d32d", ++ "superchainConfigGuardian": "0xc07C5A1fBF6c7BC6b4f321E7dd031c0E1E98d32d", ++ ++ "baseFeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000", ++ "l1FeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000", ++ "sequencerFeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000", ++ "baseFeeVaultWithdrawalNetwork": 0, ++ "l1FeeVaultWithdrawalNetwork": 0, ++ "sequencerFeeVaultWithdrawalNetwork": 0, ++ ++ "gasPriceOracleOverhead": 0, ++ "gasPriceOracleScalar": 1000000, ++ ++ "enableGovernance": false, ++ "governanceTokenSymbol": "OP", ++ "governanceTokenName": "Optimism", ++ "governanceTokenOwner": "0xc07C5A1fBF6c7BC6b4f321E7dd031c0E1E98d32d", ++ ++ "l2GenesisBlockGasLimit": "0x1c9c380", ++ "l2GenesisBlockBaseFeePerGas": "0x3b9aca00", ++ "l2GenesisRegolithTimeOffset": "0x0", ++ ++ "eip1559Denominator": 50, ++ "eip1559DenominatorCanyon": 250, ++ "eip1559Elasticity": 6, ++ ++ "l2GenesisGraniteTimeOffset": "0x0", ++ "l2GenesisEcotoneTimeOffset": "0x0", ++ "l2GenesisDeltaTimeOffset": "0x0", ++ "l2GenesisCanyonTimeOffset": "0x0", ++ ++ "systemConfigStartBlock": 0, ++ ++ "requiredProtocolVersion": "0x0000000000000000000000000000000000000000000000000000000000000000", ++ "recommendedProtocolVersion": "0x0000000000000000000000000000000000000000000000000000000000000000", ++ ++ "faultGameAbsolutePrestate": "0x03c7ae758795765c6664a5d39bf63841c71ff191e9189522bad8ebff5d4eca98", ++ "faultGameMaxDepth": 44, ++ "faultGameClockExtension": 0, ++ "faultGameMaxClockDuration": 600, ++ "faultGameGenesisBlock": 0, ++ "faultGameGenesisOutputRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", ++ "faultGameSplitDepth": 14, ++ "faultGameWithdrawalDelay": 604800, ++ ++ "preimageOracleMinProposalSize": 1800000, ++ "preimageOracleChallengePeriod": 86400, ++ ++ "fundDevAccounts": false, ++ "useFaultProofs": false, ++ "proofMaturityDelaySeconds": 604800, ++ "disputeGameFinalityDelaySeconds": 302400, ++ "respectedGameType": 0, ++ ++ "usePlasma": false, ++ "daCommitmentType": "KeccakCommitment", ++ "daChallengeWindow": 160, ++ "daResolveWindow": 160, ++ "daBondSize": 1000000, ++ "daResolverRefundPercentage": 0 ++}
+
+ + +
+ + +
+
+
+ + (new)
- -
-
-
diff --git OP/op-e2e/celo/src/OptimismPortal.js CELO/op-e2e/celo/src/OptimismPortal.js -new file mode 100644 -index 0000000000000000000000000000000000000000..80b02f38341420bc72c43c39150aaf591dfa09fa ---- /dev/null -+++ CELO/op-e2e/celo/src/OptimismPortal.js -@@ -0,0 +1,658 @@ -+export const OptimismPortalABI = [ -+ { -+ type: 'constructor', -+ inputs: [], -+ stateMutability: 'nonpayable', -+ }, -+ { -+ type: 'receive', -+ stateMutability: 'payable', -+ }, -+ { -+ type: 'function', -+ name: 'balance', -+ inputs: [], -+ outputs: [ -+ { -+ name: '', -+ type: 'uint256', -+ internalType: 'uint256', -+ }, -+ ], -+ stateMutability: 'view', -+ }, -+ { -+ type: 'function', -+ name: 'depositERC20Transaction', -+ inputs: [ -+ { -+ name: '_to', -+ type: 'address', -+ internalType: 'address', -+ }, -+ { -+ name: '_mint', -+ type: 'uint256', -+ internalType: 'uint256', -+ }, -+ { -+ name: '_value', -+ type: 'uint256', -+ internalType: 'uint256', -+ }, -+ { -+ name: '_gasLimit', -+ type: 'uint64', -+ internalType: 'uint64', -+ }, -+ { -+ name: '_isCreation', -+ type: 'bool', -+ internalType: 'bool', -+ }, -+ { -+ name: '_data', -+ type: 'bytes', -+ internalType: 'bytes', -+ }, -+ ], -+ outputs: [], -+ stateMutability: 'nonpayable', -+ }, -+ { -+ type: 'function', -+ name: 'depositTransaction', -+ inputs: [ -+ { -+ name: '_to', -+ type: 'address', -+ internalType: 'address', -+ }, -+ { -+ name: '_value', -+ type: 'uint256', -+ internalType: 'uint256', -+ }, -+ { -+ name: '_gasLimit', -+ type: 'uint64', -+ internalType: 'uint64', -+ }, -+ { -+ name: '_isCreation', -+ type: 'bool', -+ internalType: 'bool', -+ }, -+ { -+ name: '_data', -+ type: 'bytes', -+ internalType: 'bytes', -+ }, -+ ], -+ outputs: [], -+ stateMutability: 'payable', -+ }, -+ { -+ type: 'function', -+ name: 'donateETH', -+ inputs: [], -+ outputs: [], -+ stateMutability: 'payable', -+ }, -+ { -+ type: 'function', -+ name: 'finalizeWithdrawalTransaction', -+ inputs: [ -+ { -+ name: '_tx', -+ type: 'tuple', -+ internalType: 'struct Types.WithdrawalTransaction', -+ components: [ -+ { -+ name: 'nonce', -+ type: 'uint256', -+ internalType: 'uint256', -+ }, -+ { -+ name: 'sender', -+ type: 'address', -+ internalType: 'address', -+ }, -+ { -+ name: 'target', -+ type: 'address', -+ internalType: 'address', -+ }, -+ { -+ name: 'value', -+ type: 'uint256', -+ internalType: 'uint256', -+ }, -+ { -+ name: 'gasLimit', -+ type: 'uint256', -+ internalType: 'uint256', -+ }, -+ { -+ name: 'data', -+ type: 'bytes', -+ internalType: 'bytes', -+ }, -+ ], -+ }, -+ ], -+ outputs: [], -+ stateMutability: 'nonpayable', -+ }, -+ { -+ type: 'function', -+ name: 'finalizedWithdrawals', -+ inputs: [ -+ { -+ name: '', -+ type: 'bytes32', -+ internalType: 'bytes32', -+ }, -+ ], -+ outputs: [ -+ { -+ name: '', -+ type: 'bool', -+ internalType: 'bool', -+ }, -+ ], -+ stateMutability: 'view', -+ }, -+ { -+ type: 'function', -+ name: 'guardian', -+ inputs: [], -+ outputs: [ -+ { -+ name: '', -+ type: 'address', -+ internalType: 'address', -+ }, -+ ], -+ stateMutability: 'view', -+ }, -+ { -+ type: 'function', -+ name: 'initialize', -+ inputs: [ -+ { -+ name: '_l2Oracle', -+ type: 'address', -+ internalType: 'contract L2OutputOracle', -+ }, -+ { -+ name: '_systemConfig', -+ type: 'address', -+ internalType: 'contract SystemConfig', -+ }, -+ { -+ name: '_superchainConfig', -+ type: 'address', -+ internalType: 'contract SuperchainConfig', -+ }, -+ { -+ name: '_initialBalance', -+ type: 'uint256', -+ internalType: 'uint256', -+ }, -+ ], -+ outputs: [], -+ stateMutability: 'nonpayable', -+ }, -+ { -+ type: 'function', -+ name: 'isOutputFinalized', -+ inputs: [ -+ { -+ name: '_l2OutputIndex', -+ type: 'uint256', -+ internalType: 'uint256', -+ }, -+ ], -+ outputs: [ -+ { -+ name: '', -+ type: 'bool', -+ internalType: 'bool', -+ }, -+ ], -+ stateMutability: 'view', -+ }, -+ { -+ type: 'function', -+ name: 'l2Oracle', -+ inputs: [], -+ outputs: [ -+ { -+ name: '', -+ type: 'address', -+ internalType: 'contract L2OutputOracle', -+ }, -+ ], -+ stateMutability: 'view', -+ }, -+ { -+ type: 'function', -+ name: 'l2Sender', -+ inputs: [], -+ outputs: [ -+ { -+ name: '', -+ type: 'address', -+ internalType: 'address', -+ }, -+ ], -+ stateMutability: 'view', -+ }, -+ { -+ type: 'function', -+ name: 'minimumGasLimit', -+ inputs: [ -+ { -+ name: '_byteCount', -+ type: 'uint64', -+ internalType: 'uint64', -+ }, -+ ], -+ outputs: [ -+ { -+ name: '', -+ type: 'uint64', -+ internalType: 'uint64', -+ }, -+ ], -+ stateMutability: 'pure', -+ }, -+ { -+ type: 'function', -+ name: 'params', -+ inputs: [], -+ outputs: [ -+ { -+ name: 'prevBaseFee', -+ type: 'uint128', -+ internalType: 'uint128', -+ }, -+ { -+ name: 'prevBoughtGas', -+ type: 'uint64', -+ internalType: 'uint64', -+ }, -+ { -+ name: 'prevBlockNum', -+ type: 'uint64', -+ internalType: 'uint64', -+ }, -+ ], -+ stateMutability: 'view', -+ }, -+ { -+ type: 'function', -+ name: 'paused', -+ inputs: [], -+ outputs: [ -+ { -+ name: 'paused_', -+ type: 'bool', -+ internalType: 'bool', -+ }, -+ ], -+ stateMutability: 'view', -+ }, -+ { -+ type: 'function', -+ name: 'proveWithdrawalTransaction', -+ inputs: [ -+ { -+ name: '_tx', -+ type: 'tuple', -+ internalType: 'struct Types.WithdrawalTransaction', -+ components: [ -+ { -+ name: 'nonce', -+ type: 'uint256', -+ internalType: 'uint256', -+ }, -+ { -+ name: 'sender', -+ type: 'address', -+ internalType: 'address', -+ }, -+ { -+ name: 'target', -+ type: 'address', -+ internalType: 'address', -+ }, -+ { -+ name: 'value', -+ type: 'uint256', -+ internalType: 'uint256', -+ }, -+ { -+ name: 'gasLimit', -+ type: 'uint256', -+ internalType: 'uint256', -+ }, -+ { -+ name: 'data', -+ type: 'bytes', -+ internalType: 'bytes', -+ }, -+ ], -+ }, -+ { -+ name: '_l2OutputIndex', -+ type: 'uint256', -+ internalType: 'uint256', -+ }, -+ { -+ name: '_outputRootProof', -+ type: 'tuple', -+ internalType: 'struct Types.OutputRootProof', -+ components: [ -+ { -+ name: 'version', -+ type: 'bytes32', -+ internalType: 'bytes32', -+ }, -+ { -+ name: 'stateRoot', -+ type: 'bytes32', -+ internalType: 'bytes32', -+ }, -+ { -+ name: 'messagePasserStorageRoot', -+ type: 'bytes32', -+ internalType: 'bytes32', -+ }, -+ { -+ name: 'latestBlockhash', -+ type: 'bytes32', -+ internalType: 'bytes32', -+ }, -+ ], -+ }, -+ { -+ name: '_withdrawalProof', -+ type: 'bytes[]', -+ internalType: 'bytes[]', -+ }, -+ ], -+ outputs: [], -+ stateMutability: 'nonpayable', -+ }, -+ { -+ type: 'function', -+ name: 'provenWithdrawals', -+ inputs: [ -+ { -+ name: '', -+ type: 'bytes32', -+ internalType: 'bytes32', -+ }, -+ ], -+ outputs: [ -+ { -+ name: 'outputRoot', -+ type: 'bytes32', -+ internalType: 'bytes32', -+ }, -+ { -+ name: 'timestamp', -+ type: 'uint128', -+ internalType: 'uint128', -+ }, -+ { -+ name: 'l2OutputIndex', -+ type: 'uint128', -+ internalType: 'uint128', -+ }, -+ ], -+ stateMutability: 'view', -+ }, -+ { -+ type: 'function', -+ name: 'setGasPayingToken', -+ inputs: [ -+ { -+ name: '_token', -+ type: 'address', -+ internalType: 'address', -+ }, -+ { -+ name: '_decimals', -+ type: 'uint8', -+ internalType: 'uint8', -+ }, -+ { -+ name: '_name', -+ type: 'bytes32', -+ internalType: 'bytes32', -+ }, -+ { -+ name: '_symbol', -+ type: 'bytes32', -+ internalType: 'bytes32', -+ }, -+ ], -+ outputs: [], -+ stateMutability: 'nonpayable', -+ }, -+ { -+ type: 'function', -+ name: 'superchainConfig', -+ inputs: [], -+ outputs: [ -+ { -+ name: '', -+ type: 'address', -+ internalType: 'contract SuperchainConfig', -+ }, -+ ], -+ stateMutability: 'view', -+ }, -+ { -+ type: 'function', -+ name: 'systemConfig', -+ inputs: [], -+ outputs: [ -+ { -+ name: '', -+ type: 'address', -+ internalType: 'contract SystemConfig', -+ }, -+ ], -+ stateMutability: 'view', -+ }, -+ { -+ type: 'function', -+ name: 'version', -+ inputs: [], -+ outputs: [ -+ { -+ name: '', -+ type: 'string', -+ internalType: 'string', -+ }, -+ ], -+ stateMutability: 'view', -+ }, -+ { -+ type: 'event', -+ name: 'Initialized', -+ inputs: [ -+ { -+ name: 'version', -+ type: 'uint8', -+ indexed: false, -+ internalType: 'uint8', -+ }, -+ ], -+ anonymous: false, + +
+ + CELO + +
+
+
+ +
+ +
+ +
+36
+
-0
+ +
+ +
+
+
diff --git OP/op-chain-ops/cmd/celo-migrate/testdata/deployment-l1-dango.json CELO/op-chain-ops/cmd/celo-migrate/testdata/deployment-l1-dango.json +new file mode 100644 +index 0000000000000000000000000000000000000000..58c1f74772ed173da257ce7ab3fb5a03bad32d9a +--- /dev/null ++++ CELO/op-chain-ops/cmd/celo-migrate/testdata/deployment-l1-dango.json +@@ -0,0 +1,37 @@ ++{ ++ "AddressManager": "0x5Ab3E4093B06a69954885caDAF29b280613c674f", ++ "AnchorStateRegistry": "0x5b530E1DD25513F0Da1CC39333f6fa91143884aB", ++ "AnchorStateRegistryProxy": "0xCCb982Cc00F9Cc970f71AF753Ff834e9AadADad6", ++ "CustomGasToken": "0xf7a83872810aBea270FAFF54206A522AB53f3df1", ++ "CustomGasTokenProxy": "0x3c300204B89F8A333350d9FfE72352D990DDA36f", ++ "DelayedWETH": "0x9eC20144141099E0c0581ABe0C507aCd2B07Da68", ++ "DelayedWETHProxy": "0xb0b158f73CF23c2edc220E586Bd043CB1b69c5Ad", ++ "DisputeGameFactory": "0x88ca8D6b24b691F617C9A02Ce8179F23C13e13Ae", ++ "DisputeGameFactoryProxy": "0x3889C8BA734148dec7A31472B4A370BC7fc3E50c", ++ "L1CrossDomainMessenger": "0xDb787d88Fa092d7144053138023137b01b2FB1af", ++ "L1CrossDomainMessengerProxy": "0x4401780183661b211a9ED386D56b400E430b0995", ++ "L1ERC721Bridge": "0x442Cc0A770Cd776930a14C0d3363a2931aBE273b", ++ "L1ERC721BridgeProxy": "0xC262D512A52D4F90D7Bc221979A584857Ab90dd9", ++ "L1StandardBridge": "0x3D4712d8cA71b8f5ae918213421e098761415898", ++ "L1StandardBridgeProxy": "0x59f2BDd9674c8C7c5750b12a004783da9a992e5A", ++ "L2OutputOracle": "0x1dd308d7e3aC77ea70f3c7069b29350665ab57F4", ++ "L2OutputOracleProxy": "0xD31bf46c090Ea08191fd11BFbf0758fAbeE468cC", ++ "Mips": "0x30f82aD995f412FBC3386022270AB071e616CaEA", ++ "OptimismMintableERC20Factory": "0x4626Da66AEE29bC145c7B04614437Aa6540D82F2", ++ "OptimismMintableERC20FactoryProxy": "0xabcd2bd6a5bc474287Fc460aD99F70d42711AA33", ++ "OptimismPortal": "0xD10c0833b38b47662200A026d60f0c891ea6C960", ++ "OptimismPortal2": "0xAAcC881F37e45CAb4C57A6757DE0334FC5b4DE7F", ++ "OptimismPortalProxy": "0xf550A0aEc6cD8fDFA904242d6e07F71E38BE5240", ++ "PermissionedDelayedWETHProxy": "0x85E318CE71dE55c19290Fa22149cC773526C8987", ++ "PreimageOracle": "0x2c010f9f6A63234d03baB647788633Fd5000410A", ++ "ProtocolVersions": "0x9233fCE30bfb57de432B1a8cf0Cad87A12011eFC", ++ "ProtocolVersionsProxy": "0x4CE6aDa5fef5BffD2f13257aAF5a40efd412C8E7", ++ "ProxyAdmin": "0x9f03734bE814De3652C757B3a5702BfE99BA0098", ++ "SafeProxyFactory": "0xa6B71E26C5e0845f74c812102Ca7114b6a896AB2", ++ "SafeSingleton": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", ++ "SuperchainConfig": "0x05B71600Fe59197339837509F702da31F9fa5cf3", ++ "SuperchainConfigProxy": "0xDDfcA11fD8553C6Fc1185aD5f492230c3A0091E3", ++ "SystemConfig": "0x5b10806e8068B517eaBd8DeD5B872034f31878F9", ++ "SystemConfigProxy": "0xFbe6510A1E209d9E2148d54F134f4E5634bE7241", ++ "SystemOwnerSafe": "0xD751beb42dBcde9BDe9E2866c0490DccA6A11Ba9" ++} +\ No newline at end of file
+ + + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+34
+
-0
+ +
+ +
+
+
diff --git OP/op-chain-ops/cmd/celo-migrate/testdata/deployment-l1-holesky.json CELO/op-chain-ops/cmd/celo-migrate/testdata/deployment-l1-holesky.json +new file mode 100644 +index 0000000000000000000000000000000000000000..b37b79f4d4c8f1ee70c7aae7e7f351713226b8a3 +--- /dev/null ++++ CELO/op-chain-ops/cmd/celo-migrate/testdata/deployment-l1-holesky.json +@@ -0,0 +1,34 @@ ++{ ++ "AddressManager": "0x2d256f3b82f673Ee377C393fBF2Cf3DcA5D1D901", ++ "AnchorStateRegistry": "0x036fDE501893043825356Ce49dfd554809F07597", ++ "AnchorStateRegistryProxy": "0xe5077701c64782954d27384da76D95ABf320460f", ++ "DelayedWETH": "0x408Ad04Dd953958B080226025E17d6Ba12987EB7", ++ "DelayedWETHProxy": "0x27f7Ade64F031A39553Be8104bF8B0b410735845", ++ "DisputeGameFactory": "0xd7771F9687804Bba1D360B08AD9e4d8CB4523738", ++ "DisputeGameFactoryProxy": "0x193FdDF22D31c227f1Af1286cf2B051d701FF86E", ++ "L1CrossDomainMessenger": "0x1e3513a619AA4f2550CDD95709B92C1FE0397184", ++ "L1CrossDomainMessengerProxy": "0x35841aC1f5FdC5b812562adB17F6A0B9A178F643", ++ "L1ERC721Bridge": "0x695b01393f0539ec64AC316d4998E4130309efB0", ++ "L1ERC721BridgeProxy": "0x2b9C1e5b9a0D01256388cc4A0F8F290E839F2d82", ++ "L1StandardBridge": "0x2d1A818544b657Bc5d1E8c8B80F953bd0CA1C9B2", ++ "L1StandardBridgeProxy": "0xD10A531CB9b80BD507501F34D87Ad4083E9b7F98", ++ "L2OutputOracle": "0x04CD14625ff0Da62d6E0820a816b4dD3eCd0FF27", ++ "L2OutputOracleProxy": "0x5636f9D582DB69EAf1Eb9f05B0738225C91fBC1E", ++ "Mips": "0x60E1b8b535626Fc9fFCdf6147B45879634645771", ++ "OptimismMintableERC20Factory": "0x3fcd69a03857aA6e79AE9408fc7c887EE70FC145", ++ "OptimismMintableERC20FactoryProxy": "0x23c80F2503b93a58EC620D20b6b9B6AB8cCa2a12", ++ "OptimismPortal": "0xdF803FAC1d84a31Ff5aee841f11659f9a3787CE5", ++ "OptimismPortal2": "0x60bc423dDf0B24fa5104EcacAC5000674Ac3EBfB", ++ "OptimismPortalProxy": "0xa292B051eA58e2558243f4A9f74262B1796c9648", ++ "PreimageOracle": "0xEC19353B7364Fb85b9b0A57EaEEC6aCeBbFb6a53", ++ "ProtocolVersions": "0x077d61D4fb3378025950Bb60AD69179B38921107", ++ "ProtocolVersionsProxy": "0x791D5101840A547F1EE91148d34E061412A57ECD", ++ "ProxyAdmin": "0x4ddC758DA1697Ad58D86D03150872c042390dCa2", ++ "SafeProxyFactory": "0xa6B71E26C5e0845f74c812102Ca7114b6a896AB2", ++ "SafeSingleton": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", ++ "SuperchainConfig": "0xA4f7dB67A6e098613B107be3F8441475Ec30FCC2", ++ "SuperchainConfigProxy": "0xB21214DA32a85A0d43372310D62095cf91d67765", ++ "SystemConfig": "0xeFA98Ba3ada6c6AC4bB84074820685E1F01C835d", ++ "SystemConfigProxy": "0x733043Aa78d25F6759d9e6Ce2B2897bE6d630E08", ++ "SystemOwnerSafe": "0xD2a6B91aB77691D6F8688eAFA7a5f188bc5baA3a" ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+42
+
-0
+ +
+ +
+
+
diff --git OP/op-chain-ops/cmd/celo-migrate/testdata/rollup-config-dango.json CELO/op-chain-ops/cmd/celo-migrate/testdata/rollup-config-dango.json +new file mode 100644 +index 0000000000000000000000000000000000000000..83de52fa1acebe25c1489c6465bbe6a8a84155b8 +--- /dev/null ++++ CELO/op-chain-ops/cmd/celo-migrate/testdata/rollup-config-dango.json +@@ -0,0 +1,42 @@ ++{ ++ "genesis": { ++ "l1": { ++ "hash": "0xe18e94c26beea64e318e25c32303c9a1ee2bfcee4492337bb5ac14181e99bd0c", ++ "number": 2358856 ++ }, ++ "l2": { ++ "hash": "0x0e1287f3eba321cb620a032d4d26978424e15b0533e1d19e870baeb1f0078e10", ++ "number": 25275061 ++ }, ++ "l2_time": 1726651200, ++ "system_config": { ++ "batcherAddr": "0x1660b1f70de0f32490b50f976e8983213dcf7fd5", ++ "overhead": "0x0000000000000000000000000000000000000000000000000000000000000000", ++ "scalar": "0x00000000000000000000000000000000000000000000000000000000000f4240", ++ "gasLimit": 30000000 ++ } + }, -+ { -+ type: 'event', -+ name: 'TransactionDeposited', -+ inputs: [ -+ { -+ name: 'from', -+ type: 'address', -+ indexed: true, -+ internalType: 'address', -+ }, -+ { -+ name: 'to', -+ type: 'address', -+ indexed: true, -+ internalType: 'address', -+ }, -+ { -+ name: 'version', -+ type: 'uint256', -+ indexed: true, -+ internalType: 'uint256', -+ }, -+ { -+ name: 'opaqueData', -+ type: 'bytes', -+ indexed: false, -+ internalType: 'bytes', -+ }, -+ ], -+ anonymous: false, ++ "block_time": 2, ++ "max_sequencer_drift": 600, ++ "seq_window_size": 3600, ++ "channel_timeout": 300, ++ "l1_chain_id": 17000, ++ "l2_chain_id": 44787, ++ "regolith_time": 0, ++ "cel2_time": 0, ++ "canyon_time": 0, ++ "delta_time": 0, ++ "ecotone_time": 0, ++ "fjord_time": 0, ++ "batch_inbox_address": "0xff00000000000000000000000000000000044787", ++ "deposit_contract_address": "0xf550a0aec6cd8fdfa904242d6e07f71e38be5240", ++ "l1_system_config_address": "0xfbe6510a1e209d9e2148d54f134f4e5634be7241", ++ "protocol_versions_address": "0x0000000000000000000000000000000000000000", ++ "alt_da": { ++ "da_challenge_contract_address": "0x0000000000000000000000000000000000000000", ++ "da_commitment_type": "GenericCommitment", ++ "da_challenge_window": 1, ++ "da_resolve_window": 1 ++ } ++} ++
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+36
+
-0
+ +
+ +
+
+
diff --git OP/op-chain-ops/cmd/celo-migrate/testdata/rollup-config.json CELO/op-chain-ops/cmd/celo-migrate/testdata/rollup-config.json +new file mode 100644 +index 0000000000000000000000000000000000000000..8dfd1f25e28d86be0d6188ab982c2439b077a2f0 +--- /dev/null ++++ CELO/op-chain-ops/cmd/celo-migrate/testdata/rollup-config.json +@@ -0,0 +1,36 @@ ++{ ++ "genesis": { ++ "l1": { ++ "hash": "0xbbed3612407993e67f8ca7a423b181837ae164a531941e78f5ee48e766d39cad", ++ "number": 1729797 ++ }, ++ "l2": { ++ "hash": "0x2664d0a1f45dc9a010e553e815a25f33c6d949cbb0d38e179c6209fc0486aa41", ++ "number": 23912613 ++ }, ++ "l2_time": 1718312256, ++ "system_config": { ++ "batcherAddr": "0x1660b1f70de0f32490b50f976e8983213dcf7fd5", ++ "overhead": "0x0000000000000000000000000000000000000000000000000000000000000000", ++ "scalar": "0x00000000000000000000000000000000000000000000000000000000000f4240", ++ "gasLimit": 30000000 ++ } + }, ++ "block_time": 2, ++ "max_sequencer_drift": 600, ++ "seq_window_size": 3600, ++ "channel_timeout": 300, ++ "l1_chain_id": 17000, ++ "l2_chain_id": 44787, ++ "regolith_time": 0, ++ "cel2_time": 0, ++ "canyon_time": 0, ++ "delta_time": 0, ++ "ecotone_time": 0, ++ "batch_inbox_address": "0xff00000000000000000000000000000000044787", ++ "deposit_contract_address": "0xa292b051ea58e2558243f4a9f74262b1796c9648", ++ "l1_system_config_address": "0x733043aa78d25f6759d9e6ce2b2897be6d630e08", ++ "protocol_versions_address": "0x0000000000000000000000000000000000000000", ++ "da_challenge_contract_address": "0x0000000000000000000000000000000000000000" ++} ++
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ + (binary file) + +
+
+
diff --git OP/op-chain-ops/deployer/pipeline/testdata/artifacts.tar.gz CELO/op-chain-ops/deployer/pipeline/testdata/artifacts.tar.gz +new file mode 100644 +index 0000000000000000000000000000000000000000..58f034254f46aa79a18fcfaa10429b447e08c78d +Binary files /dev/null and CELO/op-chain-ops/deployer/pipeline/testdata/artifacts.tar.gz differ
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+80
+
-0
+ +
+ +
+
+
diff --git OP/op-chain-ops/script/testdata/scripts/ScriptExample.s.sol CELO/op-chain-ops/script/testdata/scripts/ScriptExample.s.sol +index 4c1dcf6275f2d373f5e0bd21a2826c0140003d7b..f2f20e5ca14e9e12a1a18f3e4a0ba4a9eb8ce80a 100644 +--- OP/op-chain-ops/script/testdata/scripts/ScriptExample.s.sol ++++ CELO/op-chain-ops/script/testdata/scripts/ScriptExample.s.sol +@@ -8,6 +8,11 @@ function getNonce(address account) external view returns (uint64 nonce); + function parseJsonKeys(string calldata json, string calldata key) external pure returns (string[] memory keys); + function startPrank(address msgSender) external; + function stopPrank() external; ++ function broadcast() external; ++ function broadcast(address msgSender) external; ++ function startBroadcast(address msgSender) external; ++ function startBroadcast() external; ++ function stopBroadcast() external; + } +  + // console is a minimal version of the console2 lib. +@@ -64,6 +69,9 @@ + address internal constant VM_ADDRESS = address(uint160(uint256(keccak256("hevm cheat code")))); + Vm internal constant vm = Vm(VM_ADDRESS); +  ++ // @notice counter variable to force non-pure calls. ++ uint256 public counter; ++ + /// @notice example function, runs through basic cheat-codes and console logs. + function run() public { + bool x = vm.envOr("EXAMPLE_BOOL", false); +@@ -90,9 +98,81 @@ + console.log("done!"); + } +  ++ /// @notice example function, to test vm.broadcast with. ++ function runBroadcast() public { ++ console.log("nonce start", uint256(vm.getNonce(address(this)))); ++ ++ console.log("testing single"); ++ vm.broadcast(); ++ this.call1("single_call1"); ++ this.call2("single_call2"); ++ ++ console.log("testing start/stop"); ++ vm.startBroadcast(address(uint160(0xc0ffee))); ++ this.call1("startstop_call1"); ++ this.call2("startstop_call2"); ++ this.callPure("startstop_pure"); ++ vm.stopBroadcast(); ++ this.call1("startstop_call3"); ++ ++ console.log("testing nested"); ++ vm.startBroadcast(address(uint160(0x1234))); ++ this.nested1("nested"); ++ vm.stopBroadcast(); ++ ++ console.log("contract deployment"); ++ vm.broadcast(address(uint160(0x123456))); ++ FooBar x = new FooBar(1234); ++ require(x.foo() == 1234); ++ ++ console.log("create 2"); ++ vm.broadcast(address(uint160(0xcafe))); ++ FooBar y = new FooBar{salt: bytes32(uint256(42))}(1234); ++ require(y.foo() == 1234); ++ console.log("done!"); ++ ++ // Deploy a script without a pranked sender and check the nonce. ++ vm.broadcast(); ++ new FooBar(1234); ++ ++ console.log("nonce end", uint256(vm.getNonce(address(this)))); ++ } ++ + /// @notice example external function, to force a CALL, and test vm.startPrank with. + function hello(string calldata _v) external view { + console.log(_v); + console.log("hello msg.sender", address(msg.sender)); ++ } ++ ++ function call1(string calldata _v) external { ++ counter++; ++ console.log(_v); ++ } ++ ++ function call2(string calldata _v) external { ++ counter++; ++ console.log(_v); ++ } ++ ++ function nested1(string calldata _v) external { ++ counter++; ++ this.nested2(_v); ++ } ++ ++ function nested2(string calldata _v) external { ++ counter++; ++ console.log(_v); ++ } ++ ++ function callPure(string calldata _v) external pure { ++ console.log(_v); ++ } ++} ++ ++contract FooBar { ++ uint256 public foo; ++ ++ constructor(uint256 v) { ++ foo = v; + } + }
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+0
+
-0
+ +
+ +
+
+
diff --git OP/op-chain-ops/script/testdata/test-artifacts/ScriptExample.s.sol/FooBar.json CELO/op-chain-ops/script/testdata/test-artifacts/ScriptExample.s.sol/FooBar.json +new file mode 100644 +index 0000000000000000000000000000000000000000..ad4ac1569433c8a3337b9cf5d78f1f09ca27c330 +--- /dev/null ++++ CELO/op-chain-ops/script/testdata/test-artifacts/ScriptExample.s.sol/FooBar.json +@@ -0,0 +1 @@ ++{"abi":[{"type":"constructor","inputs":[{"name":"v","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"type":"function","name":"foo","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"}],"bytecode":{"object":"0x608060405234801561001057600080fd5b506040516100b23803806100b283398101604081905261002f91610037565b600055610050565b60006020828403121561004957600080fd5b5051919050565b60548061005e6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063c298557814602d575b600080fd5b603560005481565b60405190815260200160405180910390f3fea164736f6c634300080f000a","sourceMap":"5902:96:0:-:0;;;5949:47;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5982:3;:7;5902:96;;14:184:1;84:6;137:2;125:9;116:7;112:23;108:32;105:52;;;153:1;150;143:12;105:52;-1:-1:-1;176:16:1;;14:184;-1:-1:-1;14:184:1:o;:::-;5902:96:0;;;;;;","linkReferences":{}},"deployedBytecode":{"object":"0x6080604052348015600f57600080fd5b506004361060285760003560e01c8063c298557814602d575b600080fd5b603560005481565b60405190815260200160405180910390f3fea164736f6c634300080f000a","sourceMap":"5902:96:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5924:18;;;;;;;;;160:25:1;;;148:2;133:18;5924::0;;;;;;","linkReferences":{}},"methodIdentifiers":{"foo()":"c2985578"},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"v\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"foo\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"scripts/ScriptExample.s.sol\":\"FooBar\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[]},\"sources\":{\"scripts/ScriptExample.s.sol\":{\"keccak256\":\"0x8d1dfa41908e7ccc3a498a2a2aa51c5275bedbb904ce32d08f8598e36f896d8d\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://5117bb7158363cae8b9dc0508d2852692fd36172f1c699ff680afbb5acebe1f3\",\"dweb:/ipfs/QmQdahJ8SPKfJ4yea5Ge9qaj5qh1TxVffhHvaWytBaL95h\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.15+commit.e14f2714"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"uint256","name":"v","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"stateMutability":"view","type":"function","name":"foo","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]}],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"remappings":[],"optimizer":{"enabled":true,"runs":999999},"metadata":{"bytecodeHash":"none"},"compilationTarget":{"scripts/ScriptExample.s.sol":"FooBar"},"evmVersion":"london","libraries":{}},"sources":{"scripts/ScriptExample.s.sol":{"keccak256":"0x8d1dfa41908e7ccc3a498a2a2aa51c5275bedbb904ce32d08f8598e36f896d8d","urls":["bzz-raw://5117bb7158363cae8b9dc0508d2852692fd36172f1c699ff680afbb5acebe1f3","dweb:/ipfs/QmQdahJ8SPKfJ4yea5Ge9qaj5qh1TxVffhHvaWytBaL95h"],"license":"MIT"}},"version":1},"storageLayout":{"storage":[{"astId":708,"contract":"scripts/ScriptExample.s.sol:FooBar","label":"foo","offset":0,"slot":"0","type":"t_uint256"}],"types":{"t_uint256":{"encoding":"inplace","label":"uint256","numberOfBytes":"32"}}},"userdoc":{"version":1,"kind":"user"},"devdoc":{"version":1,"kind":"dev"},"ast":{"absolutePath":"scripts/ScriptExample.s.sol","id":720,"exportedSymbols":{"FooBar":[719],"ScriptExample":[706],"Vm":[55],"console":[192]},"nodeType":"SourceUnit","src":"32:5967:0","nodes":[{"id":1,"nodeType":"PragmaDirective","src":"32:23:0","nodes":[],"literals":["solidity","0.8",".15"]},{"id":55,"nodeType":"ContractDefinition","src":"120:616:0","nodes":[{"id":10,"nodeType":"FunctionDefinition","src":"139:91:0","nodes":[],"functionSelector":"4777f3cf","implemented":false,"kind":"function","modifiers":[],"name":"envOr","nameLocation":"148:5:0","parameters":{"id":6,"nodeType":"ParameterList","parameters":[{"constant":false,"id":3,"mutability":"mutable","name":"name","nameLocation":"170:4:0","nodeType":"VariableDeclaration","scope":10,"src":"154:20:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":2,"name":"string","nodeType":"ElementaryTypeName","src":"154:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":5,"mutability":"mutable","name":"defaultValue","nameLocation":"181:12:0","nodeType":"VariableDeclaration","scope":10,"src":"176:17:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":4,"name":"bool","nodeType":"ElementaryTypeName","src":"176:4:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"src":"153:41:0"},"returnParameters":{"id":9,"nodeType":"ParameterList","parameters":[{"constant":false,"id":8,"mutability":"mutable","name":"value","nameLocation":"223:5:0","nodeType":"VariableDeclaration","scope":10,"src":"218:10:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":7,"name":"bool","nodeType":"ElementaryTypeName","src":"218:4:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"src":"217:12:0"},"scope":55,"stateMutability":"view","virtual":false,"visibility":"external"},{"id":17,"nodeType":"FunctionDefinition","src":"235:72:0","nodes":[],"functionSelector":"2d0335ab","implemented":false,"kind":"function","modifiers":[],"name":"getNonce","nameLocation":"244:8:0","parameters":{"id":13,"nodeType":"ParameterList","parameters":[{"constant":false,"id":12,"mutability":"mutable","name":"account","nameLocation":"261:7:0","nodeType":"VariableDeclaration","scope":17,"src":"253:15:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":11,"name":"address","nodeType":"ElementaryTypeName","src":"253:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"252:17:0"},"returnParameters":{"id":16,"nodeType":"ParameterList","parameters":[{"constant":false,"id":15,"mutability":"mutable","name":"nonce","nameLocation":"300:5:0","nodeType":"VariableDeclaration","scope":17,"src":"293:12:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"},"typeName":{"id":14,"name":"uint64","nodeType":"ElementaryTypeName","src":"293:6:0","typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}},"visibility":"internal"}],"src":"292:14:0"},"scope":55,"stateMutability":"view","virtual":false,"visibility":"external"},{"id":27,"nodeType":"FunctionDefinition","src":"312:111:0","nodes":[],"functionSelector":"213e4198","implemented":false,"kind":"function","modifiers":[],"name":"parseJsonKeys","nameLocation":"321:13:0","parameters":{"id":22,"nodeType":"ParameterList","parameters":[{"constant":false,"id":19,"mutability":"mutable","name":"json","nameLocation":"351:4:0","nodeType":"VariableDeclaration","scope":27,"src":"335:20:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":18,"name":"string","nodeType":"ElementaryTypeName","src":"335:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":21,"mutability":"mutable","name":"key","nameLocation":"373:3:0","nodeType":"VariableDeclaration","scope":27,"src":"357:19:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":20,"name":"string","nodeType":"ElementaryTypeName","src":"357:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"334:43:0"},"returnParameters":{"id":26,"nodeType":"ParameterList","parameters":[{"constant":false,"id":25,"mutability":"mutable","name":"keys","nameLocation":"417:4:0","nodeType":"VariableDeclaration","scope":27,"src":"401:20:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string[]"},"typeName":{"baseType":{"id":23,"name":"string","nodeType":"ElementaryTypeName","src":"401:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"id":24,"nodeType":"ArrayTypeName","src":"401:8:0","typeDescriptions":{"typeIdentifier":"t_array$_t_string_storage_$dyn_storage_ptr","typeString":"string[]"}},"visibility":"internal"}],"src":"400:22:0"},"scope":55,"stateMutability":"pure","virtual":false,"visibility":"external"},{"id":32,"nodeType":"FunctionDefinition","src":"428:48:0","nodes":[],"functionSelector":"06447d56","implemented":false,"kind":"function","modifiers":[],"name":"startPrank","nameLocation":"437:10:0","parameters":{"id":30,"nodeType":"ParameterList","parameters":[{"constant":false,"id":29,"mutability":"mutable","name":"msgSender","nameLocation":"456:9:0","nodeType":"VariableDeclaration","scope":32,"src":"448:17:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":28,"name":"address","nodeType":"ElementaryTypeName","src":"448:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"447:19:0"},"returnParameters":{"id":31,"nodeType":"ParameterList","parameters":[],"src":"475:0:0"},"scope":55,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":35,"nodeType":"FunctionDefinition","src":"481:30:0","nodes":[],"functionSelector":"90c5013b","implemented":false,"kind":"function","modifiers":[],"name":"stopPrank","nameLocation":"490:9:0","parameters":{"id":33,"nodeType":"ParameterList","parameters":[],"src":"499:2:0"},"returnParameters":{"id":34,"nodeType":"ParameterList","parameters":[],"src":"510:0:0"},"scope":55,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":38,"nodeType":"FunctionDefinition","src":"516:30:0","nodes":[],"functionSelector":"afc98040","implemented":false,"kind":"function","modifiers":[],"name":"broadcast","nameLocation":"525:9:0","parameters":{"id":36,"nodeType":"ParameterList","parameters":[],"src":"534:2:0"},"returnParameters":{"id":37,"nodeType":"ParameterList","parameters":[],"src":"545:0:0"},"scope":55,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":43,"nodeType":"FunctionDefinition","src":"551:47:0","nodes":[],"functionSelector":"e6962cdb","implemented":false,"kind":"function","modifiers":[],"name":"broadcast","nameLocation":"560:9:0","parameters":{"id":41,"nodeType":"ParameterList","parameters":[{"constant":false,"id":40,"mutability":"mutable","name":"msgSender","nameLocation":"578:9:0","nodeType":"VariableDeclaration","scope":43,"src":"570:17:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":39,"name":"address","nodeType":"ElementaryTypeName","src":"570:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"569:19:0"},"returnParameters":{"id":42,"nodeType":"ParameterList","parameters":[],"src":"597:0:0"},"scope":55,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":48,"nodeType":"FunctionDefinition","src":"603:52:0","nodes":[],"functionSelector":"7fec2a8d","implemented":false,"kind":"function","modifiers":[],"name":"startBroadcast","nameLocation":"612:14:0","parameters":{"id":46,"nodeType":"ParameterList","parameters":[{"constant":false,"id":45,"mutability":"mutable","name":"msgSender","nameLocation":"635:9:0","nodeType":"VariableDeclaration","scope":48,"src":"627:17:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":44,"name":"address","nodeType":"ElementaryTypeName","src":"627:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"626:19:0"},"returnParameters":{"id":47,"nodeType":"ParameterList","parameters":[],"src":"654:0:0"},"scope":55,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":51,"nodeType":"FunctionDefinition","src":"660:35:0","nodes":[],"functionSelector":"7fb5297f","implemented":false,"kind":"function","modifiers":[],"name":"startBroadcast","nameLocation":"669:14:0","parameters":{"id":49,"nodeType":"ParameterList","parameters":[],"src":"683:2:0"},"returnParameters":{"id":50,"nodeType":"ParameterList","parameters":[],"src":"694:0:0"},"scope":55,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":54,"nodeType":"FunctionDefinition","src":"700:34:0","nodes":[],"functionSelector":"76eadd36","implemented":false,"kind":"function","modifiers":[],"name":"stopBroadcast","nameLocation":"709:13:0","parameters":{"id":52,"nodeType":"ParameterList","parameters":[],"src":"722:2:0"},"returnParameters":{"id":53,"nodeType":"ParameterList","parameters":[],"src":"733:0:0"},"scope":55,"stateMutability":"nonpayable","virtual":false,"visibility":"external"}],"abstract":false,"baseContracts":[],"canonicalName":"Vm","contractDependencies":[],"contractKind":"interface","fullyImplemented":false,"linearizedBaseContracts":[55],"name":"Vm","nameLocation":"130:2:0","scope":720,"usedErrors":[]},{"id":192,"nodeType":"ContractDefinition","src":"791:1622:0","nodes":[{"id":61,"nodeType":"VariableDeclaration","src":"813:86:0","nodes":[],"constant":true,"mutability":"constant","name":"CONSOLE_ADDRESS","nameLocation":"830:15:0","scope":192,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":56,"name":"address","nodeType":"ElementaryTypeName","src":"813:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"value":{"arguments":[{"hexValue":"307830303030303030303030303030303030303036333646366537333646366336353265366336663637","id":59,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"856:42:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"value":"0x000000000000000000636F6e736F6c652e6c6f67"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":58,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"848:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":57,"name":"address","nodeType":"ElementaryTypeName","src":"848:7:0","typeDescriptions":{}}},"id":60,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"848:51:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"},{"id":78,"nodeType":"FunctionDefinition","src":"906:221:0","nodes":[],"body":{"id":77,"nodeType":"Block","src":"1065:62:0","nodes":[],"statements":[{"AST":{"nodeType":"YulBlock","src":"1084:37:0","statements":[{"nodeType":"YulAssignment","src":"1098:13:0","value":{"name":"fnIn","nodeType":"YulIdentifier","src":"1107:4:0"},"variableNames":[{"name":"fnOut","nodeType":"YulIdentifier","src":"1098:5:0"}]}]},"evmVersion":"london","externalReferences":[{"declaration":67,"isOffset":false,"isSlot":false,"src":"1107:4:0","valueSize":1},{"declaration":74,"isOffset":false,"isSlot":false,"src":"1098:5:0","valueSize":1}],"id":76,"nodeType":"InlineAssembly","src":"1075:46:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"_castLogPayloadViewToPure","nameLocation":"915:25:0","parameters":{"id":68,"nodeType":"ParameterList","parameters":[{"constant":false,"id":67,"mutability":"mutable","name":"fnIn","nameLocation":"987:4:0","nodeType":"VariableDeclaration","scope":78,"src":"950:41:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_function_internal_view$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes) view"},"typeName":{"id":66,"nodeType":"FunctionTypeName","parameterTypes":{"id":64,"nodeType":"ParameterList","parameters":[{"constant":false,"id":63,"mutability":"mutable","name":"","nameLocation":"-1:-1:-1","nodeType":"VariableDeclaration","scope":66,"src":"959:12:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":62,"name":"bytes","nodeType":"ElementaryTypeName","src":"959:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"958:14:0"},"returnParameterTypes":{"id":65,"nodeType":"ParameterList","parameters":[],"src":"987:0:0"},"src":"950:41:0","stateMutability":"view","typeDescriptions":{"typeIdentifier":"t_function_internal_view$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes) view"},"visibility":"internal"},"visibility":"internal"}],"src":"940:57:0"},"returnParameters":{"id":75,"nodeType":"ParameterList","parameters":[{"constant":false,"id":74,"mutability":"mutable","name":"fnOut","nameLocation":"1058:5:0","nodeType":"VariableDeclaration","scope":78,"src":"1021:42:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes) pure"},"typeName":{"id":73,"nodeType":"FunctionTypeName","parameterTypes":{"id":71,"nodeType":"ParameterList","parameters":[{"constant":false,"id":70,"mutability":"mutable","name":"","nameLocation":"-1:-1:-1","nodeType":"VariableDeclaration","scope":73,"src":"1030:12:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":69,"name":"bytes","nodeType":"ElementaryTypeName","src":"1030:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"1029:14:0"},"returnParameterTypes":{"id":72,"nodeType":"ParameterList","parameters":[],"src":"1058:0:0"},"src":"1021:42:0","stateMutability":"pure","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes) pure"},"visibility":"internal"},"visibility":"internal"}],"src":"1020:44:0"},"scope":192,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":90,"nodeType":"FunctionDefinition","src":"1133:133:0","nodes":[],"body":{"id":89,"nodeType":"Block","src":"1194:72:0","nodes":[],"statements":[{"expression":{"arguments":[{"id":86,"name":"payload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":80,"src":"1251:7:0","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"arguments":[{"id":84,"name":"_sendLogPayloadView","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":106,"src":"1230:19:0","typeDescriptions":{"typeIdentifier":"t_function_internal_view$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) view"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_function_internal_view$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) view"}],"id":83,"name":"_castLogPayloadViewToPure","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":78,"src":"1204:25:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_function_internal_view$_t_bytes_memory_ptr_$returns$__$_$returns$_t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$_$","typeString":"function (function (bytes memory) view) pure returns (function (bytes memory) pure)"}},"id":85,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1204:46:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":87,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1204:55:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":88,"nodeType":"ExpressionStatement","src":"1204:55:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"_sendLogPayload","nameLocation":"1142:15:0","parameters":{"id":81,"nodeType":"ParameterList","parameters":[{"constant":false,"id":80,"mutability":"mutable","name":"payload","nameLocation":"1171:7:0","nodeType":"VariableDeclaration","scope":90,"src":"1158:20:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":79,"name":"bytes","nodeType":"ElementaryTypeName","src":"1158:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"1157:22:0"},"returnParameters":{"id":82,"nodeType":"ParameterList","parameters":[],"src":"1194:0:0"},"scope":192,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":106,"nodeType":"FunctionDefinition","src":"1272:380:0","nodes":[],"body":{"id":105,"nodeType":"Block","src":"1336:316:0","nodes":[],"statements":[{"assignments":[96],"declarations":[{"constant":false,"id":96,"mutability":"mutable","name":"payloadLength","nameLocation":"1354:13:0","nodeType":"VariableDeclaration","scope":105,"src":"1346:21:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":95,"name":"uint256","nodeType":"ElementaryTypeName","src":"1346:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"}],"id":99,"initialValue":{"expression":{"id":97,"name":"payload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":92,"src":"1370:7:0","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}},"id":98,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"length","nodeType":"MemberAccess","src":"1370:14:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"nodeType":"VariableDeclarationStatement","src":"1346:38:0"},{"assignments":[101],"declarations":[{"constant":false,"id":101,"mutability":"mutable","name":"consoleAddress","nameLocation":"1402:14:0","nodeType":"VariableDeclaration","scope":105,"src":"1394:22:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":100,"name":"address","nodeType":"ElementaryTypeName","src":"1394:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"id":103,"initialValue":{"id":102,"name":"CONSOLE_ADDRESS","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":61,"src":"1419:15:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"nodeType":"VariableDeclarationStatement","src":"1394:40:0"},{"AST":{"nodeType":"YulBlock","src":"1496:150:0","statements":[{"nodeType":"YulVariableDeclaration","src":"1510:36:0","value":{"arguments":[{"name":"payload","nodeType":"YulIdentifier","src":"1534:7:0"},{"kind":"number","nodeType":"YulLiteral","src":"1543:2:0","type":"","value":"32"}],"functionName":{"name":"add","nodeType":"YulIdentifier","src":"1530:3:0"},"nodeType":"YulFunctionCall","src":"1530:16:0"},"variables":[{"name":"payloadStart","nodeType":"YulTypedName","src":"1514:12:0","type":""}]},{"nodeType":"YulVariableDeclaration","src":"1559:77:0","value":{"arguments":[{"arguments":[],"functionName":{"name":"gas","nodeType":"YulIdentifier","src":"1579:3:0"},"nodeType":"YulFunctionCall","src":"1579:5:0"},{"name":"consoleAddress","nodeType":"YulIdentifier","src":"1586:14:0"},{"name":"payloadStart","nodeType":"YulIdentifier","src":"1602:12:0"},{"name":"payloadLength","nodeType":"YulIdentifier","src":"1616:13:0"},{"kind":"number","nodeType":"YulLiteral","src":"1631:1:0","type":"","value":"0"},{"kind":"number","nodeType":"YulLiteral","src":"1634:1:0","type":"","value":"0"}],"functionName":{"name":"staticcall","nodeType":"YulIdentifier","src":"1568:10:0"},"nodeType":"YulFunctionCall","src":"1568:68:0"},"variables":[{"name":"r","nodeType":"YulTypedName","src":"1563:1:0","type":""}]}]},"documentation":"@solidity memory-safe-assembly","evmVersion":"london","externalReferences":[{"declaration":101,"isOffset":false,"isSlot":false,"src":"1586:14:0","valueSize":1},{"declaration":92,"isOffset":false,"isSlot":false,"src":"1534:7:0","valueSize":1},{"declaration":96,"isOffset":false,"isSlot":false,"src":"1616:13:0","valueSize":1}],"id":104,"nodeType":"InlineAssembly","src":"1487:159:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"_sendLogPayloadView","nameLocation":"1281:19:0","parameters":{"id":93,"nodeType":"ParameterList","parameters":[{"constant":false,"id":92,"mutability":"mutable","name":"payload","nameLocation":"1314:7:0","nodeType":"VariableDeclaration","scope":106,"src":"1301:20:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":91,"name":"bytes","nodeType":"ElementaryTypeName","src":"1301:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"1300:22:0"},"returnParameters":{"id":94,"nodeType":"ParameterList","parameters":[],"src":"1336:0:0"},"scope":192,"stateMutability":"view","virtual":false,"visibility":"private"},{"id":120,"nodeType":"FunctionDefinition","src":"1658:121:0","nodes":[],"body":{"id":119,"nodeType":"Block","src":"1703:76:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e6729","id":114,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"1753:13:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_41304facd9323d75b11bcdd609cb38effffdb05710f7caf0e9b16c6d9d709f50","typeString":"literal_string \"log(string)\""},"value":"log(string)"},{"id":115,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":108,"src":"1768:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_41304facd9323d75b11bcdd609cb38effffdb05710f7caf0e9b16c6d9d709f50","typeString":"literal_string \"log(string)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}],"expression":{"id":112,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"1729:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":113,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"1729:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":116,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1729:42:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":111,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":90,"src":"1713:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":117,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1713:59:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":118,"nodeType":"ExpressionStatement","src":"1713:59:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"1667:3:0","parameters":{"id":109,"nodeType":"ParameterList","parameters":[{"constant":false,"id":108,"mutability":"mutable","name":"p0","nameLocation":"1685:2:0","nodeType":"VariableDeclaration","scope":120,"src":"1671:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":107,"name":"string","nodeType":"ElementaryTypeName","src":"1671:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"1670:18:0"},"returnParameters":{"id":110,"nodeType":"ParameterList","parameters":[],"src":"1703:0:0"},"scope":192,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":137,"nodeType":"FunctionDefinition","src":"1785:139:0","nodes":[],"body":{"id":136,"nodeType":"Block","src":"1839:85:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e672c626f6f6c29","id":130,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"1889:18:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_c3b556354c088fbb43886eb83c2a04bc7089663f964d22be308197a236f5b870","typeString":"literal_string \"log(string,bool)\""},"value":"log(string,bool)"},{"id":131,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":122,"src":"1909:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":132,"name":"p1","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":124,"src":"1913:2:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_c3b556354c088fbb43886eb83c2a04bc7089663f964d22be308197a236f5b870","typeString":"literal_string \"log(string,bool)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_bool","typeString":"bool"}],"expression":{"id":128,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"1865:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":129,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"1865:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":133,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1865:51:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":127,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":90,"src":"1849:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":134,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1849:68:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":135,"nodeType":"ExpressionStatement","src":"1849:68:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"1794:3:0","parameters":{"id":125,"nodeType":"ParameterList","parameters":[{"constant":false,"id":122,"mutability":"mutable","name":"p0","nameLocation":"1812:2:0","nodeType":"VariableDeclaration","scope":137,"src":"1798:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":121,"name":"string","nodeType":"ElementaryTypeName","src":"1798:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":124,"mutability":"mutable","name":"p1","nameLocation":"1821:2:0","nodeType":"VariableDeclaration","scope":137,"src":"1816:7:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":123,"name":"bool","nodeType":"ElementaryTypeName","src":"1816:4:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"src":"1797:27:0"},"returnParameters":{"id":126,"nodeType":"ParameterList","parameters":[],"src":"1839:0:0"},"scope":192,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":154,"nodeType":"FunctionDefinition","src":"1930:145:0","nodes":[],"body":{"id":153,"nodeType":"Block","src":"1987:88:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e672c75696e7432353629","id":147,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2037:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_b60e72ccf6d57ab53eb84d7e94a9545806ed7f93c4d5673f11a64f03471e584e","typeString":"literal_string \"log(string,uint256)\""},"value":"log(string,uint256)"},{"id":148,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":139,"src":"2060:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":149,"name":"p1","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":141,"src":"2064:2:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_b60e72ccf6d57ab53eb84d7e94a9545806ed7f93c4d5673f11a64f03471e584e","typeString":"literal_string \"log(string,uint256)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_uint256","typeString":"uint256"}],"expression":{"id":145,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"2013:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":146,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"2013:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":150,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2013:54:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":144,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":90,"src":"1997:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":151,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1997:71:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":152,"nodeType":"ExpressionStatement","src":"1997:71:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"1939:3:0","parameters":{"id":142,"nodeType":"ParameterList","parameters":[{"constant":false,"id":139,"mutability":"mutable","name":"p0","nameLocation":"1957:2:0","nodeType":"VariableDeclaration","scope":154,"src":"1943:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":138,"name":"string","nodeType":"ElementaryTypeName","src":"1943:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":141,"mutability":"mutable","name":"p1","nameLocation":"1969:2:0","nodeType":"VariableDeclaration","scope":154,"src":"1961:10:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":140,"name":"uint256","nodeType":"ElementaryTypeName","src":"1961:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"}],"src":"1942:30:0"},"returnParameters":{"id":143,"nodeType":"ParameterList","parameters":[],"src":"1987:0:0"},"scope":192,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":171,"nodeType":"FunctionDefinition","src":"2081:145:0","nodes":[],"body":{"id":170,"nodeType":"Block","src":"2138:88:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e672c6164647265737329","id":164,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2188:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_319af333460570a1937bf195dd33445c0d0951c59127da6f1f038b9fdce3fd72","typeString":"literal_string \"log(string,address)\""},"value":"log(string,address)"},{"id":165,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":156,"src":"2211:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":166,"name":"p1","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":158,"src":"2215:2:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_319af333460570a1937bf195dd33445c0d0951c59127da6f1f038b9fdce3fd72","typeString":"literal_string \"log(string,address)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":162,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"2164:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":163,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"2164:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":167,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2164:54:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":161,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":90,"src":"2148:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":168,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2148:71:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":169,"nodeType":"ExpressionStatement","src":"2148:71:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"2090:3:0","parameters":{"id":159,"nodeType":"ParameterList","parameters":[{"constant":false,"id":156,"mutability":"mutable","name":"p0","nameLocation":"2108:2:0","nodeType":"VariableDeclaration","scope":171,"src":"2094:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":155,"name":"string","nodeType":"ElementaryTypeName","src":"2094:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":158,"mutability":"mutable","name":"p1","nameLocation":"2120:2:0","nodeType":"VariableDeclaration","scope":171,"src":"2112:10:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":157,"name":"address","nodeType":"ElementaryTypeName","src":"2112:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"2093:30:0"},"returnParameters":{"id":160,"nodeType":"ParameterList","parameters":[],"src":"2138:0:0"},"scope":192,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":191,"nodeType":"FunctionDefinition","src":"2232:179:0","nodes":[],"body":{"id":190,"nodeType":"Block","src":"2313:98:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e672c737472696e672c737472696e6729","id":183,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2363:27:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_2ced7cef693312206c21f0e92e3b54e2e16bf33db5eec350c78866822c665e1f","typeString":"literal_string \"log(string,string,string)\""},"value":"log(string,string,string)"},{"id":184,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"2392:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":185,"name":"p1","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":175,"src":"2396:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":186,"name":"p2","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":177,"src":"2400:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_2ced7cef693312206c21f0e92e3b54e2e16bf33db5eec350c78866822c665e1f","typeString":"literal_string \"log(string,string,string)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}],"expression":{"id":181,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"2339:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":182,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"2339:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":187,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2339:64:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":180,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":90,"src":"2323:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":188,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2323:81:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":189,"nodeType":"ExpressionStatement","src":"2323:81:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"2241:3:0","parameters":{"id":178,"nodeType":"ParameterList","parameters":[{"constant":false,"id":173,"mutability":"mutable","name":"p0","nameLocation":"2259:2:0","nodeType":"VariableDeclaration","scope":191,"src":"2245:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":172,"name":"string","nodeType":"ElementaryTypeName","src":"2245:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":175,"mutability":"mutable","name":"p1","nameLocation":"2277:2:0","nodeType":"VariableDeclaration","scope":191,"src":"2263:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":174,"name":"string","nodeType":"ElementaryTypeName","src":"2263:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":177,"mutability":"mutable","name":"p2","nameLocation":"2295:2:0","nodeType":"VariableDeclaration","scope":191,"src":"2281:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":176,"name":"string","nodeType":"ElementaryTypeName","src":"2281:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"2244:54:0"},"returnParameters":{"id":179,"nodeType":"ParameterList","parameters":[],"src":"2313:0:0"},"scope":192,"stateMutability":"pure","virtual":false,"visibility":"internal"}],"abstract":false,"baseContracts":[],"canonicalName":"console","contractDependencies":[],"contractKind":"library","fullyImplemented":true,"linearizedBaseContracts":[192],"name":"console","nameLocation":"799:7:0","scope":720,"usedErrors":[]},{"id":706,"nodeType":"ContractDefinition","src":"2541:3359:0","nodes":[{"id":207,"nodeType":"VariableDeclaration","src":"2571:94:0","nodes":[],"constant":true,"mutability":"constant","name":"VM_ADDRESS","nameLocation":"2597:10:0","scope":706,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":194,"name":"address","nodeType":"ElementaryTypeName","src":"2571:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"value":{"arguments":[{"arguments":[{"arguments":[{"arguments":[{"hexValue":"6865766d20636865617420636f6465","id":202,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2644:17:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d","typeString":"literal_string \"hevm cheat code\""},"value":"hevm cheat code"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d","typeString":"literal_string \"hevm cheat code\""}],"id":201,"name":"keccak256","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-8,"src":"2634:9:0","typeDescriptions":{"typeIdentifier":"t_function_keccak256_pure$_t_bytes_memory_ptr_$returns$_t_bytes32_$","typeString":"function (bytes memory) pure returns (bytes32)"}},"id":203,"isConstant":false,"isLValue":false,"isPure":true,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2634:28:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes32","typeString":"bytes32"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes32","typeString":"bytes32"}],"id":200,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2626:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint256_$","typeString":"type(uint256)"},"typeName":{"id":199,"name":"uint256","nodeType":"ElementaryTypeName","src":"2626:7:0","typeDescriptions":{}}},"id":204,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2626:37:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint256","typeString":"uint256"}],"id":198,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2618:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":197,"name":"uint160","nodeType":"ElementaryTypeName","src":"2618:7:0","typeDescriptions":{}}},"id":205,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2618:46:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":196,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2610:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":195,"name":"address","nodeType":"ElementaryTypeName","src":"2610:7:0","typeDescriptions":{}}},"id":206,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2610:55:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"},{"id":213,"nodeType":"VariableDeclaration","src":"2671:40:0","nodes":[],"constant":true,"mutability":"constant","name":"vm","nameLocation":"2692:2:0","scope":706,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"},"typeName":{"id":209,"nodeType":"UserDefinedTypeName","pathNode":{"id":208,"name":"Vm","nodeType":"IdentifierPath","referencedDeclaration":55,"src":"2671:2:0"},"referencedDeclaration":55,"src":"2671:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"value":{"arguments":[{"id":211,"name":"VM_ADDRESS","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":207,"src":"2700:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":210,"name":"Vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":55,"src":"2697:2:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_Vm_$55_$","typeString":"type(contract Vm)"}},"id":212,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2697:14:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"visibility":"internal"},{"id":215,"nodeType":"VariableDeclaration","src":"2775:22:0","nodes":[],"constant":false,"functionSelector":"61bc221a","mutability":"mutable","name":"counter","nameLocation":"2790:7:0","scope":706,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":214,"name":"uint256","nodeType":"ElementaryTypeName","src":"2775:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"public"},{"id":378,"nodeType":"FunctionDefinition","src":"2887:949:0","nodes":[],"body":{"id":377,"nodeType":"Block","src":"2909:927:0","nodes":[],"statements":[{"assignments":[220],"declarations":[{"constant":false,"id":220,"mutability":"mutable","name":"x","nameLocation":"2924:1:0","nodeType":"VariableDeclaration","scope":377,"src":"2919:6:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":219,"name":"bool","nodeType":"ElementaryTypeName","src":"2919:4:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"id":226,"initialValue":{"arguments":[{"hexValue":"4558414d504c455f424f4f4c","id":223,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2937:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_a634dae177a0e138ae7aaa2afae347412e148992e88c7aabd33ee71be146cb7f","typeString":"literal_string \"EXAMPLE_BOOL\""},"value":"EXAMPLE_BOOL"},{"hexValue":"66616c7365","id":224,"isConstant":false,"isLValue":false,"isPure":true,"kind":"bool","lValueRequested":false,"nodeType":"Literal","src":"2953:5:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"value":"false"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_a634dae177a0e138ae7aaa2afae347412e148992e88c7aabd33ee71be146cb7f","typeString":"literal_string \"EXAMPLE_BOOL\""},{"typeIdentifier":"t_bool","typeString":"bool"}],"expression":{"id":221,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"2928:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":222,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"envOr","nodeType":"MemberAccess","referencedDeclaration":10,"src":"2928:8:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$_t_bool_$returns$_t_bool_$","typeString":"function (string memory,bool) view external returns (bool)"}},"id":225,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2928:31:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"nodeType":"VariableDeclarationStatement","src":"2919:40:0"},{"expression":{"arguments":[{"hexValue":"626f6f6c2076616c75652066726f6d20656e76","id":230,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2981:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_5a607d0b5a1295325aa8901721d78ba402601bba6f62cebdd5235dd0204a590b","typeString":"literal_string \"bool value from env\""},"value":"bool value from env"},{"id":231,"name":"x","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":220,"src":"3004:1:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_5a607d0b5a1295325aa8901721d78ba402601bba6f62cebdd5235dd0204a590b","typeString":"literal_string \"bool value from env\""},{"typeIdentifier":"t_bool","typeString":"bool"}],"expression":{"id":227,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"2969:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":229,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":137,"src":"2969:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_bool_$returns$__$","typeString":"function (string memory,bool) pure"}},"id":232,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2969:37:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":233,"nodeType":"ExpressionStatement","src":"2969:37:0"},{"expression":{"arguments":[{"hexValue":"636f6e74726163742061646472","id":237,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3029:15:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_fa50728770d00fe8f6a0592f3565bbfaf063ee4077f1f5bbc003d091d33cd0c4","typeString":"literal_string \"contract addr\""},"value":"contract addr"},{"arguments":[{"id":240,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3054:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}],"id":239,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3046:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":238,"name":"address","nodeType":"ElementaryTypeName","src":"3046:7:0","typeDescriptions":{}}},"id":241,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3046:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_fa50728770d00fe8f6a0592f3565bbfaf063ee4077f1f5bbc003d091d33cd0c4","typeString":"literal_string \"contract addr\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":234,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3017:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":236,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":171,"src":"3017:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":242,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3017:43:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":243,"nodeType":"ExpressionStatement","src":"3017:43:0"},{"expression":{"arguments":[{"hexValue":"636f6e7472616374206e6f6e6365","id":247,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3082:16:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_3a23091615a5de8c0a35ffd8857a37e2c4e0b72f3ef8a34d6caf65efcd562e2f","typeString":"literal_string \"contract nonce\""},"value":"contract nonce"},{"arguments":[{"arguments":[{"id":252,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3120:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}],"id":251,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3112:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":250,"name":"address","nodeType":"ElementaryTypeName","src":"3112:7:0","typeDescriptions":{}}},"id":253,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3112:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":248,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"3100:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":249,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"getNonce","nodeType":"MemberAccess","referencedDeclaration":17,"src":"3100:11:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_address_$returns$_t_uint64_$","typeString":"function (address) view external returns (uint64)"}},"id":254,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3100:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_3a23091615a5de8c0a35ffd8857a37e2c4e0b72f3ef8a34d6caf65efcd562e2f","typeString":"literal_string \"contract nonce\""},{"typeIdentifier":"t_uint64","typeString":"uint64"}],"expression":{"id":244,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3070:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":246,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":154,"src":"3070:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_uint256_$returns$__$","typeString":"function (string memory,uint256) pure"}},"id":255,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3070:57:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":256,"nodeType":"ExpressionStatement","src":"3070:57:0"},{"expression":{"arguments":[{"hexValue":"73656e6465722061646472","id":260,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3149:13:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_8125ca2decf812b25b65606ff16dad37cb198ff0433485a7926e50feafacfc35","typeString":"literal_string \"sender addr\""},"value":"sender addr"},{"arguments":[{"expression":{"id":263,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"3172:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":264,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"sender","nodeType":"MemberAccess","src":"3172:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":262,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3164:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":261,"name":"address","nodeType":"ElementaryTypeName","src":"3164:7:0","typeDescriptions":{}}},"id":265,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3164:19:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_8125ca2decf812b25b65606ff16dad37cb198ff0433485a7926e50feafacfc35","typeString":"literal_string \"sender addr\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":257,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3137:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":259,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":171,"src":"3137:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":266,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3137:47:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":267,"nodeType":"ExpressionStatement","src":"3137:47:0"},{"expression":{"arguments":[{"hexValue":"73656e646572206e6f6e6365","id":271,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3206:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_db7deb43f2f9e0404016de53b7e64c4976b54149581f7534daae2551e8cf4e40","typeString":"literal_string \"sender nonce\""},"value":"sender nonce"},{"arguments":[{"arguments":[{"expression":{"id":276,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"3242:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":277,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"sender","nodeType":"MemberAccess","src":"3242:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":275,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3234:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":274,"name":"address","nodeType":"ElementaryTypeName","src":"3234:7:0","typeDescriptions":{}}},"id":278,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3234:19:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":272,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"3222:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":273,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"getNonce","nodeType":"MemberAccess","referencedDeclaration":17,"src":"3222:11:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_address_$returns$_t_uint64_$","typeString":"function (address) view external returns (uint64)"}},"id":279,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3222:32:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_db7deb43f2f9e0404016de53b7e64c4976b54149581f7534daae2551e8cf4e40","typeString":"literal_string \"sender nonce\""},{"typeIdentifier":"t_uint64","typeString":"uint64"}],"expression":{"id":268,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3194:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":270,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":154,"src":"3194:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_uint256_$returns$__$","typeString":"function (string memory,uint256) pure"}},"id":280,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3194:61:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":281,"nodeType":"ExpressionStatement","src":"3194:61:0"},{"assignments":[283],"declarations":[{"constant":false,"id":283,"mutability":"mutable","name":"json","nameLocation":"3280:4:0","nodeType":"VariableDeclaration","scope":377,"src":"3266:18:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":282,"name":"string","nodeType":"ElementaryTypeName","src":"3266:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"id":285,"initialValue":{"hexValue":"7b22726f6f745f6b6579223a205b7b2261223a20312c202262223a20327d5d7d","id":284,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3287:34:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_e95522e99766888d0261f55bd1eae5e3f3e26eaf009a16e2433eafaf0a4ecdf2","typeString":"literal_string \"{\"root_key\": [{\"a\": 1, \"b\": 2}]}\""},"value":"{\"root_key\": [{\"a\": 1, \"b\": 2}]}"},"nodeType":"VariableDeclarationStatement","src":"3266:55:0"},{"assignments":[290],"declarations":[{"constant":false,"id":290,"mutability":"mutable","name":"keys","nameLocation":"3347:4:0","nodeType":"VariableDeclaration","scope":377,"src":"3331:20:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string[]"},"typeName":{"baseType":{"id":288,"name":"string","nodeType":"ElementaryTypeName","src":"3331:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"id":289,"nodeType":"ArrayTypeName","src":"3331:8:0","typeDescriptions":{"typeIdentifier":"t_array$_t_string_storage_$dyn_storage_ptr","typeString":"string[]"}},"visibility":"internal"}],"id":296,"initialValue":{"arguments":[{"id":293,"name":"json","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":283,"src":"3371:4:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"hexValue":"2e726f6f745f6b65795b305d","id":294,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3377:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_d82f67100edb80050915e1ec4b565c9a8319a22efb1075e1298b7bb60101d266","typeString":"literal_string \".root_key[0]\""},"value":".root_key[0]"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_stringliteral_d82f67100edb80050915e1ec4b565c9a8319a22efb1075e1298b7bb60101d266","typeString":"literal_string \".root_key[0]\""}],"expression":{"id":291,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"3354:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":292,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"parseJsonKeys","nodeType":"MemberAccess","referencedDeclaration":27,"src":"3354:16:0","typeDescriptions":{"typeIdentifier":"t_function_external_pure$_t_string_memory_ptr_$_t_string_memory_ptr_$returns$_t_array$_t_string_memory_ptr_$dyn_memory_ptr_$","typeString":"function (string memory,string memory) pure external returns (string memory[] memory)"}},"id":295,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3354:38:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string memory[] memory"}},"nodeType":"VariableDeclarationStatement","src":"3331:61:0"},{"expression":{"arguments":[{"hexValue":"6b657973","id":300,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3414:6:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_f29790a80c4ce5f42f59892f424f9c92856c6b656c3378e2cf305b260c6f4195","typeString":"literal_string \"keys\""},"value":"keys"},{"baseExpression":{"id":301,"name":"keys","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":290,"src":"3422:4:0","typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string memory[] memory"}},"id":303,"indexExpression":{"hexValue":"30","id":302,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"3427:1:0","typeDescriptions":{"typeIdentifier":"t_rational_0_by_1","typeString":"int_const 0"},"value":"0"},"isConstant":false,"isLValue":true,"isPure":false,"lValueRequested":false,"nodeType":"IndexAccess","src":"3422:7:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"baseExpression":{"id":304,"name":"keys","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":290,"src":"3431:4:0","typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string memory[] memory"}},"id":306,"indexExpression":{"hexValue":"31","id":305,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"3436:1:0","typeDescriptions":{"typeIdentifier":"t_rational_1_by_1","typeString":"int_const 1"},"value":"1"},"isConstant":false,"isLValue":true,"isPure":false,"lValueRequested":false,"nodeType":"IndexAccess","src":"3431:7:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_f29790a80c4ce5f42f59892f424f9c92856c6b656c3378e2cf305b260c6f4195","typeString":"literal_string \"keys\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}],"expression":{"id":297,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3402:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":299,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":191,"src":"3402:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_string_memory_ptr_$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory,string memory,string memory) pure"}},"id":307,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3402:37:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":308,"nodeType":"ExpressionStatement","src":"3402:37:0"},{"expression":{"arguments":[{"hexValue":"66726f6d206f726967696e616c","id":312,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3461:15:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_77928970c8757d110f3c23e003246f49e0de890480ba9717ba659b2f56f316b2","typeString":"literal_string \"from original\""},"value":"from original"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_77928970c8757d110f3c23e003246f49e0de890480ba9717ba659b2f56f316b2","typeString":"literal_string \"from original\""}],"expression":{"id":309,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3450:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":311,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"hello","nodeType":"MemberAccess","referencedDeclaration":633,"src":"3450:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) view external"}},"id":313,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3450:27:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":314,"nodeType":"ExpressionStatement","src":"3450:27:0"},{"expression":{"arguments":[{"arguments":[{"arguments":[{"hexValue":"30783432","id":322,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"3517:4:0","typeDescriptions":{"typeIdentifier":"t_rational_66_by_1","typeString":"int_const 66"},"value":"0x42"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_66_by_1","typeString":"int_const 66"}],"id":321,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3509:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":320,"name":"uint160","nodeType":"ElementaryTypeName","src":"3509:7:0","typeDescriptions":{}}},"id":323,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3509:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":319,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3501:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":318,"name":"address","nodeType":"ElementaryTypeName","src":"3501:7:0","typeDescriptions":{}}},"id":324,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3501:22:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":315,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"3487:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":317,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"startPrank","nodeType":"MemberAccess","referencedDeclaration":32,"src":"3487:13:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_address_$returns$__$","typeString":"function (address) external"}},"id":325,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3487:37:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":326,"nodeType":"ExpressionStatement","src":"3487:37:0"},{"expression":{"arguments":[{"hexValue":"66726f6d207072616e6b2031","id":330,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3545:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_42b34abfe37a8b0add910cda7b4a379e6538fa7a1dcafce47a02bd38f6c88e2a","typeString":"literal_string \"from prank 1\""},"value":"from prank 1"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_42b34abfe37a8b0add910cda7b4a379e6538fa7a1dcafce47a02bd38f6c88e2a","typeString":"literal_string \"from prank 1\""}],"expression":{"id":327,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3534:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":329,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"hello","nodeType":"MemberAccess","referencedDeclaration":633,"src":"3534:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) view external"}},"id":331,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3534:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":332,"nodeType":"ExpressionStatement","src":"3534:26:0"},{"expression":{"arguments":[{"hexValue":"706172656e742073636f7065206d73672e73656e646572","id":336,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3582:25:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_83ec9246154d8845de47aafc5c2865c9985d2efe84472c27283879f2fbf5cc94","typeString":"literal_string \"parent scope msg.sender\""},"value":"parent scope msg.sender"},{"arguments":[{"expression":{"id":339,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"3617:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":340,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"sender","nodeType":"MemberAccess","src":"3617:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":338,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3609:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":337,"name":"address","nodeType":"ElementaryTypeName","src":"3609:7:0","typeDescriptions":{}}},"id":341,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3609:19:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_83ec9246154d8845de47aafc5c2865c9985d2efe84472c27283879f2fbf5cc94","typeString":"literal_string \"parent scope msg.sender\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":333,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3570:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":335,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":171,"src":"3570:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":342,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3570:59:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":343,"nodeType":"ExpressionStatement","src":"3570:59:0"},{"expression":{"arguments":[{"hexValue":"706172656e742073636f706520636f6e74726163742e61646472","id":347,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3651:28:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_97df66250e0b2b48f0ec8d0e01eb1b8ca012d95f1572895622aa1ea433e5570f","typeString":"literal_string \"parent scope contract.addr\""},"value":"parent scope contract.addr"},{"arguments":[{"id":350,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3689:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}],"id":349,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3681:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":348,"name":"address","nodeType":"ElementaryTypeName","src":"3681:7:0","typeDescriptions":{}}},"id":351,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3681:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_97df66250e0b2b48f0ec8d0e01eb1b8ca012d95f1572895622aa1ea433e5570f","typeString":"literal_string \"parent scope contract.addr\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":344,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3639:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":346,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":171,"src":"3639:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":352,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3639:56:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":353,"nodeType":"ExpressionStatement","src":"3639:56:0"},{"expression":{"arguments":[{"hexValue":"66726f6d207072616e6b2032","id":357,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3716:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_a38a34f8cad750a79aa097a92971f8f405b51ee9d53d25c5b14fc129ba3684bb","typeString":"literal_string \"from prank 2\""},"value":"from prank 2"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_a38a34f8cad750a79aa097a92971f8f405b51ee9d53d25c5b14fc129ba3684bb","typeString":"literal_string \"from prank 2\""}],"expression":{"id":354,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3705:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":356,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"hello","nodeType":"MemberAccess","referencedDeclaration":633,"src":"3705:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) view external"}},"id":358,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3705:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":359,"nodeType":"ExpressionStatement","src":"3705:26:0"},{"expression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":360,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"3741:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":362,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"stopPrank","nodeType":"MemberAccess","referencedDeclaration":35,"src":"3741:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$__$returns$__$","typeString":"function () external"}},"id":363,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3741:14:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":364,"nodeType":"ExpressionStatement","src":"3741:14:0"},{"expression":{"arguments":[{"hexValue":"66726f6d206f726967696e616c20616761696e","id":368,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3776:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_0c805c6579e20a9c4c8e11aeab23330910a9f2da629191dc119d1730e8ed6860","typeString":"literal_string \"from original again\""},"value":"from original again"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_0c805c6579e20a9c4c8e11aeab23330910a9f2da629191dc119d1730e8ed6860","typeString":"literal_string \"from original again\""}],"expression":{"id":365,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3765:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":367,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"hello","nodeType":"MemberAccess","referencedDeclaration":633,"src":"3765:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) view external"}},"id":369,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3765:33:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":370,"nodeType":"ExpressionStatement","src":"3765:33:0"},{"expression":{"arguments":[{"hexValue":"646f6e6521","id":374,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3821:7:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_080382d5c9e9e7c5e3d1d33f5e7422740375955180fadff167d8130e0c35f3fc","typeString":"literal_string \"done!\""},"value":"done!"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_080382d5c9e9e7c5e3d1d33f5e7422740375955180fadff167d8130e0c35f3fc","typeString":"literal_string \"done!\""}],"expression":{"id":371,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3809:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":373,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"3809:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":375,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3809:20:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":376,"nodeType":"ExpressionStatement","src":"3809:20:0"}]},"documentation":{"id":216,"nodeType":"StructuredDocumentation","src":"2804:78:0","text":"@notice example function, runs through basic cheat-codes and console logs."},"functionSelector":"c0406226","implemented":true,"kind":"function","modifiers":[],"name":"run","nameLocation":"2896:3:0","parameters":{"id":217,"nodeType":"ParameterList","parameters":[],"src":"2899:2:0"},"returnParameters":{"id":218,"nodeType":"ParameterList","parameters":[],"src":"2909:0:0"},"scope":706,"stateMutability":"nonpayable","virtual":false,"visibility":"public"},{"id":609,"nodeType":"FunctionDefinition","src":"3903:1258:0","nodes":[],"body":{"id":608,"nodeType":"Block","src":"3934:1227:0","nodes":[],"statements":[{"expression":{"arguments":[{"hexValue":"6e6f6e6365207374617274","id":385,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3956:13:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_71efc69b9a13b6bc1e9a14d766ff01c79022262c6daa6532fb5dfb14f8511a20","typeString":"literal_string \"nonce start\""},"value":"nonce start"},{"arguments":[{"arguments":[{"arguments":[{"id":392,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3999:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}],"id":391,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3991:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":390,"name":"address","nodeType":"ElementaryTypeName","src":"3991:7:0","typeDescriptions":{}}},"id":393,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3991:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":388,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"3979:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":389,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"getNonce","nodeType":"MemberAccess","referencedDeclaration":17,"src":"3979:11:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_address_$returns$_t_uint64_$","typeString":"function (address) view external returns (uint64)"}},"id":394,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3979:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint64","typeString":"uint64"}],"id":387,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3971:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint256_$","typeString":"type(uint256)"},"typeName":{"id":386,"name":"uint256","nodeType":"ElementaryTypeName","src":"3971:7:0","typeDescriptions":{}}},"id":395,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3971:35:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_71efc69b9a13b6bc1e9a14d766ff01c79022262c6daa6532fb5dfb14f8511a20","typeString":"literal_string \"nonce start\""},{"typeIdentifier":"t_uint256","typeString":"uint256"}],"expression":{"id":382,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3944:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":384,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":154,"src":"3944:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_uint256_$returns$__$","typeString":"function (string memory,uint256) pure"}},"id":396,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3944:63:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":397,"nodeType":"ExpressionStatement","src":"3944:63:0"},{"expression":{"arguments":[{"hexValue":"74657374696e672073696e676c65","id":401,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4030:16:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_b75103528423218e7569082dad569ed0d2ce7c0ac770c0812b220e2d369fe474","typeString":"literal_string \"testing single\""},"value":"testing single"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_b75103528423218e7569082dad569ed0d2ce7c0ac770c0812b220e2d369fe474","typeString":"literal_string \"testing single\""}],"expression":{"id":398,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"4018:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":400,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"4018:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":402,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4018:29:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":403,"nodeType":"ExpressionStatement","src":"4018:29:0"},{"expression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":404,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"4057:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":406,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"broadcast","nodeType":"MemberAccess","referencedDeclaration":38,"src":"4057:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$__$returns$__$","typeString":"function () external"}},"id":407,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4057:14:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":408,"nodeType":"ExpressionStatement","src":"4057:14:0"},{"expression":{"arguments":[{"hexValue":"73696e676c655f63616c6c31","id":412,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4092:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_5e1cad6d7a968cfacf2731373e1248ffb11f4886bced66a02a6de1a67ac8f777","typeString":"literal_string \"single_call1\""},"value":"single_call1"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_5e1cad6d7a968cfacf2731373e1248ffb11f4886bced66a02a6de1a67ac8f777","typeString":"literal_string \"single_call1\""}],"expression":{"id":409,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"4081:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":411,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"call1","nodeType":"MemberAccess","referencedDeclaration":648,"src":"4081:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) external"}},"id":413,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4081:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":414,"nodeType":"ExpressionStatement","src":"4081:26:0"},{"expression":{"arguments":[{"hexValue":"73696e676c655f63616c6c32","id":418,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4128:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_b37ddaf5d00ad9e6371de3fb71b91eef731fae1e86b768666380f7d44e1ada25","typeString":"literal_string \"single_call2\""},"value":"single_call2"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_b37ddaf5d00ad9e6371de3fb71b91eef731fae1e86b768666380f7d44e1ada25","typeString":"literal_string \"single_call2\""}],"expression":{"id":415,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"4117:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":417,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"call2","nodeType":"MemberAccess","referencedDeclaration":663,"src":"4117:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) external"}},"id":419,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4117:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":420,"nodeType":"ExpressionStatement","src":"4117:26:0"},{"expression":{"arguments":[{"hexValue":"74657374696e672073746172742f73746f70","id":424,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4166:20:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_778e886e3a1c3c5096aca76228832105f3f9269f362effd0e8ce3737787cb784","typeString":"literal_string \"testing start/stop\""},"value":"testing start/stop"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_778e886e3a1c3c5096aca76228832105f3f9269f362effd0e8ce3737787cb784","typeString":"literal_string \"testing start/stop\""}],"expression":{"id":421,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"4154:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":423,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"4154:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":425,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4154:33:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":426,"nodeType":"ExpressionStatement","src":"4154:33:0"},{"expression":{"arguments":[{"arguments":[{"arguments":[{"hexValue":"3078633066666565","id":434,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4231:8:0","typeDescriptions":{"typeIdentifier":"t_rational_12648430_by_1","typeString":"int_const 12648430"},"value":"0xc0ffee"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_12648430_by_1","typeString":"int_const 12648430"}],"id":433,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4223:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":432,"name":"uint160","nodeType":"ElementaryTypeName","src":"4223:7:0","typeDescriptions":{}}},"id":435,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4223:17:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":431,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4215:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":430,"name":"address","nodeType":"ElementaryTypeName","src":"4215:7:0","typeDescriptions":{}}},"id":436,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4215:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":427,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"4197:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":429,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"startBroadcast","nodeType":"MemberAccess","referencedDeclaration":48,"src":"4197:17:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_address_$returns$__$","typeString":"function (address) external"}},"id":437,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4197:45:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":438,"nodeType":"ExpressionStatement","src":"4197:45:0"},{"expression":{"arguments":[{"hexValue":"737461727473746f705f63616c6c31","id":442,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4263:17:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_2fc2682edf10ed478ee3b9a190f6b1c88bb492b300935ce44545a1613cf8f041","typeString":"literal_string \"startstop_call1\""},"value":"startstop_call1"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_2fc2682edf10ed478ee3b9a190f6b1c88bb492b300935ce44545a1613cf8f041","typeString":"literal_string \"startstop_call1\""}],"expression":{"id":439,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"4252:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":441,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"call1","nodeType":"MemberAccess","referencedDeclaration":648,"src":"4252:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) external"}},"id":443,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4252:29:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":444,"nodeType":"ExpressionStatement","src":"4252:29:0"},{"expression":{"arguments":[{"hexValue":"737461727473746f705f63616c6c32","id":448,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4302:17:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_1a6fd77f04b28bf45d6d0e2dd4c65c0bbfeba174f849e43bb67ebca1c019cda4","typeString":"literal_string \"startstop_call2\""},"value":"startstop_call2"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_1a6fd77f04b28bf45d6d0e2dd4c65c0bbfeba174f849e43bb67ebca1c019cda4","typeString":"literal_string \"startstop_call2\""}],"expression":{"id":445,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"4291:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":447,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"call2","nodeType":"MemberAccess","referencedDeclaration":663,"src":"4291:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) external"}},"id":449,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4291:29:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":450,"nodeType":"ExpressionStatement","src":"4291:29:0"},{"expression":{"arguments":[{"hexValue":"737461727473746f705f70757265","id":454,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4344:16:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_b6e9eb1efd186b1d92b54da45026aa97a178e6eaffdf9dbf9f666fc751fb0ff9","typeString":"literal_string \"startstop_pure\""},"value":"startstop_pure"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_b6e9eb1efd186b1d92b54da45026aa97a178e6eaffdf9dbf9f666fc751fb0ff9","typeString":"literal_string \"startstop_pure\""}],"expression":{"id":451,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"4330:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":453,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"callPure","nodeType":"MemberAccess","referencedDeclaration":705,"src":"4330:13:0","typeDescriptions":{"typeIdentifier":"t_function_external_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure external"}},"id":455,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4330:31:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":456,"nodeType":"ExpressionStatement","src":"4330:31:0"},{"expression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":457,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"4371:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":459,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"stopBroadcast","nodeType":"MemberAccess","referencedDeclaration":54,"src":"4371:16:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$__$returns$__$","typeString":"function () external"}},"id":460,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4371:18:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":461,"nodeType":"ExpressionStatement","src":"4371:18:0"},{"expression":{"arguments":[{"hexValue":"737461727473746f705f63616c6c33","id":465,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4410:17:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_8eb502bfdc4adda22bd960aa2ae13ce4c0ed8cc3b3791ed65e321a38cdd36f72","typeString":"literal_string \"startstop_call3\""},"value":"startstop_call3"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_8eb502bfdc4adda22bd960aa2ae13ce4c0ed8cc3b3791ed65e321a38cdd36f72","typeString":"literal_string \"startstop_call3\""}],"expression":{"id":462,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"4399:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":464,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"call1","nodeType":"MemberAccess","referencedDeclaration":648,"src":"4399:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) external"}},"id":466,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4399:29:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":467,"nodeType":"ExpressionStatement","src":"4399:29:0"},{"expression":{"arguments":[{"hexValue":"74657374696e67206e6573746564","id":471,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4451:16:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_f92f19f7a5b5b9ce341188bf4e15925f184cdb5ac135c4846ced718f259dbde5","typeString":"literal_string \"testing nested\""},"value":"testing nested"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_f92f19f7a5b5b9ce341188bf4e15925f184cdb5ac135c4846ced718f259dbde5","typeString":"literal_string \"testing nested\""}],"expression":{"id":468,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"4439:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":470,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"4439:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":472,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4439:29:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":473,"nodeType":"ExpressionStatement","src":"4439:29:0"},{"expression":{"arguments":[{"arguments":[{"arguments":[{"hexValue":"307831323334","id":481,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4512:6:0","typeDescriptions":{"typeIdentifier":"t_rational_4660_by_1","typeString":"int_const 4660"},"value":"0x1234"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_4660_by_1","typeString":"int_const 4660"}],"id":480,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4504:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":479,"name":"uint160","nodeType":"ElementaryTypeName","src":"4504:7:0","typeDescriptions":{}}},"id":482,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4504:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":478,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4496:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":477,"name":"address","nodeType":"ElementaryTypeName","src":"4496:7:0","typeDescriptions":{}}},"id":483,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4496:24:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":474,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"4478:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":476,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"startBroadcast","nodeType":"MemberAccess","referencedDeclaration":48,"src":"4478:17:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_address_$returns$__$","typeString":"function (address) external"}},"id":484,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4478:43:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":485,"nodeType":"ExpressionStatement","src":"4478:43:0"},{"expression":{"arguments":[{"hexValue":"6e6573746564","id":489,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4544:8:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_4d5b14044d78fbf0c9dd8b9c49e35f09ee5a6f5b1b3b8117b5d0e15c8dd2cb09","typeString":"literal_string \"nested\""},"value":"nested"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_4d5b14044d78fbf0c9dd8b9c49e35f09ee5a6f5b1b3b8117b5d0e15c8dd2cb09","typeString":"literal_string \"nested\""}],"expression":{"id":486,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"4531:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":488,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"nested1","nodeType":"MemberAccess","referencedDeclaration":678,"src":"4531:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) external"}},"id":490,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4531:22:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":491,"nodeType":"ExpressionStatement","src":"4531:22:0"},{"expression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":492,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"4563:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":494,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"stopBroadcast","nodeType":"MemberAccess","referencedDeclaration":54,"src":"4563:16:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$__$returns$__$","typeString":"function () external"}},"id":495,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4563:18:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":496,"nodeType":"ExpressionStatement","src":"4563:18:0"},{"expression":{"arguments":[{"hexValue":"636f6e7472616374206465706c6f796d656e74","id":500,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4604:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_aaf9be86adf9b6872d87eed3526f7c55f3c5d61f4e4dd6d55ef2fcbb8ad0bd57","typeString":"literal_string \"contract deployment\""},"value":"contract deployment"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_aaf9be86adf9b6872d87eed3526f7c55f3c5d61f4e4dd6d55ef2fcbb8ad0bd57","typeString":"literal_string \"contract deployment\""}],"expression":{"id":497,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"4592:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":499,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"4592:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":501,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4592:34:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":502,"nodeType":"ExpressionStatement","src":"4592:34:0"},{"expression":{"arguments":[{"arguments":[{"arguments":[{"hexValue":"3078313233343536","id":510,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4665:8:0","typeDescriptions":{"typeIdentifier":"t_rational_1193046_by_1","typeString":"int_const 1193046"},"value":"0x123456"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_1193046_by_1","typeString":"int_const 1193046"}],"id":509,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4657:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":508,"name":"uint160","nodeType":"ElementaryTypeName","src":"4657:7:0","typeDescriptions":{}}},"id":511,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4657:17:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":507,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4649:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":506,"name":"address","nodeType":"ElementaryTypeName","src":"4649:7:0","typeDescriptions":{}}},"id":512,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4649:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":503,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"4636:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":505,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"broadcast","nodeType":"MemberAccess","referencedDeclaration":43,"src":"4636:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_address_$returns$__$","typeString":"function (address) external"}},"id":513,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4636:40:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":514,"nodeType":"ExpressionStatement","src":"4636:40:0"},{"assignments":[517],"declarations":[{"constant":false,"id":517,"mutability":"mutable","name":"x","nameLocation":"4693:1:0","nodeType":"VariableDeclaration","scope":608,"src":"4686:8:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"},"typeName":{"id":516,"nodeType":"UserDefinedTypeName","pathNode":{"id":515,"name":"FooBar","nodeType":"IdentifierPath","referencedDeclaration":719,"src":"4686:6:0"},"referencedDeclaration":719,"src":"4686:6:0","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}},"visibility":"internal"}],"id":523,"initialValue":{"arguments":[{"hexValue":"31323334","id":521,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4708:4:0","typeDescriptions":{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"},"value":"1234"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"}],"id":520,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"NewExpression","src":"4697:10:0","typeDescriptions":{"typeIdentifier":"t_function_creation_nonpayable$_t_uint256_$returns$_t_contract$_FooBar_$719_$","typeString":"function (uint256) returns (contract FooBar)"},"typeName":{"id":519,"nodeType":"UserDefinedTypeName","pathNode":{"id":518,"name":"FooBar","nodeType":"IdentifierPath","referencedDeclaration":719,"src":"4701:6:0"},"referencedDeclaration":719,"src":"4701:6:0","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}}},"id":522,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4697:16:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}},"nodeType":"VariableDeclarationStatement","src":"4686:27:0"},{"expression":{"arguments":[{"commonType":{"typeIdentifier":"t_uint256","typeString":"uint256"},"id":529,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"leftExpression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":525,"name":"x","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":517,"src":"4731:1:0","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}},"id":526,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"foo","nodeType":"MemberAccess","referencedDeclaration":708,"src":"4731:5:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$__$returns$_t_uint256_$","typeString":"function () view external returns (uint256)"}},"id":527,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4731:7:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"nodeType":"BinaryOperation","operator":"==","rightExpression":{"hexValue":"31323334","id":528,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4742:4:0","typeDescriptions":{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"},"value":"1234"},"src":"4731:15:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bool","typeString":"bool"}],"id":524,"name":"require","nodeType":"Identifier","overloadedDeclarations":[-18,-18],"referencedDeclaration":-18,"src":"4723:7:0","typeDescriptions":{"typeIdentifier":"t_function_require_pure$_t_bool_$returns$__$","typeString":"function (bool) pure"}},"id":530,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4723:24:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":531,"nodeType":"ExpressionStatement","src":"4723:24:0"},{"expression":{"arguments":[{"hexValue":"6372656174652032","id":535,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4770:10:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_4411d6d4ffcd00382a95255a63761e69de9810e1236042a5c64948a7b6c04daa","typeString":"literal_string \"create 2\""},"value":"create 2"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_4411d6d4ffcd00382a95255a63761e69de9810e1236042a5c64948a7b6c04daa","typeString":"literal_string \"create 2\""}],"expression":{"id":532,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"4758:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":534,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"4758:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":536,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4758:23:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":537,"nodeType":"ExpressionStatement","src":"4758:23:0"},{"expression":{"arguments":[{"arguments":[{"arguments":[{"hexValue":"307863616665","id":545,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4820:6:0","typeDescriptions":{"typeIdentifier":"t_rational_51966_by_1","typeString":"int_const 51966"},"value":"0xcafe"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_51966_by_1","typeString":"int_const 51966"}],"id":544,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4812:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":543,"name":"uint160","nodeType":"ElementaryTypeName","src":"4812:7:0","typeDescriptions":{}}},"id":546,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4812:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":542,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4804:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":541,"name":"address","nodeType":"ElementaryTypeName","src":"4804:7:0","typeDescriptions":{}}},"id":547,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4804:24:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":538,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"4791:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":540,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"broadcast","nodeType":"MemberAccess","referencedDeclaration":43,"src":"4791:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_address_$returns$__$","typeString":"function (address) external"}},"id":548,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4791:38:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":549,"nodeType":"ExpressionStatement","src":"4791:38:0"},{"assignments":[552],"declarations":[{"constant":false,"id":552,"mutability":"mutable","name":"y","nameLocation":"4846:1:0","nodeType":"VariableDeclaration","scope":608,"src":"4839:8:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"},"typeName":{"id":551,"nodeType":"UserDefinedTypeName","pathNode":{"id":550,"name":"FooBar","nodeType":"IdentifierPath","referencedDeclaration":719,"src":"4839:6:0"},"referencedDeclaration":719,"src":"4839:6:0","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}},"visibility":"internal"}],"id":566,"initialValue":{"arguments":[{"hexValue":"31323334","id":564,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4889:4:0","typeDescriptions":{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"},"value":"1234"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"}],"id":555,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"NewExpression","src":"4850:10:0","typeDescriptions":{"typeIdentifier":"t_function_creation_nonpayable$_t_uint256_$returns$_t_contract$_FooBar_$719_$","typeString":"function (uint256) returns (contract FooBar)"},"typeName":{"id":554,"nodeType":"UserDefinedTypeName","pathNode":{"id":553,"name":"FooBar","nodeType":"IdentifierPath","referencedDeclaration":719,"src":"4854:6:0"},"referencedDeclaration":719,"src":"4854:6:0","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}}},"id":563,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"names":["salt"],"nodeType":"FunctionCallOptions","options":[{"arguments":[{"arguments":[{"hexValue":"3432","id":560,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4883:2:0","typeDescriptions":{"typeIdentifier":"t_rational_42_by_1","typeString":"int_const 42"},"value":"42"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_42_by_1","typeString":"int_const 42"}],"id":559,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4875:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint256_$","typeString":"type(uint256)"},"typeName":{"id":558,"name":"uint256","nodeType":"ElementaryTypeName","src":"4875:7:0","typeDescriptions":{}}},"id":561,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4875:11:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint256","typeString":"uint256"}],"id":557,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4867:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_bytes32_$","typeString":"type(bytes32)"},"typeName":{"id":556,"name":"bytes32","nodeType":"ElementaryTypeName","src":"4867:7:0","typeDescriptions":{}}},"id":562,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4867:20:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes32","typeString":"bytes32"}}],"src":"4850:38:0","typeDescriptions":{"typeIdentifier":"t_function_creation_nonpayable$_t_uint256_$returns$_t_contract$_FooBar_$719_$salt","typeString":"function (uint256) returns (contract FooBar)"}},"id":565,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4850:44:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}},"nodeType":"VariableDeclarationStatement","src":"4839:55:0"},{"expression":{"arguments":[{"commonType":{"typeIdentifier":"t_uint256","typeString":"uint256"},"id":572,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"leftExpression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":568,"name":"y","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":552,"src":"4912:1:0","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}},"id":569,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"foo","nodeType":"MemberAccess","referencedDeclaration":708,"src":"4912:5:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$__$returns$_t_uint256_$","typeString":"function () view external returns (uint256)"}},"id":570,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4912:7:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"nodeType":"BinaryOperation","operator":"==","rightExpression":{"hexValue":"31323334","id":571,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4923:4:0","typeDescriptions":{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"},"value":"1234"},"src":"4912:15:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bool","typeString":"bool"}],"id":567,"name":"require","nodeType":"Identifier","overloadedDeclarations":[-18,-18],"referencedDeclaration":-18,"src":"4904:7:0","typeDescriptions":{"typeIdentifier":"t_function_require_pure$_t_bool_$returns$__$","typeString":"function (bool) pure"}},"id":573,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4904:24:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":574,"nodeType":"ExpressionStatement","src":"4904:24:0"},{"expression":{"arguments":[{"hexValue":"646f6e6521","id":578,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4950:7:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_080382d5c9e9e7c5e3d1d33f5e7422740375955180fadff167d8130e0c35f3fc","typeString":"literal_string \"done!\""},"value":"done!"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_080382d5c9e9e7c5e3d1d33f5e7422740375955180fadff167d8130e0c35f3fc","typeString":"literal_string \"done!\""}],"expression":{"id":575,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"4938:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":577,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"4938:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":579,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4938:20:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":580,"nodeType":"ExpressionStatement","src":"4938:20:0"},{"expression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":581,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"5042:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":583,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"broadcast","nodeType":"MemberAccess","referencedDeclaration":38,"src":"5042:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$__$returns$__$","typeString":"function () external"}},"id":584,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5042:14:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":585,"nodeType":"ExpressionStatement","src":"5042:14:0"},{"expression":{"arguments":[{"hexValue":"31323334","id":589,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"5077:4:0","typeDescriptions":{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"},"value":"1234"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"}],"id":588,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"NewExpression","src":"5066:10:0","typeDescriptions":{"typeIdentifier":"t_function_creation_nonpayable$_t_uint256_$returns$_t_contract$_FooBar_$719_$","typeString":"function (uint256) returns (contract FooBar)"},"typeName":{"id":587,"nodeType":"UserDefinedTypeName","pathNode":{"id":586,"name":"FooBar","nodeType":"IdentifierPath","referencedDeclaration":719,"src":"5070:6:0"},"referencedDeclaration":719,"src":"5070:6:0","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}}},"id":590,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5066:16:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}},"id":591,"nodeType":"ExpressionStatement","src":"5066:16:0"},{"expression":{"arguments":[{"hexValue":"6e6f6e636520656e64","id":595,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"5105:11:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_fa629e6661ad2a2bdb09cf9a3a276ce0d722482ae5c2887650751be0938847e8","typeString":"literal_string \"nonce end\""},"value":"nonce end"},{"arguments":[{"arguments":[{"arguments":[{"id":602,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"5146:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}],"id":601,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"5138:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":600,"name":"address","nodeType":"ElementaryTypeName","src":"5138:7:0","typeDescriptions":{}}},"id":603,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5138:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":598,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"5126:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":599,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"getNonce","nodeType":"MemberAccess","referencedDeclaration":17,"src":"5126:11:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_address_$returns$_t_uint64_$","typeString":"function (address) view external returns (uint64)"}},"id":604,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5126:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint64","typeString":"uint64"}],"id":597,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"5118:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint256_$","typeString":"type(uint256)"},"typeName":{"id":596,"name":"uint256","nodeType":"ElementaryTypeName","src":"5118:7:0","typeDescriptions":{}}},"id":605,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5118:35:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_fa629e6661ad2a2bdb09cf9a3a276ce0d722482ae5c2887650751be0938847e8","typeString":"literal_string \"nonce end\""},{"typeIdentifier":"t_uint256","typeString":"uint256"}],"expression":{"id":592,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"5093:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":594,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":154,"src":"5093:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_uint256_$returns$__$","typeString":"function (string memory,uint256) pure"}},"id":606,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5093:61:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":607,"nodeType":"ExpressionStatement","src":"5093:61:0"}]},"documentation":{"id":379,"nodeType":"StructuredDocumentation","src":"3842:56:0","text":"@notice example function, to test vm.broadcast with."},"functionSelector":"bef03abc","implemented":true,"kind":"function","modifiers":[],"name":"runBroadcast","nameLocation":"3912:12:0","parameters":{"id":380,"nodeType":"ParameterList","parameters":[],"src":"3924:2:0"},"returnParameters":{"id":381,"nodeType":"ParameterList","parameters":[],"src":"3934:0:0"},"scope":706,"stateMutability":"nonpayable","virtual":false,"visibility":"public"},{"id":633,"nodeType":"FunctionDefinition","src":"5256:143:0","nodes":[],"body":{"id":632,"nodeType":"Block","src":"5305:94:0","nodes":[],"statements":[{"expression":{"arguments":[{"id":618,"name":"_v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":612,"src":"5327:2:0","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}],"expression":{"id":615,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"5315:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":617,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"5315:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":619,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5315:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":620,"nodeType":"ExpressionStatement","src":"5315:15:0"},{"expression":{"arguments":[{"hexValue":"68656c6c6f206d73672e73656e646572","id":624,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"5352:18:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_b3cc13bc51228b2c4c4334d82a4772908254dc0e1c512893dd16208ef13efb8e","typeString":"literal_string \"hello msg.sender\""},"value":"hello msg.sender"},{"arguments":[{"expression":{"id":627,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"5380:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":628,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"sender","nodeType":"MemberAccess","src":"5380:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":626,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"5372:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":625,"name":"address","nodeType":"ElementaryTypeName","src":"5372:7:0","typeDescriptions":{}}},"id":629,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5372:19:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_b3cc13bc51228b2c4c4334d82a4772908254dc0e1c512893dd16208ef13efb8e","typeString":"literal_string \"hello msg.sender\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":621,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"5340:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":623,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":171,"src":"5340:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":630,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5340:52:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":631,"nodeType":"ExpressionStatement","src":"5340:52:0"}]},"documentation":{"id":610,"nodeType":"StructuredDocumentation","src":"5167:84:0","text":"@notice example external function, to force a CALL, and test vm.startPrank with."},"functionSelector":"a777d0dc","implemented":true,"kind":"function","modifiers":[],"name":"hello","nameLocation":"5265:5:0","parameters":{"id":613,"nodeType":"ParameterList","parameters":[{"constant":false,"id":612,"mutability":"mutable","name":"_v","nameLocation":"5287:2:0","nodeType":"VariableDeclaration","scope":633,"src":"5271:18:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":611,"name":"string","nodeType":"ElementaryTypeName","src":"5271:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"5270:20:0"},"returnParameters":{"id":614,"nodeType":"ParameterList","parameters":[],"src":"5305:0:0"},"scope":706,"stateMutability":"view","virtual":false,"visibility":"external"},{"id":648,"nodeType":"FunctionDefinition","src":"5405:95:0","nodes":[],"body":{"id":647,"nodeType":"Block","src":"5449:51:0","nodes":[],"statements":[{"expression":{"id":639,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"UnaryOperation","operator":"++","prefix":false,"src":"5459:9:0","subExpression":{"id":638,"name":"counter","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":215,"src":"5459:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"id":640,"nodeType":"ExpressionStatement","src":"5459:9:0"},{"expression":{"arguments":[{"id":644,"name":"_v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":635,"src":"5490:2:0","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}],"expression":{"id":641,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"5478:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":643,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"5478:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":645,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5478:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":646,"nodeType":"ExpressionStatement","src":"5478:15:0"}]},"functionSelector":"7e79255d","implemented":true,"kind":"function","modifiers":[],"name":"call1","nameLocation":"5414:5:0","parameters":{"id":636,"nodeType":"ParameterList","parameters":[{"constant":false,"id":635,"mutability":"mutable","name":"_v","nameLocation":"5436:2:0","nodeType":"VariableDeclaration","scope":648,"src":"5420:18:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":634,"name":"string","nodeType":"ElementaryTypeName","src":"5420:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"5419:20:0"},"returnParameters":{"id":637,"nodeType":"ParameterList","parameters":[],"src":"5449:0:0"},"scope":706,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":663,"nodeType":"FunctionDefinition","src":"5506:95:0","nodes":[],"body":{"id":662,"nodeType":"Block","src":"5550:51:0","nodes":[],"statements":[{"expression":{"id":654,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"UnaryOperation","operator":"++","prefix":false,"src":"5560:9:0","subExpression":{"id":653,"name":"counter","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":215,"src":"5560:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"id":655,"nodeType":"ExpressionStatement","src":"5560:9:0"},{"expression":{"arguments":[{"id":659,"name":"_v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":650,"src":"5591:2:0","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}],"expression":{"id":656,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"5579:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":658,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"5579:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":660,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5579:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":661,"nodeType":"ExpressionStatement","src":"5579:15:0"}]},"functionSelector":"8d3ef7ca","implemented":true,"kind":"function","modifiers":[],"name":"call2","nameLocation":"5515:5:0","parameters":{"id":651,"nodeType":"ParameterList","parameters":[{"constant":false,"id":650,"mutability":"mutable","name":"_v","nameLocation":"5537:2:0","nodeType":"VariableDeclaration","scope":663,"src":"5521:18:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":649,"name":"string","nodeType":"ElementaryTypeName","src":"5521:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"5520:20:0"},"returnParameters":{"id":652,"nodeType":"ParameterList","parameters":[],"src":"5550:0:0"},"scope":706,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":678,"nodeType":"FunctionDefinition","src":"5607:98:0","nodes":[],"body":{"id":677,"nodeType":"Block","src":"5653:52:0","nodes":[],"statements":[{"expression":{"id":669,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"UnaryOperation","operator":"++","prefix":false,"src":"5663:9:0","subExpression":{"id":668,"name":"counter","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":215,"src":"5663:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"id":670,"nodeType":"ExpressionStatement","src":"5663:9:0"},{"expression":{"arguments":[{"id":674,"name":"_v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":665,"src":"5695:2:0","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}],"expression":{"id":671,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"5682:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":673,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"nested2","nodeType":"MemberAccess","referencedDeclaration":693,"src":"5682:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) external"}},"id":675,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5682:16:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":676,"nodeType":"ExpressionStatement","src":"5682:16:0"}]},"functionSelector":"a76ccdfa","implemented":true,"kind":"function","modifiers":[],"name":"nested1","nameLocation":"5616:7:0","parameters":{"id":666,"nodeType":"ParameterList","parameters":[{"constant":false,"id":665,"mutability":"mutable","name":"_v","nameLocation":"5640:2:0","nodeType":"VariableDeclaration","scope":678,"src":"5624:18:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":664,"name":"string","nodeType":"ElementaryTypeName","src":"5624:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"5623:20:0"},"returnParameters":{"id":667,"nodeType":"ParameterList","parameters":[],"src":"5653:0:0"},"scope":706,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":693,"nodeType":"FunctionDefinition","src":"5711:97:0","nodes":[],"body":{"id":692,"nodeType":"Block","src":"5757:51:0","nodes":[],"statements":[{"expression":{"id":684,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"UnaryOperation","operator":"++","prefix":false,"src":"5767:9:0","subExpression":{"id":683,"name":"counter","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":215,"src":"5767:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"id":685,"nodeType":"ExpressionStatement","src":"5767:9:0"},{"expression":{"arguments":[{"id":689,"name":"_v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":680,"src":"5798:2:0","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}],"expression":{"id":686,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"5786:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":688,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"5786:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":690,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5786:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":691,"nodeType":"ExpressionStatement","src":"5786:15:0"}]},"functionSelector":"dbf1282f","implemented":true,"kind":"function","modifiers":[],"name":"nested2","nameLocation":"5720:7:0","parameters":{"id":681,"nodeType":"ParameterList","parameters":[{"constant":false,"id":680,"mutability":"mutable","name":"_v","nameLocation":"5744:2:0","nodeType":"VariableDeclaration","scope":693,"src":"5728:18:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":679,"name":"string","nodeType":"ElementaryTypeName","src":"5728:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"5727:20:0"},"returnParameters":{"id":682,"nodeType":"ParameterList","parameters":[],"src":"5757:0:0"},"scope":706,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":705,"nodeType":"FunctionDefinition","src":"5814:84:0","nodes":[],"body":{"id":704,"nodeType":"Block","src":"5866:32:0","nodes":[],"statements":[{"expression":{"arguments":[{"id":701,"name":"_v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":695,"src":"5888:2:0","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}],"expression":{"id":698,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"5876:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":700,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"5876:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":702,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5876:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":703,"nodeType":"ExpressionStatement","src":"5876:15:0"}]},"functionSelector":"7f8b915c","implemented":true,"kind":"function","modifiers":[],"name":"callPure","nameLocation":"5823:8:0","parameters":{"id":696,"nodeType":"ParameterList","parameters":[{"constant":false,"id":695,"mutability":"mutable","name":"_v","nameLocation":"5848:2:0","nodeType":"VariableDeclaration","scope":705,"src":"5832:18:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":694,"name":"string","nodeType":"ElementaryTypeName","src":"5832:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"5831:20:0"},"returnParameters":{"id":697,"nodeType":"ParameterList","parameters":[],"src":"5866:0:0"},"scope":706,"stateMutability":"pure","virtual":false,"visibility":"external"}],"abstract":false,"baseContracts":[],"canonicalName":"ScriptExample","contractDependencies":[719],"contractKind":"contract","documentation":{"id":193,"nodeType":"StructuredDocumentation","src":"2415:126:0","text":"@title ScriptExample\n @notice ScriptExample is an example script. The Go forge script code tests that it can run this."},"fullyImplemented":true,"linearizedBaseContracts":[706],"name":"ScriptExample","nameLocation":"2550:13:0","scope":720,"usedErrors":[]},{"id":719,"nodeType":"ContractDefinition","src":"5902:96:0","nodes":[{"id":708,"nodeType":"VariableDeclaration","src":"5924:18:0","nodes":[],"constant":false,"functionSelector":"c2985578","mutability":"mutable","name":"foo","nameLocation":"5939:3:0","scope":719,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":707,"name":"uint256","nodeType":"ElementaryTypeName","src":"5924:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"public"},{"id":718,"nodeType":"FunctionDefinition","src":"5949:47:0","nodes":[],"body":{"id":717,"nodeType":"Block","src":"5972:24:0","nodes":[],"statements":[{"expression":{"id":715,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"leftHandSide":{"id":713,"name":"foo","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":708,"src":"5982:3:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"nodeType":"Assignment","operator":"=","rightHandSide":{"id":714,"name":"v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":710,"src":"5988:1:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"src":"5982:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"id":716,"nodeType":"ExpressionStatement","src":"5982:7:0"}]},"implemented":true,"kind":"constructor","modifiers":[],"name":"","nameLocation":"-1:-1:-1","parameters":{"id":711,"nodeType":"ParameterList","parameters":[{"constant":false,"id":710,"mutability":"mutable","name":"v","nameLocation":"5969:1:0","nodeType":"VariableDeclaration","scope":718,"src":"5961:9:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":709,"name":"uint256","nodeType":"ElementaryTypeName","src":"5961:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"}],"src":"5960:11:0"},"returnParameters":{"id":712,"nodeType":"ParameterList","parameters":[],"src":"5972:0:0"},"scope":719,"stateMutability":"nonpayable","virtual":false,"visibility":"public"}],"abstract":false,"baseContracts":[],"canonicalName":"FooBar","contractDependencies":[],"contractKind":"contract","fullyImplemented":true,"linearizedBaseContracts":[719],"name":"FooBar","nameLocation":"5911:6:0","scope":720,"usedErrors":[]}],"license":"MIT"},"id":0} +\ No newline at end of file
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+0
+
-0
+ +
+ +
+
+
diff --git OP/op-chain-ops/script/testdata/test-artifacts/ScriptExample.s.sol/ScriptExample.json CELO/op-chain-ops/script/testdata/test-artifacts/ScriptExample.s.sol/ScriptExample.json +index aab5ca4e2642737d08c12e79045a0ad98bf0e2da..09a0bf47f02dbcf6d4240edb932af49957bc0437 100644 +--- OP/op-chain-ops/script/testdata/test-artifacts/ScriptExample.s.sol/ScriptExample.json ++++ CELO/op-chain-ops/script/testdata/test-artifacts/ScriptExample.s.sol/ScriptExample.json +@@ -1 +1 @@ +-{"abi":[{"type":"function","name":"hello","inputs":[{"name":"_v","type":"string","internalType":"string"}],"outputs":[],"stateMutability":"view"},{"type":"function","name":"run","inputs":[],"outputs":[],"stateMutability":"nonpayable"}],"bytecode":{"object":"0x608060405234801561001057600080fd5b50611079806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063a777d0dc1461003b578063c040622614610050575b600080fd5b61004e610049366004610c26565b610058565b005b61004e6100da565b61009782828080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061092d92505050565b6100d66040518060400160405280601081526020017f68656c6c6f206d73672e73656e64657200000000000000000000000000000000815250336109bf565b5050565b604080517f4777f3cf0000000000000000000000000000000000000000000000000000000081526004810191909152600c60448201527f4558414d504c455f424f4f4c0000000000000000000000000000000000000000606482015260006024820181905290737109709ecfa91a80626ff3989d68f67f5b1dd12d90634777f3cf90608401602060405180830381865afa15801561017c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101a09190610c98565b90506101e16040518060400160405280601381526020017f626f6f6c2076616c75652066726f6d20656e760000000000000000000000000081525082610a50565b6102206040518060400160405280600d81526020017f636f6e7472616374206164647200000000000000000000000000000000000000815250306109bf565b604080518082018252600e81527f636f6e7472616374206e6f6e6365000000000000000000000000000000000000602082015290517f2d0335ab0000000000000000000000000000000000000000000000000000000081523060048201526102f39190737109709ecfa91a80626ff3989d68f67f5b1dd12d90632d0335ab906024015b602060405180830381865afa1580156102c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102e49190610cc1565b67ffffffffffffffff16610ae1565b6103326040518060400160405280600b81526020017f73656e6465722061646472000000000000000000000000000000000000000000815250336109bf565b604080518082018252600c81527f73656e646572206e6f6e63650000000000000000000000000000000000000000602082015290517f2d0335ab0000000000000000000000000000000000000000000000000000000081523360048201526103b99190737109709ecfa91a80626ff3989d68f67f5b1dd12d90632d0335ab906024016102a3565b60408051808201825260208082527f7b22726f6f745f6b6579223a205b7b2261223a20312c202262223a20327d5d7d9082015290517f213e4198000000000000000000000000000000000000000000000000000000008152600090737109709ecfa91a80626ff3989d68f67f5b1dd12d9063213e41989061043e908590600401610d65565b600060405180830381865afa15801561045b573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526104a19190810190610e35565b90506105176040518060400160405280600481526020017f6b65797300000000000000000000000000000000000000000000000000000000815250826000815181106104ef576104ef610f69565b60200260200101518360018151811061050a5761050a610f69565b6020026020010151610b72565b6040517fa777d0dc00000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f66726f6d206f726967696e616c000000000000000000000000000000000000006044820152309063a777d0dc9060640160006040518083038186803b15801561059457600080fd5b505afa1580156105a8573d6000803e3d6000fd5b50506040517f06447d5600000000000000000000000000000000000000000000000000000000815260426004820152737109709ecfa91a80626ff3989d68f67f5b1dd12d92506306447d569150602401600060405180830381600087803b15801561061257600080fd5b505af1158015610626573d6000803e3d6000fd5b50506040517fa777d0dc00000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f66726f6d207072616e6b20310000000000000000000000000000000000000000604482015230925063a777d0dc915060640160006040518083038186803b1580156106a757600080fd5b505afa1580156106bb573d6000803e3d6000fd5b505050506106fe6040518060400160405280601781526020017f706172656e742073636f7065206d73672e73656e646572000000000000000000815250336109bf565b61073d6040518060400160405280601a81526020017f706172656e742073636f706520636f6e74726163742e61646472000000000000815250306109bf565b6040517fa777d0dc00000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f66726f6d207072616e6b203200000000000000000000000000000000000000006044820152309063a777d0dc9060640160006040518083038186803b1580156107ba57600080fd5b505afa1580156107ce573d6000803e3d6000fd5b505050507f885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d60001c73ffffffffffffffffffffffffffffffffffffffff166390c5013b6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561083d57600080fd5b505af1158015610851573d6000803e3d6000fd5b50506040517fa777d0dc00000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f66726f6d206f726967696e616c20616761696e00000000000000000000000000604482015230925063a777d0dc915060640160006040518083038186803b1580156108d257600080fd5b505afa1580156108e6573d6000803e3d6000fd5b505050506109286040518060400160405280600581526020017f646f6e652100000000000000000000000000000000000000000000000000000081525061092d565b505050565b6109bc816040516024016109419190610f98565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f41304fac00000000000000000000000000000000000000000000000000000000179052610c01565b50565b6100d682826040516024016109d5929190610fab565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f319af33300000000000000000000000000000000000000000000000000000000179052610c01565b6100d68282604051602401610a66929190610fe3565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fc3b5563500000000000000000000000000000000000000000000000000000000179052610c01565b6100d68282604051602401610af7929190611007565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fb60e72cc00000000000000000000000000000000000000000000000000000000179052610c01565b610928838383604051602401610b8a93929190611029565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f2ced7cef000000000000000000000000000000000000000000000000000000001790525b6109bc8180516a636f6e736f6c652e6c6f67602083016000808483855afa5050505050565b60008060208385031215610c3957600080fd5b823567ffffffffffffffff80821115610c5157600080fd5b818501915085601f830112610c6557600080fd5b813581811115610c7457600080fd5b866020828501011115610c8657600080fd5b60209290920196919550909350505050565b600060208284031215610caa57600080fd5b81518015158114610cba57600080fd5b9392505050565b600060208284031215610cd357600080fd5b815167ffffffffffffffff81168114610cba57600080fd5b60005b83811015610d06578181015183820152602001610cee565b83811115610d15576000848401525b50505050565b60008151808452610d33816020860160208601610ceb565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b604081526000610d786040830184610d1b565b8281036020840152600c81527f2e726f6f745f6b65795b305d000000000000000000000000000000000000000060208201526040810191505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715610e2d57610e2d610db7565b604052919050565b60006020808385031215610e4857600080fd5b825167ffffffffffffffff80821115610e6057600080fd5b8185019150601f8681840112610e7557600080fd5b825182811115610e8757610e87610db7565b8060051b610e96868201610de6565b918252848101860191868101908a841115610eb057600080fd5b87870192505b83831015610f5b57825186811115610ece5760008081fd5b8701603f81018c13610ee05760008081fd5b88810151604088821115610ef657610ef6610db7565b610f258b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08a85011601610de6565b8281528e82848601011115610f3a5760008081fd5b610f49838d8301848701610ceb565b85525050509187019190870190610eb6565b9a9950505050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602081526000610cba6020830184610d1b565b604081526000610fbe6040830185610d1b565b905073ffffffffffffffffffffffffffffffffffffffff831660208301529392505050565b604081526000610ff66040830185610d1b565b905082151560208301529392505050565b60408152600061101a6040830185610d1b565b90508260208301529392505050565b60608152600061103c6060830186610d1b565b828103602084015261104e8186610d1b565b905082810360408401526110628185610d1b565b969550505050505056fea164736f6c634300080f000a","sourceMap":"2318:1449:0:-:0;;;;;;;;;;;;;;;;;;;","linkReferences":{}},"deployedBytecode":{"object":"0x608060405234801561001057600080fd5b50600436106100365760003560e01c8063a777d0dc1461003b578063c040622614610050575b600080fd5b61004e610049366004610c26565b610058565b005b61004e6100da565b61009782828080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061092d92505050565b6100d66040518060400160405280601081526020017f68656c6c6f206d73672e73656e64657200000000000000000000000000000000815250336109bf565b5050565b604080517f4777f3cf0000000000000000000000000000000000000000000000000000000081526004810191909152600c60448201527f4558414d504c455f424f4f4c0000000000000000000000000000000000000000606482015260006024820181905290737109709ecfa91a80626ff3989d68f67f5b1dd12d90634777f3cf90608401602060405180830381865afa15801561017c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101a09190610c98565b90506101e16040518060400160405280601381526020017f626f6f6c2076616c75652066726f6d20656e760000000000000000000000000081525082610a50565b6102206040518060400160405280600d81526020017f636f6e7472616374206164647200000000000000000000000000000000000000815250306109bf565b604080518082018252600e81527f636f6e7472616374206e6f6e6365000000000000000000000000000000000000602082015290517f2d0335ab0000000000000000000000000000000000000000000000000000000081523060048201526102f39190737109709ecfa91a80626ff3989d68f67f5b1dd12d90632d0335ab906024015b602060405180830381865afa1580156102c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102e49190610cc1565b67ffffffffffffffff16610ae1565b6103326040518060400160405280600b81526020017f73656e6465722061646472000000000000000000000000000000000000000000815250336109bf565b604080518082018252600c81527f73656e646572206e6f6e63650000000000000000000000000000000000000000602082015290517f2d0335ab0000000000000000000000000000000000000000000000000000000081523360048201526103b99190737109709ecfa91a80626ff3989d68f67f5b1dd12d90632d0335ab906024016102a3565b60408051808201825260208082527f7b22726f6f745f6b6579223a205b7b2261223a20312c202262223a20327d5d7d9082015290517f213e4198000000000000000000000000000000000000000000000000000000008152600090737109709ecfa91a80626ff3989d68f67f5b1dd12d9063213e41989061043e908590600401610d65565b600060405180830381865afa15801561045b573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526104a19190810190610e35565b90506105176040518060400160405280600481526020017f6b65797300000000000000000000000000000000000000000000000000000000815250826000815181106104ef576104ef610f69565b60200260200101518360018151811061050a5761050a610f69565b6020026020010151610b72565b6040517fa777d0dc00000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f66726f6d206f726967696e616c000000000000000000000000000000000000006044820152309063a777d0dc9060640160006040518083038186803b15801561059457600080fd5b505afa1580156105a8573d6000803e3d6000fd5b50506040517f06447d5600000000000000000000000000000000000000000000000000000000815260426004820152737109709ecfa91a80626ff3989d68f67f5b1dd12d92506306447d569150602401600060405180830381600087803b15801561061257600080fd5b505af1158015610626573d6000803e3d6000fd5b50506040517fa777d0dc00000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f66726f6d207072616e6b20310000000000000000000000000000000000000000604482015230925063a777d0dc915060640160006040518083038186803b1580156106a757600080fd5b505afa1580156106bb573d6000803e3d6000fd5b505050506106fe6040518060400160405280601781526020017f706172656e742073636f7065206d73672e73656e646572000000000000000000815250336109bf565b61073d6040518060400160405280601a81526020017f706172656e742073636f706520636f6e74726163742e61646472000000000000815250306109bf565b6040517fa777d0dc00000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f66726f6d207072616e6b203200000000000000000000000000000000000000006044820152309063a777d0dc9060640160006040518083038186803b1580156107ba57600080fd5b505afa1580156107ce573d6000803e3d6000fd5b505050507f885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d60001c73ffffffffffffffffffffffffffffffffffffffff166390c5013b6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561083d57600080fd5b505af1158015610851573d6000803e3d6000fd5b50506040517fa777d0dc00000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f66726f6d206f726967696e616c20616761696e00000000000000000000000000604482015230925063a777d0dc915060640160006040518083038186803b1580156108d257600080fd5b505afa1580156108e6573d6000803e3d6000fd5b505050506109286040518060400160405280600581526020017f646f6e652100000000000000000000000000000000000000000000000000000081525061092d565b505050565b6109bc816040516024016109419190610f98565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f41304fac00000000000000000000000000000000000000000000000000000000179052610c01565b50565b6100d682826040516024016109d5929190610fab565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f319af33300000000000000000000000000000000000000000000000000000000179052610c01565b6100d68282604051602401610a66929190610fe3565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fc3b5563500000000000000000000000000000000000000000000000000000000179052610c01565b6100d68282604051602401610af7929190611007565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fb60e72cc00000000000000000000000000000000000000000000000000000000179052610c01565b610928838383604051602401610b8a93929190611029565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f2ced7cef000000000000000000000000000000000000000000000000000000001790525b6109bc8180516a636f6e736f6c652e6c6f67602083016000808483855afa5050505050565b60008060208385031215610c3957600080fd5b823567ffffffffffffffff80821115610c5157600080fd5b818501915085601f830112610c6557600080fd5b813581811115610c7457600080fd5b866020828501011115610c8657600080fd5b60209290920196919550909350505050565b600060208284031215610caa57600080fd5b81518015158114610cba57600080fd5b9392505050565b600060208284031215610cd357600080fd5b815167ffffffffffffffff81168114610cba57600080fd5b60005b83811015610d06578181015183820152602001610cee565b83811115610d15576000848401525b50505050565b60008151808452610d33816020860160208601610ceb565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b604081526000610d786040830184610d1b565b8281036020840152600c81527f2e726f6f745f6b65795b305d000000000000000000000000000000000000000060208201526040810191505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715610e2d57610e2d610db7565b604052919050565b60006020808385031215610e4857600080fd5b825167ffffffffffffffff80821115610e6057600080fd5b8185019150601f8681840112610e7557600080fd5b825182811115610e8757610e87610db7565b8060051b610e96868201610de6565b918252848101860191868101908a841115610eb057600080fd5b87870192505b83831015610f5b57825186811115610ece5760008081fd5b8701603f81018c13610ee05760008081fd5b88810151604088821115610ef657610ef6610db7565b610f258b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08a85011601610de6565b8281528e82848601011115610f3a5760008081fd5b610f49838d8301848701610ceb565b85525050509187019190870190610eb6565b9a9950505050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602081526000610cba6020830184610d1b565b604081526000610fbe6040830185610d1b565b905073ffffffffffffffffffffffffffffffffffffffff831660208301529392505050565b604081526000610ff66040830185610d1b565b905082151560208301529392505050565b60408152600061101a6040830185610d1b565b90508260208301529392505050565b60608152600061103c6060830186610d1b565b828103602084015261104e8186610d1b565b905082810360408401526110628185610d1b565b969550505050505056fea164736f6c634300080f000a","sourceMap":"2318:1449:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3622:143;;;;;;:::i;:::-;;:::i;:::-;;2578:949;;;:::i;3622:143::-;3681:15;3693:2;;3681:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;3681:11:0;;-1:-1:-1;;;3681:15:0:i;:::-;3706:52;;;;;;;;;;;;;;;;;;3746:10;3706:11;:52::i;:::-;3622:143;;:::o;2578:949::-;2619:31;;;;;;;;;817:21:1;;;;874:2;854:18;;;847:30;913:14;893:18;;;886:42;2610:6:0;980:20:1;;;973:52;;;2610:6:0;2619:8;;;;945:19:1;;2619:31:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;2610:40;;2660:37;;;;;;;;;;;;;;;;;;2695:1;2660:11;:37::i;:::-;2708:43;;;;;;;;;;;;;;;;;;2745:4;2708:11;:43::i;:::-;2761:57;;;;;;;;;;;;;;;;2791:26;;;;;2811:4;2791:26;;;1464:74:1;2761:57:0;;;2791:11;;;;1437:18:1;;2791:26:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;2761:57;;:11;:57::i;:::-;2828:47;;;;;;;;;;;;;;;;;;2863:10;2828:11;:47::i;:::-;2885:61;;;;;;;;;;;;;;;;2913:32;;;;;2933:10;2913:32;;;1464:74:1;2885:61:0;;;2913:11;;;;1437:18:1;;2913:32:0;1318:226:1;2885:61:0;2957:55;;;;;;;;;;;;;;;;;3045:38;;;;;2957:18;;3045:16;;;;:38;;2957:55;;3045:38;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;3022:61;;3093:37;;;;;;;;;;;;;;;;;;3113:4;3118:1;3113:7;;;;;;;;:::i;:::-;;;;;;;3122:4;3127:1;3122:7;;;;;;;;:::i;:::-;;;;;;;3093:11;:37::i;:::-;3141:27;;;;;5650:2:1;3141:27:0;;;5632:21:1;5689:2;5669:18;;;5662:30;5728:15;5708:18;;;5701:43;3141:4:0;;:10;;5761:18:1;;3141:27:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;3178:37:0;;;;;3208:4;3178:37;;;1464:74:1;3178:13:0;;-1:-1:-1;3178:13:0;;-1:-1:-1;1437:18:1;;3178:37:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;3225:26:0;;;;;5992:2:1;3225:26:0;;;5974:21:1;6031:2;6011:18;;;6004:30;6070:14;6050:18;;;6043:42;3225:4:0;;-1:-1:-1;3225:10:0;;-1:-1:-1;6102:18:1;;3225:26:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3261:59;;;;;;;;;;;;;;;;;;3308:10;3261:11;:59::i;:::-;3330:56;;;;;;;;;;;;;;;;;;3380:4;3330:11;:56::i;:::-;3396:26;;;;;6333:2:1;3396:26:0;;;6315:21:1;6372:2;6352:18;;;6345:30;6411:14;6391:18;;;6384:42;3396:4:0;;:10;;6443:18:1;;3396:26:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2411:28;2403:37;;3432:12;;;:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;3456:33:0;;;;;6674:2:1;3456:33:0;;;6656:21:1;6713:2;6693:18;;;6686:30;6752:21;6732:18;;;6725:49;3456:4:0;;-1:-1:-1;3456:10:0;;-1:-1:-1;6791:18:1;;3456:33:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3500:20;;;;;;;;;;;;;;;;;;:11;:20::i;:::-;2600:927;;;2578:949::o;1435:121::-;1490:59;1545:2;1506:42;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;1490:15;:59::i;:::-;1435:121;:::o;1858:145::-;1925:71;1988:2;1992;1941:54;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;1925:15;:71::i;1562:139::-;1626:68;1686:2;1690;1642:51;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;1626:15;:68::i;1707:145::-;1774:71;1837:2;1841;1790:54;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;1774:15;:71::i;2009:179::-;2100:81;2169:2;2173;2177;2116:64;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;910:133;981:55;1028:7;1147:14;;633:42;1320:2;1307:16;;1123:21;;1147:14;1307:16;633:42;1356:5;1345:68;1336:77;;1273:150;;1049:380;:::o;14:592:1:-;85:6;93;146:2;134:9;125:7;121:23;117:32;114:52;;;162:1;159;152:12;114:52;202:9;189:23;231:18;272:2;264:6;261:14;258:34;;;288:1;285;278:12;258:34;326:6;315:9;311:22;301:32;;371:7;364:4;360:2;356:13;352:27;342:55;;393:1;390;383:12;342:55;433:2;420:16;459:2;451:6;448:14;445:34;;;475:1;472;465:12;445:34;520:7;515:2;506:6;502:2;498:15;494:24;491:37;488:57;;;541:1;538;531:12;488:57;572:2;564:11;;;;;594:6;;-1:-1:-1;14:592:1;;-1:-1:-1;;;;14:592:1:o;1036:277::-;1103:6;1156:2;1144:9;1135:7;1131:23;1127:32;1124:52;;;1172:1;1169;1162:12;1124:52;1204:9;1198:16;1257:5;1250:13;1243:21;1236:5;1233:32;1223:60;;1279:1;1276;1269:12;1223:60;1302:5;1036:277;-1:-1:-1;;;1036:277:1:o;1549:288::-;1618:6;1671:2;1659:9;1650:7;1646:23;1642:32;1639:52;;;1687:1;1684;1677:12;1639:52;1719:9;1713:16;1769:18;1762:5;1758:30;1751:5;1748:41;1738:69;;1803:1;1800;1793:12;1842:258;1914:1;1924:113;1938:6;1935:1;1932:13;1924:113;;;2014:11;;;2008:18;1995:11;;;1988:39;1960:2;1953:10;1924:113;;;2055:6;2052:1;2049:13;2046:48;;;2090:1;2081:6;2076:3;2072:16;2065:27;2046:48;;1842:258;;;:::o;2105:317::-;2147:3;2185:5;2179:12;2212:6;2207:3;2200:19;2228:63;2284:6;2277:4;2272:3;2268:14;2261:4;2254:5;2250:16;2228:63;:::i;:::-;2336:2;2324:15;2341:66;2320:88;2311:98;;;;2411:4;2307:109;;2105:317;-1:-1:-1;;2105:317:1:o;2427:493::-;2677:2;2666:9;2659:21;2640:4;2703:45;2744:2;2733:9;2729:18;2721:6;2703:45;:::i;:::-;2796:9;2788:6;2784:22;2779:2;2768:9;2764:18;2757:50;2831:2;2823:6;2816:18;2867:14;2862:2;2854:6;2850:15;2843:39;2911:2;2903:6;2899:15;2891:23;;;2427:493;;;;:::o;2925:184::-;2977:77;2974:1;2967:88;3074:4;3071:1;3064:15;3098:4;3095:1;3088:15;3114:334;3185:2;3179:9;3241:2;3231:13;;3246:66;3227:86;3215:99;;3344:18;3329:34;;3365:22;;;3326:62;3323:88;;;3391:18;;:::i;:::-;3427:2;3420:22;3114:334;;-1:-1:-1;3114:334:1:o;3453:1801::-;3558:6;3589:2;3632;3620:9;3611:7;3607:23;3603:32;3600:52;;;3648:1;3645;3638:12;3600:52;3681:9;3675:16;3710:18;3751:2;3743:6;3740:14;3737:34;;;3767:1;3764;3757:12;3737:34;3805:6;3794:9;3790:22;3780:32;;3831:4;3871:7;3866:2;3862;3858:11;3854:25;3844:53;;3893:1;3890;3883:12;3844:53;3922:2;3916:9;3944:2;3940;3937:10;3934:36;;;3950:18;;:::i;:::-;3996:2;3993:1;3989:10;4019:28;4043:2;4039;4035:11;4019:28;:::i;:::-;4081:15;;;4151:11;;;4147:20;;;4112:12;;;;4179:19;;;4176:39;;;4211:1;4208;4201:12;4176:39;4243:2;4239;4235:11;4224:22;;4255:969;4271:6;4266:3;4263:15;4255:969;;;4350:3;4344:10;4386:2;4373:11;4370:19;4367:109;;;4430:1;4459:2;4455;4448:14;4367:109;4499:20;;4554:2;4546:11;;4542:25;-1:-1:-1;4532:123:1;;4609:1;4638:2;4634;4627:14;4532:123;4693:2;4689;4685:11;4679:18;4721:2;4747;4742:3;4739:11;4736:37;;;4753:18;;:::i;:::-;4799:111;4906:2;4837:66;4832:2;4827:3;4823:12;4819:85;4815:94;4799:111;:::i;:::-;4937:3;4930:5;4923:18;4984:7;4978:3;4972;4968:2;4964:12;4960:22;4957:35;4954:128;;;5034:1;5064:3;5059;5052:16;4954:128;5095:56;5147:3;5142:2;5135:5;5131:14;5125:3;5121:2;5117:12;5095:56;:::i;:::-;5164:18;;-1:-1:-1;;;4288:12:1;;;;5202;;;;4255:969;;;5243:5;3453:1801;-1:-1:-1;;;;;;;;;;3453:1801:1:o;5259:184::-;5311:77;5308:1;5301:88;5408:4;5405:1;5398:15;5432:4;5429:1;5422:15;6820:220;6969:2;6958:9;6951:21;6932:4;6989:45;7030:2;7019:9;7015:18;7007:6;6989:45;:::i;7045:340::-;7222:2;7211:9;7204:21;7185:4;7242:45;7283:2;7272:9;7268:18;7260:6;7242:45;:::i;:::-;7234:53;;7335:42;7327:6;7323:55;7318:2;7307:9;7303:18;7296:83;7045:340;;;;;:::o;7390:301::-;7561:2;7550:9;7543:21;7524:4;7581:45;7622:2;7611:9;7607:18;7599:6;7581:45;:::i;:::-;7573:53;;7676:6;7669:14;7662:22;7657:2;7646:9;7642:18;7635:50;7390:301;;;;;:::o;7696:291::-;7873:2;7862:9;7855:21;7836:4;7893:45;7934:2;7923:9;7919:18;7911:6;7893:45;:::i;:::-;7885:53;;7974:6;7969:2;7958:9;7954:18;7947:34;7696:291;;;;;:::o;7992:546::-;8237:2;8226:9;8219:21;8200:4;8263:45;8304:2;8293:9;8289:18;8281:6;8263:45;:::i;:::-;8356:9;8348:6;8344:22;8339:2;8328:9;8324:18;8317:50;8390:33;8416:6;8408;8390:33;:::i;:::-;8376:47;;8471:9;8463:6;8459:22;8454:2;8443:9;8439:18;8432:50;8499:33;8525:6;8517;8499:33;:::i;:::-;8491:41;7992:546;-1:-1:-1;;;;;;7992:546:1:o","linkReferences":{}},"methodIdentifiers":{"hello(string)":"a777d0dc","run()":"c0406226"},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_v\",\"type\":\"string\"}],\"name\":\"hello\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"run\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"title\":\"ScriptExample\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"hello(string)\":{\"notice\":\"example external function, to force a CALL, and test vm.startPrank with.\"},\"run()\":{\"notice\":\"example function, runs through basic cheat-codes and console logs.\"}},\"notice\":\"ScriptExample is an example script. The Go forge script code tests that it can run this.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"scripts/ScriptExample.s.sol\":\"ScriptExample\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[]},\"sources\":{\"scripts/ScriptExample.s.sol\":{\"keccak256\":\"0x531a2ad96c1a2c0bbfa9ab0e1195cd32551b0c10e16e7d256ce5e4c0289a8089\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://24dc6c71502c01f43fb5e113786e377c3b4cafabd5c506067d229fcdd7b037fa\",\"dweb:/ipfs/QmZ9AuxNx9Ygescfg5M4p6Abc2CCwCMZpX5xU32Fz1r4kY\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.15+commit.e14f2714"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"string","name":"_v","type":"string"}],"stateMutability":"view","type":"function","name":"hello"},{"inputs":[],"stateMutability":"nonpayable","type":"function","name":"run"}],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{"hello(string)":{"notice":"example external function, to force a CALL, and test vm.startPrank with."},"run()":{"notice":"example function, runs through basic cheat-codes and console logs."}},"version":1}},"settings":{"remappings":[],"optimizer":{"enabled":true,"runs":999999},"metadata":{"bytecodeHash":"none"},"compilationTarget":{"scripts/ScriptExample.s.sol":"ScriptExample"},"evmVersion":"london","libraries":{}},"sources":{"scripts/ScriptExample.s.sol":{"keccak256":"0x531a2ad96c1a2c0bbfa9ab0e1195cd32551b0c10e16e7d256ce5e4c0289a8089","urls":["bzz-raw://24dc6c71502c01f43fb5e113786e377c3b4cafabd5c506067d229fcdd7b037fa","dweb:/ipfs/QmZ9AuxNx9Ygescfg5M4p6Abc2CCwCMZpX5xU32Fz1r4kY"],"license":"MIT"}},"version":1},"storageLayout":{"storage":[],"types":{}},"userdoc":{"version":1,"kind":"user","methods":{"hello(string)":{"notice":"example external function, to force a CALL, and test vm.startPrank with."},"run()":{"notice":"example function, runs through basic cheat-codes and console logs."}},"notice":"ScriptExample is an example script. The Go forge script code tests that it can run this."},"devdoc":{"version":1,"kind":"dev","title":"ScriptExample"},"ast":{"absolutePath":"scripts/ScriptExample.s.sol","id":383,"exportedSymbols":{"ScriptExample":[382],"Vm":[36],"console":[173]},"nodeType":"SourceUnit","src":"32:3736:0","nodes":[{"id":1,"nodeType":"PragmaDirective","src":"32:23:0","nodes":[],"literals":["solidity","0.8",".15"]},{"id":36,"nodeType":"ContractDefinition","src":"120:393:0","nodes":[{"id":10,"nodeType":"FunctionDefinition","src":"139:91:0","nodes":[],"functionSelector":"4777f3cf","implemented":false,"kind":"function","modifiers":[],"name":"envOr","nameLocation":"148:5:0","parameters":{"id":6,"nodeType":"ParameterList","parameters":[{"constant":false,"id":3,"mutability":"mutable","name":"name","nameLocation":"170:4:0","nodeType":"VariableDeclaration","scope":10,"src":"154:20:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":2,"name":"string","nodeType":"ElementaryTypeName","src":"154:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":5,"mutability":"mutable","name":"defaultValue","nameLocation":"181:12:0","nodeType":"VariableDeclaration","scope":10,"src":"176:17:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":4,"name":"bool","nodeType":"ElementaryTypeName","src":"176:4:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"src":"153:41:0"},"returnParameters":{"id":9,"nodeType":"ParameterList","parameters":[{"constant":false,"id":8,"mutability":"mutable","name":"value","nameLocation":"223:5:0","nodeType":"VariableDeclaration","scope":10,"src":"218:10:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":7,"name":"bool","nodeType":"ElementaryTypeName","src":"218:4:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"src":"217:12:0"},"scope":36,"stateMutability":"view","virtual":false,"visibility":"external"},{"id":17,"nodeType":"FunctionDefinition","src":"235:72:0","nodes":[],"functionSelector":"2d0335ab","implemented":false,"kind":"function","modifiers":[],"name":"getNonce","nameLocation":"244:8:0","parameters":{"id":13,"nodeType":"ParameterList","parameters":[{"constant":false,"id":12,"mutability":"mutable","name":"account","nameLocation":"261:7:0","nodeType":"VariableDeclaration","scope":17,"src":"253:15:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":11,"name":"address","nodeType":"ElementaryTypeName","src":"253:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"252:17:0"},"returnParameters":{"id":16,"nodeType":"ParameterList","parameters":[{"constant":false,"id":15,"mutability":"mutable","name":"nonce","nameLocation":"300:5:0","nodeType":"VariableDeclaration","scope":17,"src":"293:12:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"},"typeName":{"id":14,"name":"uint64","nodeType":"ElementaryTypeName","src":"293:6:0","typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}},"visibility":"internal"}],"src":"292:14:0"},"scope":36,"stateMutability":"view","virtual":false,"visibility":"external"},{"id":27,"nodeType":"FunctionDefinition","src":"312:111:0","nodes":[],"functionSelector":"213e4198","implemented":false,"kind":"function","modifiers":[],"name":"parseJsonKeys","nameLocation":"321:13:0","parameters":{"id":22,"nodeType":"ParameterList","parameters":[{"constant":false,"id":19,"mutability":"mutable","name":"json","nameLocation":"351:4:0","nodeType":"VariableDeclaration","scope":27,"src":"335:20:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":18,"name":"string","nodeType":"ElementaryTypeName","src":"335:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":21,"mutability":"mutable","name":"key","nameLocation":"373:3:0","nodeType":"VariableDeclaration","scope":27,"src":"357:19:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":20,"name":"string","nodeType":"ElementaryTypeName","src":"357:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"334:43:0"},"returnParameters":{"id":26,"nodeType":"ParameterList","parameters":[{"constant":false,"id":25,"mutability":"mutable","name":"keys","nameLocation":"417:4:0","nodeType":"VariableDeclaration","scope":27,"src":"401:20:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string[]"},"typeName":{"baseType":{"id":23,"name":"string","nodeType":"ElementaryTypeName","src":"401:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"id":24,"nodeType":"ArrayTypeName","src":"401:8:0","typeDescriptions":{"typeIdentifier":"t_array$_t_string_storage_$dyn_storage_ptr","typeString":"string[]"}},"visibility":"internal"}],"src":"400:22:0"},"scope":36,"stateMutability":"pure","virtual":false,"visibility":"external"},{"id":32,"nodeType":"FunctionDefinition","src":"428:48:0","nodes":[],"functionSelector":"06447d56","implemented":false,"kind":"function","modifiers":[],"name":"startPrank","nameLocation":"437:10:0","parameters":{"id":30,"nodeType":"ParameterList","parameters":[{"constant":false,"id":29,"mutability":"mutable","name":"msgSender","nameLocation":"456:9:0","nodeType":"VariableDeclaration","scope":32,"src":"448:17:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":28,"name":"address","nodeType":"ElementaryTypeName","src":"448:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"447:19:0"},"returnParameters":{"id":31,"nodeType":"ParameterList","parameters":[],"src":"475:0:0"},"scope":36,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":35,"nodeType":"FunctionDefinition","src":"481:30:0","nodes":[],"functionSelector":"90c5013b","implemented":false,"kind":"function","modifiers":[],"name":"stopPrank","nameLocation":"490:9:0","parameters":{"id":33,"nodeType":"ParameterList","parameters":[],"src":"499:2:0"},"returnParameters":{"id":34,"nodeType":"ParameterList","parameters":[],"src":"510:0:0"},"scope":36,"stateMutability":"nonpayable","virtual":false,"visibility":"external"}],"abstract":false,"baseContracts":[],"canonicalName":"Vm","contractDependencies":[],"contractKind":"interface","fullyImplemented":false,"linearizedBaseContracts":[36],"name":"Vm","nameLocation":"130:2:0","scope":383,"usedErrors":[]},{"id":173,"nodeType":"ContractDefinition","src":"568:1622:0","nodes":[{"id":42,"nodeType":"VariableDeclaration","src":"590:86:0","nodes":[],"constant":true,"mutability":"constant","name":"CONSOLE_ADDRESS","nameLocation":"607:15:0","scope":173,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":37,"name":"address","nodeType":"ElementaryTypeName","src":"590:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"value":{"arguments":[{"hexValue":"307830303030303030303030303030303030303036333646366537333646366336353265366336663637","id":40,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"633:42:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"value":"0x000000000000000000636F6e736F6c652e6c6f67"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":39,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"625:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":38,"name":"address","nodeType":"ElementaryTypeName","src":"625:7:0","typeDescriptions":{}}},"id":41,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"625:51:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"},{"id":59,"nodeType":"FunctionDefinition","src":"683:221:0","nodes":[],"body":{"id":58,"nodeType":"Block","src":"842:62:0","nodes":[],"statements":[{"AST":{"nodeType":"YulBlock","src":"861:37:0","statements":[{"nodeType":"YulAssignment","src":"875:13:0","value":{"name":"fnIn","nodeType":"YulIdentifier","src":"884:4:0"},"variableNames":[{"name":"fnOut","nodeType":"YulIdentifier","src":"875:5:0"}]}]},"evmVersion":"london","externalReferences":[{"declaration":48,"isOffset":false,"isSlot":false,"src":"884:4:0","valueSize":1},{"declaration":55,"isOffset":false,"isSlot":false,"src":"875:5:0","valueSize":1}],"id":57,"nodeType":"InlineAssembly","src":"852:46:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"_castLogPayloadViewToPure","nameLocation":"692:25:0","parameters":{"id":49,"nodeType":"ParameterList","parameters":[{"constant":false,"id":48,"mutability":"mutable","name":"fnIn","nameLocation":"764:4:0","nodeType":"VariableDeclaration","scope":59,"src":"727:41:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_function_internal_view$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes) view"},"typeName":{"id":47,"nodeType":"FunctionTypeName","parameterTypes":{"id":45,"nodeType":"ParameterList","parameters":[{"constant":false,"id":44,"mutability":"mutable","name":"","nameLocation":"-1:-1:-1","nodeType":"VariableDeclaration","scope":47,"src":"736:12:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":43,"name":"bytes","nodeType":"ElementaryTypeName","src":"736:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"735:14:0"},"returnParameterTypes":{"id":46,"nodeType":"ParameterList","parameters":[],"src":"764:0:0"},"src":"727:41:0","stateMutability":"view","typeDescriptions":{"typeIdentifier":"t_function_internal_view$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes) view"},"visibility":"internal"},"visibility":"internal"}],"src":"717:57:0"},"returnParameters":{"id":56,"nodeType":"ParameterList","parameters":[{"constant":false,"id":55,"mutability":"mutable","name":"fnOut","nameLocation":"835:5:0","nodeType":"VariableDeclaration","scope":59,"src":"798:42:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes) pure"},"typeName":{"id":54,"nodeType":"FunctionTypeName","parameterTypes":{"id":52,"nodeType":"ParameterList","parameters":[{"constant":false,"id":51,"mutability":"mutable","name":"","nameLocation":"-1:-1:-1","nodeType":"VariableDeclaration","scope":54,"src":"807:12:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":50,"name":"bytes","nodeType":"ElementaryTypeName","src":"807:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"806:14:0"},"returnParameterTypes":{"id":53,"nodeType":"ParameterList","parameters":[],"src":"835:0:0"},"src":"798:42:0","stateMutability":"pure","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes) pure"},"visibility":"internal"},"visibility":"internal"}],"src":"797:44:0"},"scope":173,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":71,"nodeType":"FunctionDefinition","src":"910:133:0","nodes":[],"body":{"id":70,"nodeType":"Block","src":"971:72:0","nodes":[],"statements":[{"expression":{"arguments":[{"id":67,"name":"payload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":61,"src":"1028:7:0","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"arguments":[{"id":65,"name":"_sendLogPayloadView","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":87,"src":"1007:19:0","typeDescriptions":{"typeIdentifier":"t_function_internal_view$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) view"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_function_internal_view$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) view"}],"id":64,"name":"_castLogPayloadViewToPure","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":59,"src":"981:25:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_function_internal_view$_t_bytes_memory_ptr_$returns$__$_$returns$_t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$_$","typeString":"function (function (bytes memory) view) pure returns (function (bytes memory) pure)"}},"id":66,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"981:46:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":68,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"981:55:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":69,"nodeType":"ExpressionStatement","src":"981:55:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"_sendLogPayload","nameLocation":"919:15:0","parameters":{"id":62,"nodeType":"ParameterList","parameters":[{"constant":false,"id":61,"mutability":"mutable","name":"payload","nameLocation":"948:7:0","nodeType":"VariableDeclaration","scope":71,"src":"935:20:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":60,"name":"bytes","nodeType":"ElementaryTypeName","src":"935:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"934:22:0"},"returnParameters":{"id":63,"nodeType":"ParameterList","parameters":[],"src":"971:0:0"},"scope":173,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":87,"nodeType":"FunctionDefinition","src":"1049:380:0","nodes":[],"body":{"id":86,"nodeType":"Block","src":"1113:316:0","nodes":[],"statements":[{"assignments":[77],"declarations":[{"constant":false,"id":77,"mutability":"mutable","name":"payloadLength","nameLocation":"1131:13:0","nodeType":"VariableDeclaration","scope":86,"src":"1123:21:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":76,"name":"uint256","nodeType":"ElementaryTypeName","src":"1123:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"}],"id":80,"initialValue":{"expression":{"id":78,"name":"payload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":73,"src":"1147:7:0","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}},"id":79,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"length","nodeType":"MemberAccess","src":"1147:14:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"nodeType":"VariableDeclarationStatement","src":"1123:38:0"},{"assignments":[82],"declarations":[{"constant":false,"id":82,"mutability":"mutable","name":"consoleAddress","nameLocation":"1179:14:0","nodeType":"VariableDeclaration","scope":86,"src":"1171:22:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":81,"name":"address","nodeType":"ElementaryTypeName","src":"1171:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"id":84,"initialValue":{"id":83,"name":"CONSOLE_ADDRESS","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":42,"src":"1196:15:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"nodeType":"VariableDeclarationStatement","src":"1171:40:0"},{"AST":{"nodeType":"YulBlock","src":"1273:150:0","statements":[{"nodeType":"YulVariableDeclaration","src":"1287:36:0","value":{"arguments":[{"name":"payload","nodeType":"YulIdentifier","src":"1311:7:0"},{"kind":"number","nodeType":"YulLiteral","src":"1320:2:0","type":"","value":"32"}],"functionName":{"name":"add","nodeType":"YulIdentifier","src":"1307:3:0"},"nodeType":"YulFunctionCall","src":"1307:16:0"},"variables":[{"name":"payloadStart","nodeType":"YulTypedName","src":"1291:12:0","type":""}]},{"nodeType":"YulVariableDeclaration","src":"1336:77:0","value":{"arguments":[{"arguments":[],"functionName":{"name":"gas","nodeType":"YulIdentifier","src":"1356:3:0"},"nodeType":"YulFunctionCall","src":"1356:5:0"},{"name":"consoleAddress","nodeType":"YulIdentifier","src":"1363:14:0"},{"name":"payloadStart","nodeType":"YulIdentifier","src":"1379:12:0"},{"name":"payloadLength","nodeType":"YulIdentifier","src":"1393:13:0"},{"kind":"number","nodeType":"YulLiteral","src":"1408:1:0","type":"","value":"0"},{"kind":"number","nodeType":"YulLiteral","src":"1411:1:0","type":"","value":"0"}],"functionName":{"name":"staticcall","nodeType":"YulIdentifier","src":"1345:10:0"},"nodeType":"YulFunctionCall","src":"1345:68:0"},"variables":[{"name":"r","nodeType":"YulTypedName","src":"1340:1:0","type":""}]}]},"documentation":"@solidity memory-safe-assembly","evmVersion":"london","externalReferences":[{"declaration":82,"isOffset":false,"isSlot":false,"src":"1363:14:0","valueSize":1},{"declaration":73,"isOffset":false,"isSlot":false,"src":"1311:7:0","valueSize":1},{"declaration":77,"isOffset":false,"isSlot":false,"src":"1393:13:0","valueSize":1}],"id":85,"nodeType":"InlineAssembly","src":"1264:159:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"_sendLogPayloadView","nameLocation":"1058:19:0","parameters":{"id":74,"nodeType":"ParameterList","parameters":[{"constant":false,"id":73,"mutability":"mutable","name":"payload","nameLocation":"1091:7:0","nodeType":"VariableDeclaration","scope":87,"src":"1078:20:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":72,"name":"bytes","nodeType":"ElementaryTypeName","src":"1078:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"1077:22:0"},"returnParameters":{"id":75,"nodeType":"ParameterList","parameters":[],"src":"1113:0:0"},"scope":173,"stateMutability":"view","virtual":false,"visibility":"private"},{"id":101,"nodeType":"FunctionDefinition","src":"1435:121:0","nodes":[],"body":{"id":100,"nodeType":"Block","src":"1480:76:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e6729","id":95,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"1530:13:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_41304facd9323d75b11bcdd609cb38effffdb05710f7caf0e9b16c6d9d709f50","typeString":"literal_string \"log(string)\""},"value":"log(string)"},{"id":96,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":89,"src":"1545:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_41304facd9323d75b11bcdd609cb38effffdb05710f7caf0e9b16c6d9d709f50","typeString":"literal_string \"log(string)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}],"expression":{"id":93,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"1506:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":94,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"1506:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":97,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1506:42:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":92,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":71,"src":"1490:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":98,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1490:59:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":99,"nodeType":"ExpressionStatement","src":"1490:59:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"1444:3:0","parameters":{"id":90,"nodeType":"ParameterList","parameters":[{"constant":false,"id":89,"mutability":"mutable","name":"p0","nameLocation":"1462:2:0","nodeType":"VariableDeclaration","scope":101,"src":"1448:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":88,"name":"string","nodeType":"ElementaryTypeName","src":"1448:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"1447:18:0"},"returnParameters":{"id":91,"nodeType":"ParameterList","parameters":[],"src":"1480:0:0"},"scope":173,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":118,"nodeType":"FunctionDefinition","src":"1562:139:0","nodes":[],"body":{"id":117,"nodeType":"Block","src":"1616:85:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e672c626f6f6c29","id":111,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"1666:18:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_c3b556354c088fbb43886eb83c2a04bc7089663f964d22be308197a236f5b870","typeString":"literal_string \"log(string,bool)\""},"value":"log(string,bool)"},{"id":112,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":103,"src":"1686:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":113,"name":"p1","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":105,"src":"1690:2:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_c3b556354c088fbb43886eb83c2a04bc7089663f964d22be308197a236f5b870","typeString":"literal_string \"log(string,bool)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_bool","typeString":"bool"}],"expression":{"id":109,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"1642:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":110,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"1642:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":114,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1642:51:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":108,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":71,"src":"1626:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":115,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1626:68:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":116,"nodeType":"ExpressionStatement","src":"1626:68:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"1571:3:0","parameters":{"id":106,"nodeType":"ParameterList","parameters":[{"constant":false,"id":103,"mutability":"mutable","name":"p0","nameLocation":"1589:2:0","nodeType":"VariableDeclaration","scope":118,"src":"1575:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":102,"name":"string","nodeType":"ElementaryTypeName","src":"1575:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":105,"mutability":"mutable","name":"p1","nameLocation":"1598:2:0","nodeType":"VariableDeclaration","scope":118,"src":"1593:7:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":104,"name":"bool","nodeType":"ElementaryTypeName","src":"1593:4:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"src":"1574:27:0"},"returnParameters":{"id":107,"nodeType":"ParameterList","parameters":[],"src":"1616:0:0"},"scope":173,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":135,"nodeType":"FunctionDefinition","src":"1707:145:0","nodes":[],"body":{"id":134,"nodeType":"Block","src":"1764:88:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e672c75696e7432353629","id":128,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"1814:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_b60e72ccf6d57ab53eb84d7e94a9545806ed7f93c4d5673f11a64f03471e584e","typeString":"literal_string \"log(string,uint256)\""},"value":"log(string,uint256)"},{"id":129,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":120,"src":"1837:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":130,"name":"p1","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":122,"src":"1841:2:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_b60e72ccf6d57ab53eb84d7e94a9545806ed7f93c4d5673f11a64f03471e584e","typeString":"literal_string \"log(string,uint256)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_uint256","typeString":"uint256"}],"expression":{"id":126,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"1790:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":127,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"1790:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":131,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1790:54:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":125,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":71,"src":"1774:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":132,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1774:71:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":133,"nodeType":"ExpressionStatement","src":"1774:71:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"1716:3:0","parameters":{"id":123,"nodeType":"ParameterList","parameters":[{"constant":false,"id":120,"mutability":"mutable","name":"p0","nameLocation":"1734:2:0","nodeType":"VariableDeclaration","scope":135,"src":"1720:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":119,"name":"string","nodeType":"ElementaryTypeName","src":"1720:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":122,"mutability":"mutable","name":"p1","nameLocation":"1746:2:0","nodeType":"VariableDeclaration","scope":135,"src":"1738:10:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":121,"name":"uint256","nodeType":"ElementaryTypeName","src":"1738:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"}],"src":"1719:30:0"},"returnParameters":{"id":124,"nodeType":"ParameterList","parameters":[],"src":"1764:0:0"},"scope":173,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":152,"nodeType":"FunctionDefinition","src":"1858:145:0","nodes":[],"body":{"id":151,"nodeType":"Block","src":"1915:88:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e672c6164647265737329","id":145,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"1965:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_319af333460570a1937bf195dd33445c0d0951c59127da6f1f038b9fdce3fd72","typeString":"literal_string \"log(string,address)\""},"value":"log(string,address)"},{"id":146,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":137,"src":"1988:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":147,"name":"p1","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":139,"src":"1992:2:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_319af333460570a1937bf195dd33445c0d0951c59127da6f1f038b9fdce3fd72","typeString":"literal_string \"log(string,address)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":143,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"1941:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":144,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"1941:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":148,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1941:54:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":142,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":71,"src":"1925:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":149,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1925:71:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":150,"nodeType":"ExpressionStatement","src":"1925:71:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"1867:3:0","parameters":{"id":140,"nodeType":"ParameterList","parameters":[{"constant":false,"id":137,"mutability":"mutable","name":"p0","nameLocation":"1885:2:0","nodeType":"VariableDeclaration","scope":152,"src":"1871:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":136,"name":"string","nodeType":"ElementaryTypeName","src":"1871:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":139,"mutability":"mutable","name":"p1","nameLocation":"1897:2:0","nodeType":"VariableDeclaration","scope":152,"src":"1889:10:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":138,"name":"address","nodeType":"ElementaryTypeName","src":"1889:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"1870:30:0"},"returnParameters":{"id":141,"nodeType":"ParameterList","parameters":[],"src":"1915:0:0"},"scope":173,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":172,"nodeType":"FunctionDefinition","src":"2009:179:0","nodes":[],"body":{"id":171,"nodeType":"Block","src":"2090:98:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e672c737472696e672c737472696e6729","id":164,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2140:27:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_2ced7cef693312206c21f0e92e3b54e2e16bf33db5eec350c78866822c665e1f","typeString":"literal_string \"log(string,string,string)\""},"value":"log(string,string,string)"},{"id":165,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":154,"src":"2169:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":166,"name":"p1","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":156,"src":"2173:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":167,"name":"p2","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":158,"src":"2177:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_2ced7cef693312206c21f0e92e3b54e2e16bf33db5eec350c78866822c665e1f","typeString":"literal_string \"log(string,string,string)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}],"expression":{"id":162,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"2116:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":163,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"2116:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":168,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2116:64:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":161,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":71,"src":"2100:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":169,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2100:81:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":170,"nodeType":"ExpressionStatement","src":"2100:81:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"2018:3:0","parameters":{"id":159,"nodeType":"ParameterList","parameters":[{"constant":false,"id":154,"mutability":"mutable","name":"p0","nameLocation":"2036:2:0","nodeType":"VariableDeclaration","scope":172,"src":"2022:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":153,"name":"string","nodeType":"ElementaryTypeName","src":"2022:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":156,"mutability":"mutable","name":"p1","nameLocation":"2054:2:0","nodeType":"VariableDeclaration","scope":172,"src":"2040:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":155,"name":"string","nodeType":"ElementaryTypeName","src":"2040:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":158,"mutability":"mutable","name":"p2","nameLocation":"2072:2:0","nodeType":"VariableDeclaration","scope":172,"src":"2058:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":157,"name":"string","nodeType":"ElementaryTypeName","src":"2058:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"2021:54:0"},"returnParameters":{"id":160,"nodeType":"ParameterList","parameters":[],"src":"2090:0:0"},"scope":173,"stateMutability":"pure","virtual":false,"visibility":"internal"}],"abstract":false,"baseContracts":[],"canonicalName":"console","contractDependencies":[],"contractKind":"library","fullyImplemented":true,"linearizedBaseContracts":[173],"name":"console","nameLocation":"576:7:0","scope":383,"usedErrors":[]},{"id":382,"nodeType":"ContractDefinition","src":"2318:1449:0","nodes":[{"id":188,"nodeType":"VariableDeclaration","src":"2348:94:0","nodes":[],"constant":true,"mutability":"constant","name":"VM_ADDRESS","nameLocation":"2374:10:0","scope":382,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":175,"name":"address","nodeType":"ElementaryTypeName","src":"2348:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"value":{"arguments":[{"arguments":[{"arguments":[{"arguments":[{"hexValue":"6865766d20636865617420636f6465","id":183,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2421:17:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d","typeString":"literal_string \"hevm cheat code\""},"value":"hevm cheat code"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d","typeString":"literal_string \"hevm cheat code\""}],"id":182,"name":"keccak256","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-8,"src":"2411:9:0","typeDescriptions":{"typeIdentifier":"t_function_keccak256_pure$_t_bytes_memory_ptr_$returns$_t_bytes32_$","typeString":"function (bytes memory) pure returns (bytes32)"}},"id":184,"isConstant":false,"isLValue":false,"isPure":true,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2411:28:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes32","typeString":"bytes32"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes32","typeString":"bytes32"}],"id":181,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2403:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint256_$","typeString":"type(uint256)"},"typeName":{"id":180,"name":"uint256","nodeType":"ElementaryTypeName","src":"2403:7:0","typeDescriptions":{}}},"id":185,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2403:37:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint256","typeString":"uint256"}],"id":179,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2395:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":178,"name":"uint160","nodeType":"ElementaryTypeName","src":"2395:7:0","typeDescriptions":{}}},"id":186,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2395:46:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":177,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2387:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":176,"name":"address","nodeType":"ElementaryTypeName","src":"2387:7:0","typeDescriptions":{}}},"id":187,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2387:55:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"},{"id":194,"nodeType":"VariableDeclaration","src":"2448:40:0","nodes":[],"constant":true,"mutability":"constant","name":"vm","nameLocation":"2469:2:0","scope":382,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$36","typeString":"contract Vm"},"typeName":{"id":190,"nodeType":"UserDefinedTypeName","pathNode":{"id":189,"name":"Vm","nodeType":"IdentifierPath","referencedDeclaration":36,"src":"2448:2:0"},"referencedDeclaration":36,"src":"2448:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$36","typeString":"contract Vm"}},"value":{"arguments":[{"id":192,"name":"VM_ADDRESS","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":188,"src":"2477:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":191,"name":"Vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":36,"src":"2474:2:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_Vm_$36_$","typeString":"type(contract Vm)"}},"id":193,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2474:14:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$36","typeString":"contract Vm"}},"visibility":"internal"},{"id":357,"nodeType":"FunctionDefinition","src":"2578:949:0","nodes":[],"body":{"id":356,"nodeType":"Block","src":"2600:927:0","nodes":[],"statements":[{"assignments":[199],"declarations":[{"constant":false,"id":199,"mutability":"mutable","name":"x","nameLocation":"2615:1:0","nodeType":"VariableDeclaration","scope":356,"src":"2610:6:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":198,"name":"bool","nodeType":"ElementaryTypeName","src":"2610:4:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"id":205,"initialValue":{"arguments":[{"hexValue":"4558414d504c455f424f4f4c","id":202,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2628:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_a634dae177a0e138ae7aaa2afae347412e148992e88c7aabd33ee71be146cb7f","typeString":"literal_string \"EXAMPLE_BOOL\""},"value":"EXAMPLE_BOOL"},{"hexValue":"66616c7365","id":203,"isConstant":false,"isLValue":false,"isPure":true,"kind":"bool","lValueRequested":false,"nodeType":"Literal","src":"2644:5:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"value":"false"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_a634dae177a0e138ae7aaa2afae347412e148992e88c7aabd33ee71be146cb7f","typeString":"literal_string \"EXAMPLE_BOOL\""},{"typeIdentifier":"t_bool","typeString":"bool"}],"expression":{"id":200,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":194,"src":"2619:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$36","typeString":"contract Vm"}},"id":201,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"envOr","nodeType":"MemberAccess","referencedDeclaration":10,"src":"2619:8:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$_t_bool_$returns$_t_bool_$","typeString":"function (string memory,bool) view external returns (bool)"}},"id":204,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2619:31:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"nodeType":"VariableDeclarationStatement","src":"2610:40:0"},{"expression":{"arguments":[{"hexValue":"626f6f6c2076616c75652066726f6d20656e76","id":209,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2672:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_5a607d0b5a1295325aa8901721d78ba402601bba6f62cebdd5235dd0204a590b","typeString":"literal_string \"bool value from env\""},"value":"bool value from env"},{"id":210,"name":"x","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":199,"src":"2695:1:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_5a607d0b5a1295325aa8901721d78ba402601bba6f62cebdd5235dd0204a590b","typeString":"literal_string \"bool value from env\""},{"typeIdentifier":"t_bool","typeString":"bool"}],"expression":{"id":206,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"2660:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":208,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":118,"src":"2660:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_bool_$returns$__$","typeString":"function (string memory,bool) pure"}},"id":211,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2660:37:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":212,"nodeType":"ExpressionStatement","src":"2660:37:0"},{"expression":{"arguments":[{"hexValue":"636f6e74726163742061646472","id":216,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2720:15:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_fa50728770d00fe8f6a0592f3565bbfaf063ee4077f1f5bbc003d091d33cd0c4","typeString":"literal_string \"contract addr\""},"value":"contract addr"},{"arguments":[{"id":219,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"2745:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}],"id":218,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2737:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":217,"name":"address","nodeType":"ElementaryTypeName","src":"2737:7:0","typeDescriptions":{}}},"id":220,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2737:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_fa50728770d00fe8f6a0592f3565bbfaf063ee4077f1f5bbc003d091d33cd0c4","typeString":"literal_string \"contract addr\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":213,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"2708:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":215,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":152,"src":"2708:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":221,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2708:43:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":222,"nodeType":"ExpressionStatement","src":"2708:43:0"},{"expression":{"arguments":[{"hexValue":"636f6e7472616374206e6f6e6365","id":226,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2773:16:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_3a23091615a5de8c0a35ffd8857a37e2c4e0b72f3ef8a34d6caf65efcd562e2f","typeString":"literal_string \"contract nonce\""},"value":"contract nonce"},{"arguments":[{"arguments":[{"id":231,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"2811:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}],"id":230,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2803:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":229,"name":"address","nodeType":"ElementaryTypeName","src":"2803:7:0","typeDescriptions":{}}},"id":232,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2803:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":227,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":194,"src":"2791:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$36","typeString":"contract Vm"}},"id":228,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"getNonce","nodeType":"MemberAccess","referencedDeclaration":17,"src":"2791:11:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_address_$returns$_t_uint64_$","typeString":"function (address) view external returns (uint64)"}},"id":233,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2791:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_3a23091615a5de8c0a35ffd8857a37e2c4e0b72f3ef8a34d6caf65efcd562e2f","typeString":"literal_string \"contract nonce\""},{"typeIdentifier":"t_uint64","typeString":"uint64"}],"expression":{"id":223,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"2761:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":225,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":135,"src":"2761:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_uint256_$returns$__$","typeString":"function (string memory,uint256) pure"}},"id":234,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2761:57:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":235,"nodeType":"ExpressionStatement","src":"2761:57:0"},{"expression":{"arguments":[{"hexValue":"73656e6465722061646472","id":239,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2840:13:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_8125ca2decf812b25b65606ff16dad37cb198ff0433485a7926e50feafacfc35","typeString":"literal_string \"sender addr\""},"value":"sender addr"},{"arguments":[{"expression":{"id":242,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"2863:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":243,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"sender","nodeType":"MemberAccess","src":"2863:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":241,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2855:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":240,"name":"address","nodeType":"ElementaryTypeName","src":"2855:7:0","typeDescriptions":{}}},"id":244,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2855:19:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_8125ca2decf812b25b65606ff16dad37cb198ff0433485a7926e50feafacfc35","typeString":"literal_string \"sender addr\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":236,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"2828:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":238,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":152,"src":"2828:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":245,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2828:47:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":246,"nodeType":"ExpressionStatement","src":"2828:47:0"},{"expression":{"arguments":[{"hexValue":"73656e646572206e6f6e6365","id":250,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2897:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_db7deb43f2f9e0404016de53b7e64c4976b54149581f7534daae2551e8cf4e40","typeString":"literal_string \"sender nonce\""},"value":"sender nonce"},{"arguments":[{"arguments":[{"expression":{"id":255,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"2933:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":256,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"sender","nodeType":"MemberAccess","src":"2933:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":254,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2925:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":253,"name":"address","nodeType":"ElementaryTypeName","src":"2925:7:0","typeDescriptions":{}}},"id":257,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2925:19:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":251,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":194,"src":"2913:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$36","typeString":"contract Vm"}},"id":252,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"getNonce","nodeType":"MemberAccess","referencedDeclaration":17,"src":"2913:11:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_address_$returns$_t_uint64_$","typeString":"function (address) view external returns (uint64)"}},"id":258,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2913:32:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_db7deb43f2f9e0404016de53b7e64c4976b54149581f7534daae2551e8cf4e40","typeString":"literal_string \"sender nonce\""},{"typeIdentifier":"t_uint64","typeString":"uint64"}],"expression":{"id":247,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"2885:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":249,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":135,"src":"2885:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_uint256_$returns$__$","typeString":"function (string memory,uint256) pure"}},"id":259,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2885:61:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":260,"nodeType":"ExpressionStatement","src":"2885:61:0"},{"assignments":[262],"declarations":[{"constant":false,"id":262,"mutability":"mutable","name":"json","nameLocation":"2971:4:0","nodeType":"VariableDeclaration","scope":356,"src":"2957:18:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":261,"name":"string","nodeType":"ElementaryTypeName","src":"2957:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"id":264,"initialValue":{"hexValue":"7b22726f6f745f6b6579223a205b7b2261223a20312c202262223a20327d5d7d","id":263,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2978:34:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_e95522e99766888d0261f55bd1eae5e3f3e26eaf009a16e2433eafaf0a4ecdf2","typeString":"literal_string \"{\"root_key\": [{\"a\": 1, \"b\": 2}]}\""},"value":"{\"root_key\": [{\"a\": 1, \"b\": 2}]}"},"nodeType":"VariableDeclarationStatement","src":"2957:55:0"},{"assignments":[269],"declarations":[{"constant":false,"id":269,"mutability":"mutable","name":"keys","nameLocation":"3038:4:0","nodeType":"VariableDeclaration","scope":356,"src":"3022:20:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string[]"},"typeName":{"baseType":{"id":267,"name":"string","nodeType":"ElementaryTypeName","src":"3022:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"id":268,"nodeType":"ArrayTypeName","src":"3022:8:0","typeDescriptions":{"typeIdentifier":"t_array$_t_string_storage_$dyn_storage_ptr","typeString":"string[]"}},"visibility":"internal"}],"id":275,"initialValue":{"arguments":[{"id":272,"name":"json","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":262,"src":"3062:4:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"hexValue":"2e726f6f745f6b65795b305d","id":273,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3068:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_d82f67100edb80050915e1ec4b565c9a8319a22efb1075e1298b7bb60101d266","typeString":"literal_string \".root_key[0]\""},"value":".root_key[0]"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_stringliteral_d82f67100edb80050915e1ec4b565c9a8319a22efb1075e1298b7bb60101d266","typeString":"literal_string \".root_key[0]\""}],"expression":{"id":270,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":194,"src":"3045:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$36","typeString":"contract Vm"}},"id":271,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"parseJsonKeys","nodeType":"MemberAccess","referencedDeclaration":27,"src":"3045:16:0","typeDescriptions":{"typeIdentifier":"t_function_external_pure$_t_string_memory_ptr_$_t_string_memory_ptr_$returns$_t_array$_t_string_memory_ptr_$dyn_memory_ptr_$","typeString":"function (string memory,string memory) pure external returns (string memory[] memory)"}},"id":274,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3045:38:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string memory[] memory"}},"nodeType":"VariableDeclarationStatement","src":"3022:61:0"},{"expression":{"arguments":[{"hexValue":"6b657973","id":279,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3105:6:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_f29790a80c4ce5f42f59892f424f9c92856c6b656c3378e2cf305b260c6f4195","typeString":"literal_string \"keys\""},"value":"keys"},{"baseExpression":{"id":280,"name":"keys","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":269,"src":"3113:4:0","typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string memory[] memory"}},"id":282,"indexExpression":{"hexValue":"30","id":281,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"3118:1:0","typeDescriptions":{"typeIdentifier":"t_rational_0_by_1","typeString":"int_const 0"},"value":"0"},"isConstant":false,"isLValue":true,"isPure":false,"lValueRequested":false,"nodeType":"IndexAccess","src":"3113:7:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"baseExpression":{"id":283,"name":"keys","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":269,"src":"3122:4:0","typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string memory[] memory"}},"id":285,"indexExpression":{"hexValue":"31","id":284,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"3127:1:0","typeDescriptions":{"typeIdentifier":"t_rational_1_by_1","typeString":"int_const 1"},"value":"1"},"isConstant":false,"isLValue":true,"isPure":false,"lValueRequested":false,"nodeType":"IndexAccess","src":"3122:7:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_f29790a80c4ce5f42f59892f424f9c92856c6b656c3378e2cf305b260c6f4195","typeString":"literal_string \"keys\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}],"expression":{"id":276,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"3093:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":278,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":172,"src":"3093:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_string_memory_ptr_$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory,string memory,string memory) pure"}},"id":286,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3093:37:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":287,"nodeType":"ExpressionStatement","src":"3093:37:0"},{"expression":{"arguments":[{"hexValue":"66726f6d206f726967696e616c","id":291,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3152:15:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_77928970c8757d110f3c23e003246f49e0de890480ba9717ba659b2f56f316b2","typeString":"literal_string \"from original\""},"value":"from original"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_77928970c8757d110f3c23e003246f49e0de890480ba9717ba659b2f56f316b2","typeString":"literal_string \"from original\""}],"expression":{"id":288,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3141:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}},"id":290,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"hello","nodeType":"MemberAccess","referencedDeclaration":381,"src":"3141:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) view external"}},"id":292,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3141:27:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":293,"nodeType":"ExpressionStatement","src":"3141:27:0"},{"expression":{"arguments":[{"arguments":[{"arguments":[{"hexValue":"30783432","id":301,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"3208:4:0","typeDescriptions":{"typeIdentifier":"t_rational_66_by_1","typeString":"int_const 66"},"value":"0x42"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_66_by_1","typeString":"int_const 66"}],"id":300,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3200:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":299,"name":"uint160","nodeType":"ElementaryTypeName","src":"3200:7:0","typeDescriptions":{}}},"id":302,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3200:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":298,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3192:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":297,"name":"address","nodeType":"ElementaryTypeName","src":"3192:7:0","typeDescriptions":{}}},"id":303,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3192:22:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":294,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":194,"src":"3178:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$36","typeString":"contract Vm"}},"id":296,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"startPrank","nodeType":"MemberAccess","referencedDeclaration":32,"src":"3178:13:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_address_$returns$__$","typeString":"function (address) external"}},"id":304,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3178:37:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":305,"nodeType":"ExpressionStatement","src":"3178:37:0"},{"expression":{"arguments":[{"hexValue":"66726f6d207072616e6b2031","id":309,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3236:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_42b34abfe37a8b0add910cda7b4a379e6538fa7a1dcafce47a02bd38f6c88e2a","typeString":"literal_string \"from prank 1\""},"value":"from prank 1"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_42b34abfe37a8b0add910cda7b4a379e6538fa7a1dcafce47a02bd38f6c88e2a","typeString":"literal_string \"from prank 1\""}],"expression":{"id":306,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3225:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}},"id":308,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"hello","nodeType":"MemberAccess","referencedDeclaration":381,"src":"3225:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) view external"}},"id":310,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3225:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":311,"nodeType":"ExpressionStatement","src":"3225:26:0"},{"expression":{"arguments":[{"hexValue":"706172656e742073636f7065206d73672e73656e646572","id":315,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3273:25:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_83ec9246154d8845de47aafc5c2865c9985d2efe84472c27283879f2fbf5cc94","typeString":"literal_string \"parent scope msg.sender\""},"value":"parent scope msg.sender"},{"arguments":[{"expression":{"id":318,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"3308:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":319,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"sender","nodeType":"MemberAccess","src":"3308:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":317,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3300:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":316,"name":"address","nodeType":"ElementaryTypeName","src":"3300:7:0","typeDescriptions":{}}},"id":320,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3300:19:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_83ec9246154d8845de47aafc5c2865c9985d2efe84472c27283879f2fbf5cc94","typeString":"literal_string \"parent scope msg.sender\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":312,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"3261:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":314,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":152,"src":"3261:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":321,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3261:59:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":322,"nodeType":"ExpressionStatement","src":"3261:59:0"},{"expression":{"arguments":[{"hexValue":"706172656e742073636f706520636f6e74726163742e61646472","id":326,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3342:28:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_97df66250e0b2b48f0ec8d0e01eb1b8ca012d95f1572895622aa1ea433e5570f","typeString":"literal_string \"parent scope contract.addr\""},"value":"parent scope contract.addr"},{"arguments":[{"id":329,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3380:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}],"id":328,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3372:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":327,"name":"address","nodeType":"ElementaryTypeName","src":"3372:7:0","typeDescriptions":{}}},"id":330,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3372:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_97df66250e0b2b48f0ec8d0e01eb1b8ca012d95f1572895622aa1ea433e5570f","typeString":"literal_string \"parent scope contract.addr\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":323,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"3330:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":325,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":152,"src":"3330:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":331,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3330:56:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":332,"nodeType":"ExpressionStatement","src":"3330:56:0"},{"expression":{"arguments":[{"hexValue":"66726f6d207072616e6b2032","id":336,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3407:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_a38a34f8cad750a79aa097a92971f8f405b51ee9d53d25c5b14fc129ba3684bb","typeString":"literal_string \"from prank 2\""},"value":"from prank 2"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_a38a34f8cad750a79aa097a92971f8f405b51ee9d53d25c5b14fc129ba3684bb","typeString":"literal_string \"from prank 2\""}],"expression":{"id":333,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3396:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}},"id":335,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"hello","nodeType":"MemberAccess","referencedDeclaration":381,"src":"3396:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) view external"}},"id":337,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3396:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":338,"nodeType":"ExpressionStatement","src":"3396:26:0"},{"expression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":339,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":194,"src":"3432:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$36","typeString":"contract Vm"}},"id":341,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"stopPrank","nodeType":"MemberAccess","referencedDeclaration":35,"src":"3432:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$__$returns$__$","typeString":"function () external"}},"id":342,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3432:14:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":343,"nodeType":"ExpressionStatement","src":"3432:14:0"},{"expression":{"arguments":[{"hexValue":"66726f6d206f726967696e616c20616761696e","id":347,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3467:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_0c805c6579e20a9c4c8e11aeab23330910a9f2da629191dc119d1730e8ed6860","typeString":"literal_string \"from original again\""},"value":"from original again"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_0c805c6579e20a9c4c8e11aeab23330910a9f2da629191dc119d1730e8ed6860","typeString":"literal_string \"from original again\""}],"expression":{"id":344,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3456:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}},"id":346,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"hello","nodeType":"MemberAccess","referencedDeclaration":381,"src":"3456:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) view external"}},"id":348,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3456:33:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":349,"nodeType":"ExpressionStatement","src":"3456:33:0"},{"expression":{"arguments":[{"hexValue":"646f6e6521","id":353,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3512:7:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_080382d5c9e9e7c5e3d1d33f5e7422740375955180fadff167d8130e0c35f3fc","typeString":"literal_string \"done!\""},"value":"done!"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_080382d5c9e9e7c5e3d1d33f5e7422740375955180fadff167d8130e0c35f3fc","typeString":"literal_string \"done!\""}],"expression":{"id":350,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"3500:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":352,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":101,"src":"3500:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":354,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3500:20:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":355,"nodeType":"ExpressionStatement","src":"3500:20:0"}]},"documentation":{"id":195,"nodeType":"StructuredDocumentation","src":"2495:78:0","text":"@notice example function, runs through basic cheat-codes and console logs."},"functionSelector":"c0406226","implemented":true,"kind":"function","modifiers":[],"name":"run","nameLocation":"2587:3:0","parameters":{"id":196,"nodeType":"ParameterList","parameters":[],"src":"2590:2:0"},"returnParameters":{"id":197,"nodeType":"ParameterList","parameters":[],"src":"2600:0:0"},"scope":382,"stateMutability":"nonpayable","virtual":false,"visibility":"public"},{"id":381,"nodeType":"FunctionDefinition","src":"3622:143:0","nodes":[],"body":{"id":380,"nodeType":"Block","src":"3671:94:0","nodes":[],"statements":[{"expression":{"arguments":[{"id":366,"name":"_v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":360,"src":"3693:2:0","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}],"expression":{"id":363,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"3681:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":365,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":101,"src":"3681:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":367,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3681:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":368,"nodeType":"ExpressionStatement","src":"3681:15:0"},{"expression":{"arguments":[{"hexValue":"68656c6c6f206d73672e73656e646572","id":372,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3718:18:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_b3cc13bc51228b2c4c4334d82a4772908254dc0e1c512893dd16208ef13efb8e","typeString":"literal_string \"hello msg.sender\""},"value":"hello msg.sender"},{"arguments":[{"expression":{"id":375,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"3746:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":376,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"sender","nodeType":"MemberAccess","src":"3746:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":374,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3738:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":373,"name":"address","nodeType":"ElementaryTypeName","src":"3738:7:0","typeDescriptions":{}}},"id":377,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3738:19:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_b3cc13bc51228b2c4c4334d82a4772908254dc0e1c512893dd16208ef13efb8e","typeString":"literal_string \"hello msg.sender\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":369,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"3706:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":371,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":152,"src":"3706:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":378,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3706:52:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":379,"nodeType":"ExpressionStatement","src":"3706:52:0"}]},"documentation":{"id":358,"nodeType":"StructuredDocumentation","src":"3533:84:0","text":"@notice example external function, to force a CALL, and test vm.startPrank with."},"functionSelector":"a777d0dc","implemented":true,"kind":"function","modifiers":[],"name":"hello","nameLocation":"3631:5:0","parameters":{"id":361,"nodeType":"ParameterList","parameters":[{"constant":false,"id":360,"mutability":"mutable","name":"_v","nameLocation":"3653:2:0","nodeType":"VariableDeclaration","scope":381,"src":"3637:18:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":359,"name":"string","nodeType":"ElementaryTypeName","src":"3637:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"3636:20:0"},"returnParameters":{"id":362,"nodeType":"ParameterList","parameters":[],"src":"3671:0:0"},"scope":382,"stateMutability":"view","virtual":false,"visibility":"external"}],"abstract":false,"baseContracts":[],"canonicalName":"ScriptExample","contractDependencies":[],"contractKind":"contract","documentation":{"id":174,"nodeType":"StructuredDocumentation","src":"2192:126:0","text":"@title ScriptExample\n @notice ScriptExample is an example script. The Go forge script code tests that it can run this."},"fullyImplemented":true,"linearizedBaseContracts":[382],"name":"ScriptExample","nameLocation":"2327:13:0","scope":383,"usedErrors":[]}],"license":"MIT"},"id":0} +\ No newline at end of file ++{"abi":[{"type":"function","name":"call1","inputs":[{"name":"_v","type":"string","internalType":"string"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"call2","inputs":[{"name":"_v","type":"string","internalType":"string"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"callPure","inputs":[{"name":"_v","type":"string","internalType":"string"}],"outputs":[],"stateMutability":"pure"},{"type":"function","name":"counter","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"hello","inputs":[{"name":"_v","type":"string","internalType":"string"}],"outputs":[],"stateMutability":"view"},{"type":"function","name":"nested1","inputs":[{"name":"_v","type":"string","internalType":"string"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"nested2","inputs":[{"name":"_v","type":"string","internalType":"string"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"run","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"runBroadcast","inputs":[],"outputs":[],"stateMutability":"nonpayable"}],"bytecode":{"object":"0x608060405234801561001057600080fd5b5061202a806100206000396000f3fe608060405234801561001057600080fd5b50600436106100a35760003560e01c8063a76ccdfa11610076578063bef03abc1161005b578063bef03abc14610111578063c040622614610119578063dbf1282f146100c357600080fd5b8063a76ccdfa146100eb578063a777d0dc146100fe57600080fd5b806361bc221a146100a85780637e79255d146100c35780637f8b915c146100d85780638d3ef7ca146100c3575b600080fd5b6100b160005481565b60405190815260200160405180910390f35b6100d66100d1366004611a60565b610121565b005b6100d66100e6366004611a60565b610178565b6100d66100f9366004611a60565b6101b7565b6100d661010c366004611a60565b61023f565b6100d66102bd565b6100d6610f54565b60008054908061013083611ad2565b919050555061017482828080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061175b92505050565b5050565b61017482828080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061175b92505050565b6000805490806101c683611ad2565b90915550506040517fdbf1282f000000000000000000000000000000000000000000000000000000008152309063dbf1282f906102099085908590600401611b31565b600060405180830381600087803b15801561022357600080fd5b505af1158015610237573d6000803e3d6000fd5b505050505050565b61027e82828080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061175b92505050565b6101746040518060400160405280601081526020017f68656c6c6f206d73672e73656e64657200000000000000000000000000000000815250336117ed565b604080518082018252600b81527f6e6f6e6365207374617274000000000000000000000000000000000000000000602082015290517f2d0335ab0000000000000000000000000000000000000000000000000000000081523060048201526103909190737109709ecfa91a80626ff3989d68f67f5b1dd12d90632d0335ab906024015b602060405180830381865afa15801561035d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103819190611b7e565b67ffffffffffffffff1661187e565b6103ce6040518060400160405280600e81526020017f74657374696e672073696e676c6500000000000000000000000000000000000081525061175b565b7f885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d60001c73ffffffffffffffffffffffffffffffffffffffff1663afc980406040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561043957600080fd5b505af115801561044d573d6000803e3d6000fd5b50506040517f7e79255d00000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f73696e676c655f63616c6c3100000000000000000000000000000000000000006044820152309250637e79255d9150606401600060405180830381600087803b1580156104d057600080fd5b505af11580156104e4573d6000803e3d6000fd5b50506040517f8d3ef7ca00000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f73696e676c655f63616c6c3200000000000000000000000000000000000000006044820152309250638d3ef7ca9150606401600060405180830381600087803b15801561056757600080fd5b505af115801561057b573d6000803e3d6000fd5b505050506105bd6040518060400160405280601281526020017f74657374696e672073746172742f73746f70000000000000000000000000000081525061175b565b6040517f7fec2a8d00000000000000000000000000000000000000000000000000000000815262c0ffee6004820152737109709ecfa91a80626ff3989d68f67f5b1dd12d90637fec2a8d90602401600060405180830381600087803b15801561062557600080fd5b505af1158015610639573d6000803e3d6000fd5b50506040517f7e79255d00000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f737461727473746f705f63616c6c3100000000000000000000000000000000006044820152309250637e79255d9150606401600060405180830381600087803b1580156106bc57600080fd5b505af11580156106d0573d6000803e3d6000fd5b50506040517f8d3ef7ca00000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f737461727473746f705f63616c6c3200000000000000000000000000000000006044820152309250638d3ef7ca9150606401600060405180830381600087803b15801561075357600080fd5b505af1158015610767573d6000803e3d6000fd5b50506040517f7f8b915c00000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f737461727473746f705f707572650000000000000000000000000000000000006044820152309250637f8b915c915060640160006040518083038186803b1580156107e857600080fd5b505afa1580156107fc573d6000803e3d6000fd5b505050507f885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d60001c73ffffffffffffffffffffffffffffffffffffffff166376eadd366040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561086b57600080fd5b505af115801561087f573d6000803e3d6000fd5b50506040517f7e79255d00000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f737461727473746f705f63616c6c3300000000000000000000000000000000006044820152309250637e79255d9150606401600060405180830381600087803b15801561090257600080fd5b505af1158015610916573d6000803e3d6000fd5b505050506109586040518060400160405280600e81526020017f74657374696e67206e657374656400000000000000000000000000000000000081525061175b565b6040517f7fec2a8d0000000000000000000000000000000000000000000000000000000081526112346004820152737109709ecfa91a80626ff3989d68f67f5b1dd12d90637fec2a8d90602401600060405180830381600087803b1580156109bf57600080fd5b505af11580156109d3573d6000803e3d6000fd5b50506040517fa76ccdfa00000000000000000000000000000000000000000000000000000000815260206004820152600660248201527f6e65737465640000000000000000000000000000000000000000000000000000604482015230925063a76ccdfa9150606401600060405180830381600087803b158015610a5657600080fd5b505af1158015610a6a573d6000803e3d6000fd5b505050507f885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d60001c73ffffffffffffffffffffffffffffffffffffffff166376eadd366040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610ad957600080fd5b505af1158015610aed573d6000803e3d6000fd5b50505050610b2f6040518060400160405280601381526020017f636f6e7472616374206465706c6f796d656e740000000000000000000000000081525061175b565b6040517fe6962cdb000000000000000000000000000000000000000000000000000000008152621234566004820152737109709ecfa91a80626ff3989d68f67f5b1dd12d9063e6962cdb90602401600060405180830381600087803b158015610b9757600080fd5b505af1158015610bab573d6000803e3d6000fd5b5050505060006104d2604051610bc090611a54565b908152602001604051809103906000f080158015610be2573d6000803e3d6000fd5b5090508073ffffffffffffffffffffffffffffffffffffffff1663c29855786040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c30573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c549190611baf565b6104d214610c6157600080fd5b610c9f6040518060400160405280600881526020017f637265617465203200000000000000000000000000000000000000000000000081525061175b565b6040517fe6962cdb00000000000000000000000000000000000000000000000000000000815261cafe6004820152737109709ecfa91a80626ff3989d68f67f5b1dd12d9063e6962cdb90602401600060405180830381600087803b158015610d0657600080fd5b505af1158015610d1a573d6000803e3d6000fd5b505050506000602a60001b6104d2604051610d3490611a54565b9081526020018190604051809103906000f5905080158015610d5a573d6000803e3d6000fd5b5090508073ffffffffffffffffffffffffffffffffffffffff1663c29855786040518163ffffffff1660e01b8152600401602060405180830381865afa158015610da8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dcc9190611baf565b6104d214610dd957600080fd5b610e176040518060400160405280600581526020017f646f6e652100000000000000000000000000000000000000000000000000000081525061175b565b7f885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d60001c73ffffffffffffffffffffffffffffffffffffffff1663afc980406040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610e8257600080fd5b505af1158015610e96573d6000803e3d6000fd5b505050506104d2604051610ea990611a54565b908152602001604051809103906000f080158015610ecb573d6000803e3d6000fd5b5050604080518082018252600981527f6e6f6e636520656e640000000000000000000000000000000000000000000000602082015290517f2d0335ab0000000000000000000000000000000000000000000000000000000081523060048201526101749190737109709ecfa91a80626ff3989d68f67f5b1dd12d90632d0335ab90602401610340565b604080517f4777f3cf0000000000000000000000000000000000000000000000000000000081526004810191909152600c60448201527f4558414d504c455f424f4f4c0000000000000000000000000000000000000000606482015260006024820181905290737109709ecfa91a80626ff3989d68f67f5b1dd12d90634777f3cf90608401602060405180830381865afa158015610ff6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061101a9190611bc8565b905061105b6040518060400160405280601381526020017f626f6f6c2076616c75652066726f6d20656e76000000000000000000000000008152508261190f565b61109a6040518060400160405280600d81526020017f636f6e7472616374206164647200000000000000000000000000000000000000815250306117ed565b604080518082018252600e81527f636f6e7472616374206e6f6e6365000000000000000000000000000000000000602082015290517f2d0335ab0000000000000000000000000000000000000000000000000000000081523060048201526111219190737109709ecfa91a80626ff3989d68f67f5b1dd12d90632d0335ab90602401610340565b6111606040518060400160405280600b81526020017f73656e6465722061646472000000000000000000000000000000000000000000815250336117ed565b604080518082018252600c81527f73656e646572206e6f6e63650000000000000000000000000000000000000000602082015290517f2d0335ab0000000000000000000000000000000000000000000000000000000081523360048201526111e79190737109709ecfa91a80626ff3989d68f67f5b1dd12d90632d0335ab90602401610340565b60408051808201825260208082527f7b22726f6f745f6b6579223a205b7b2261223a20312c202262223a20327d5d7d9082015290517f213e4198000000000000000000000000000000000000000000000000000000008152600090737109709ecfa91a80626ff3989d68f67f5b1dd12d9063213e41989061126c908590600401611c64565b600060405180830381865afa158015611289573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526112cf9190810190611d34565b90506113456040518060400160405280600481526020017f6b657973000000000000000000000000000000000000000000000000000000008152508260008151811061131d5761131d611e68565b60200260200101518360018151811061133857611338611e68565b60200260200101516119a0565b6040517fa777d0dc00000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f66726f6d206f726967696e616c000000000000000000000000000000000000006044820152309063a777d0dc9060640160006040518083038186803b1580156113c257600080fd5b505afa1580156113d6573d6000803e3d6000fd5b50506040517f06447d5600000000000000000000000000000000000000000000000000000000815260426004820152737109709ecfa91a80626ff3989d68f67f5b1dd12d92506306447d569150602401600060405180830381600087803b15801561144057600080fd5b505af1158015611454573d6000803e3d6000fd5b50506040517fa777d0dc00000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f66726f6d207072616e6b20310000000000000000000000000000000000000000604482015230925063a777d0dc915060640160006040518083038186803b1580156114d557600080fd5b505afa1580156114e9573d6000803e3d6000fd5b5050505061152c6040518060400160405280601781526020017f706172656e742073636f7065206d73672e73656e646572000000000000000000815250336117ed565b61156b6040518060400160405280601a81526020017f706172656e742073636f706520636f6e74726163742e61646472000000000000815250306117ed565b6040517fa777d0dc00000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f66726f6d207072616e6b203200000000000000000000000000000000000000006044820152309063a777d0dc9060640160006040518083038186803b1580156115e857600080fd5b505afa1580156115fc573d6000803e3d6000fd5b505050507f885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d60001c73ffffffffffffffffffffffffffffffffffffffff166390c5013b6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561166b57600080fd5b505af115801561167f573d6000803e3d6000fd5b50506040517fa777d0dc00000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f66726f6d206f726967696e616c20616761696e00000000000000000000000000604482015230925063a777d0dc915060640160006040518083038186803b15801561170057600080fd5b505afa158015611714573d6000803e3d6000fd5b505050506117566040518060400160405280600581526020017f646f6e652100000000000000000000000000000000000000000000000000000081525061175b565b505050565b6117ea8160405160240161176f9190611e97565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f41304fac00000000000000000000000000000000000000000000000000000000179052611a2f565b50565b6101748282604051602401611803929190611eaa565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f319af33300000000000000000000000000000000000000000000000000000000179052611a2f565b6101748282604051602401611894929190611ee2565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fb60e72cc00000000000000000000000000000000000000000000000000000000179052611a2f565b6101748282604051602401611925929190611f04565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fc3b5563500000000000000000000000000000000000000000000000000000000179052611a2f565b6117568383836040516024016119b893929190611f28565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f2ced7cef000000000000000000000000000000000000000000000000000000001790525b6117ea8180516a636f6e736f6c652e6c6f67602083016000808483855afa5050505050565b60b280611f6c83390190565b60008060208385031215611a7357600080fd5b823567ffffffffffffffff80821115611a8b57600080fd5b818501915085601f830112611a9f57600080fd5b813581811115611aae57600080fd5b866020828501011115611ac057600080fd5b60209290920196919550909350505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611b2a577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5060010190565b60208152816020820152818360408301376000818301604090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101919050565b600060208284031215611b9057600080fd5b815167ffffffffffffffff81168114611ba857600080fd5b9392505050565b600060208284031215611bc157600080fd5b5051919050565b600060208284031215611bda57600080fd5b81518015158114611ba857600080fd5b60005b83811015611c05578181015183820152602001611bed565b83811115611c14576000848401525b50505050565b60008151808452611c32816020860160208601611bea565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b604081526000611c776040830184611c1a565b8281036020840152600c81527f2e726f6f745f6b65795b305d000000000000000000000000000000000000000060208201526040810191505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611d2c57611d2c611cb6565b604052919050565b60006020808385031215611d4757600080fd5b825167ffffffffffffffff80821115611d5f57600080fd5b8185019150601f8681840112611d7457600080fd5b825182811115611d8657611d86611cb6565b8060051b611d95868201611ce5565b918252848101860191868101908a841115611daf57600080fd5b87870192505b83831015611e5a57825186811115611dcd5760008081fd5b8701603f81018c13611ddf5760008081fd5b88810151604088821115611df557611df5611cb6565b611e248b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08a85011601611ce5565b8281528e82848601011115611e395760008081fd5b611e48838d8301848701611bea565b85525050509187019190870190611db5565b9a9950505050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602081526000611ba86020830184611c1a565b604081526000611ebd6040830185611c1a565b905073ffffffffffffffffffffffffffffffffffffffff831660208301529392505050565b604081526000611ef56040830185611c1a565b90508260208301529392505050565b604081526000611f176040830185611c1a565b905082151560208301529392505050565b606081526000611f3b6060830186611c1a565b8281036020840152611f4d8186611c1a565b90508281036040840152611f618185611c1a565b969550505050505056fe608060405234801561001057600080fd5b506040516100b23803806100b283398101604081905261002f91610037565b600055610050565b60006020828403121561004957600080fd5b5051919050565b60548061005e6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063c298557814602d575b600080fd5b603560005481565b60405190815260200160405180910390f3fea164736f6c634300080f000aa164736f6c634300080f000a","sourceMap":"2541:3359:0:-:0;;;;;;;;;;;;;;;;;;;","linkReferences":{}},"deployedBytecode":{"object":"0x608060405234801561001057600080fd5b50600436106100a35760003560e01c8063a76ccdfa11610076578063bef03abc1161005b578063bef03abc14610111578063c040622614610119578063dbf1282f146100c357600080fd5b8063a76ccdfa146100eb578063a777d0dc146100fe57600080fd5b806361bc221a146100a85780637e79255d146100c35780637f8b915c146100d85780638d3ef7ca146100c3575b600080fd5b6100b160005481565b60405190815260200160405180910390f35b6100d66100d1366004611a60565b610121565b005b6100d66100e6366004611a60565b610178565b6100d66100f9366004611a60565b6101b7565b6100d661010c366004611a60565b61023f565b6100d66102bd565b6100d6610f54565b60008054908061013083611ad2565b919050555061017482828080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061175b92505050565b5050565b61017482828080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061175b92505050565b6000805490806101c683611ad2565b90915550506040517fdbf1282f000000000000000000000000000000000000000000000000000000008152309063dbf1282f906102099085908590600401611b31565b600060405180830381600087803b15801561022357600080fd5b505af1158015610237573d6000803e3d6000fd5b505050505050565b61027e82828080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061175b92505050565b6101746040518060400160405280601081526020017f68656c6c6f206d73672e73656e64657200000000000000000000000000000000815250336117ed565b604080518082018252600b81527f6e6f6e6365207374617274000000000000000000000000000000000000000000602082015290517f2d0335ab0000000000000000000000000000000000000000000000000000000081523060048201526103909190737109709ecfa91a80626ff3989d68f67f5b1dd12d90632d0335ab906024015b602060405180830381865afa15801561035d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103819190611b7e565b67ffffffffffffffff1661187e565b6103ce6040518060400160405280600e81526020017f74657374696e672073696e676c6500000000000000000000000000000000000081525061175b565b7f885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d60001c73ffffffffffffffffffffffffffffffffffffffff1663afc980406040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561043957600080fd5b505af115801561044d573d6000803e3d6000fd5b50506040517f7e79255d00000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f73696e676c655f63616c6c3100000000000000000000000000000000000000006044820152309250637e79255d9150606401600060405180830381600087803b1580156104d057600080fd5b505af11580156104e4573d6000803e3d6000fd5b50506040517f8d3ef7ca00000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f73696e676c655f63616c6c3200000000000000000000000000000000000000006044820152309250638d3ef7ca9150606401600060405180830381600087803b15801561056757600080fd5b505af115801561057b573d6000803e3d6000fd5b505050506105bd6040518060400160405280601281526020017f74657374696e672073746172742f73746f70000000000000000000000000000081525061175b565b6040517f7fec2a8d00000000000000000000000000000000000000000000000000000000815262c0ffee6004820152737109709ecfa91a80626ff3989d68f67f5b1dd12d90637fec2a8d90602401600060405180830381600087803b15801561062557600080fd5b505af1158015610639573d6000803e3d6000fd5b50506040517f7e79255d00000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f737461727473746f705f63616c6c3100000000000000000000000000000000006044820152309250637e79255d9150606401600060405180830381600087803b1580156106bc57600080fd5b505af11580156106d0573d6000803e3d6000fd5b50506040517f8d3ef7ca00000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f737461727473746f705f63616c6c3200000000000000000000000000000000006044820152309250638d3ef7ca9150606401600060405180830381600087803b15801561075357600080fd5b505af1158015610767573d6000803e3d6000fd5b50506040517f7f8b915c00000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f737461727473746f705f707572650000000000000000000000000000000000006044820152309250637f8b915c915060640160006040518083038186803b1580156107e857600080fd5b505afa1580156107fc573d6000803e3d6000fd5b505050507f885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d60001c73ffffffffffffffffffffffffffffffffffffffff166376eadd366040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561086b57600080fd5b505af115801561087f573d6000803e3d6000fd5b50506040517f7e79255d00000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f737461727473746f705f63616c6c3300000000000000000000000000000000006044820152309250637e79255d9150606401600060405180830381600087803b15801561090257600080fd5b505af1158015610916573d6000803e3d6000fd5b505050506109586040518060400160405280600e81526020017f74657374696e67206e657374656400000000000000000000000000000000000081525061175b565b6040517f7fec2a8d0000000000000000000000000000000000000000000000000000000081526112346004820152737109709ecfa91a80626ff3989d68f67f5b1dd12d90637fec2a8d90602401600060405180830381600087803b1580156109bf57600080fd5b505af11580156109d3573d6000803e3d6000fd5b50506040517fa76ccdfa00000000000000000000000000000000000000000000000000000000815260206004820152600660248201527f6e65737465640000000000000000000000000000000000000000000000000000604482015230925063a76ccdfa9150606401600060405180830381600087803b158015610a5657600080fd5b505af1158015610a6a573d6000803e3d6000fd5b505050507f885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d60001c73ffffffffffffffffffffffffffffffffffffffff166376eadd366040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610ad957600080fd5b505af1158015610aed573d6000803e3d6000fd5b50505050610b2f6040518060400160405280601381526020017f636f6e7472616374206465706c6f796d656e740000000000000000000000000081525061175b565b6040517fe6962cdb000000000000000000000000000000000000000000000000000000008152621234566004820152737109709ecfa91a80626ff3989d68f67f5b1dd12d9063e6962cdb90602401600060405180830381600087803b158015610b9757600080fd5b505af1158015610bab573d6000803e3d6000fd5b5050505060006104d2604051610bc090611a54565b908152602001604051809103906000f080158015610be2573d6000803e3d6000fd5b5090508073ffffffffffffffffffffffffffffffffffffffff1663c29855786040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c30573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c549190611baf565b6104d214610c6157600080fd5b610c9f6040518060400160405280600881526020017f637265617465203200000000000000000000000000000000000000000000000081525061175b565b6040517fe6962cdb00000000000000000000000000000000000000000000000000000000815261cafe6004820152737109709ecfa91a80626ff3989d68f67f5b1dd12d9063e6962cdb90602401600060405180830381600087803b158015610d0657600080fd5b505af1158015610d1a573d6000803e3d6000fd5b505050506000602a60001b6104d2604051610d3490611a54565b9081526020018190604051809103906000f5905080158015610d5a573d6000803e3d6000fd5b5090508073ffffffffffffffffffffffffffffffffffffffff1663c29855786040518163ffffffff1660e01b8152600401602060405180830381865afa158015610da8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dcc9190611baf565b6104d214610dd957600080fd5b610e176040518060400160405280600581526020017f646f6e652100000000000000000000000000000000000000000000000000000081525061175b565b7f885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d60001c73ffffffffffffffffffffffffffffffffffffffff1663afc980406040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610e8257600080fd5b505af1158015610e96573d6000803e3d6000fd5b505050506104d2604051610ea990611a54565b908152602001604051809103906000f080158015610ecb573d6000803e3d6000fd5b5050604080518082018252600981527f6e6f6e636520656e640000000000000000000000000000000000000000000000602082015290517f2d0335ab0000000000000000000000000000000000000000000000000000000081523060048201526101749190737109709ecfa91a80626ff3989d68f67f5b1dd12d90632d0335ab90602401610340565b604080517f4777f3cf0000000000000000000000000000000000000000000000000000000081526004810191909152600c60448201527f4558414d504c455f424f4f4c0000000000000000000000000000000000000000606482015260006024820181905290737109709ecfa91a80626ff3989d68f67f5b1dd12d90634777f3cf90608401602060405180830381865afa158015610ff6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061101a9190611bc8565b905061105b6040518060400160405280601381526020017f626f6f6c2076616c75652066726f6d20656e76000000000000000000000000008152508261190f565b61109a6040518060400160405280600d81526020017f636f6e7472616374206164647200000000000000000000000000000000000000815250306117ed565b604080518082018252600e81527f636f6e7472616374206e6f6e6365000000000000000000000000000000000000602082015290517f2d0335ab0000000000000000000000000000000000000000000000000000000081523060048201526111219190737109709ecfa91a80626ff3989d68f67f5b1dd12d90632d0335ab90602401610340565b6111606040518060400160405280600b81526020017f73656e6465722061646472000000000000000000000000000000000000000000815250336117ed565b604080518082018252600c81527f73656e646572206e6f6e63650000000000000000000000000000000000000000602082015290517f2d0335ab0000000000000000000000000000000000000000000000000000000081523360048201526111e79190737109709ecfa91a80626ff3989d68f67f5b1dd12d90632d0335ab90602401610340565b60408051808201825260208082527f7b22726f6f745f6b6579223a205b7b2261223a20312c202262223a20327d5d7d9082015290517f213e4198000000000000000000000000000000000000000000000000000000008152600090737109709ecfa91a80626ff3989d68f67f5b1dd12d9063213e41989061126c908590600401611c64565b600060405180830381865afa158015611289573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526112cf9190810190611d34565b90506113456040518060400160405280600481526020017f6b657973000000000000000000000000000000000000000000000000000000008152508260008151811061131d5761131d611e68565b60200260200101518360018151811061133857611338611e68565b60200260200101516119a0565b6040517fa777d0dc00000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f66726f6d206f726967696e616c000000000000000000000000000000000000006044820152309063a777d0dc9060640160006040518083038186803b1580156113c257600080fd5b505afa1580156113d6573d6000803e3d6000fd5b50506040517f06447d5600000000000000000000000000000000000000000000000000000000815260426004820152737109709ecfa91a80626ff3989d68f67f5b1dd12d92506306447d569150602401600060405180830381600087803b15801561144057600080fd5b505af1158015611454573d6000803e3d6000fd5b50506040517fa777d0dc00000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f66726f6d207072616e6b20310000000000000000000000000000000000000000604482015230925063a777d0dc915060640160006040518083038186803b1580156114d557600080fd5b505afa1580156114e9573d6000803e3d6000fd5b5050505061152c6040518060400160405280601781526020017f706172656e742073636f7065206d73672e73656e646572000000000000000000815250336117ed565b61156b6040518060400160405280601a81526020017f706172656e742073636f706520636f6e74726163742e61646472000000000000815250306117ed565b6040517fa777d0dc00000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f66726f6d207072616e6b203200000000000000000000000000000000000000006044820152309063a777d0dc9060640160006040518083038186803b1580156115e857600080fd5b505afa1580156115fc573d6000803e3d6000fd5b505050507f885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d60001c73ffffffffffffffffffffffffffffffffffffffff166390c5013b6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561166b57600080fd5b505af115801561167f573d6000803e3d6000fd5b50506040517fa777d0dc00000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f66726f6d206f726967696e616c20616761696e00000000000000000000000000604482015230925063a777d0dc915060640160006040518083038186803b15801561170057600080fd5b505afa158015611714573d6000803e3d6000fd5b505050506117566040518060400160405280600581526020017f646f6e652100000000000000000000000000000000000000000000000000000081525061175b565b505050565b6117ea8160405160240161176f9190611e97565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f41304fac00000000000000000000000000000000000000000000000000000000179052611a2f565b50565b6101748282604051602401611803929190611eaa565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f319af33300000000000000000000000000000000000000000000000000000000179052611a2f565b6101748282604051602401611894929190611ee2565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fb60e72cc00000000000000000000000000000000000000000000000000000000179052611a2f565b6101748282604051602401611925929190611f04565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fc3b5563500000000000000000000000000000000000000000000000000000000179052611a2f565b6117568383836040516024016119b893929190611f28565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f2ced7cef000000000000000000000000000000000000000000000000000000001790525b6117ea8180516a636f6e736f6c652e6c6f67602083016000808483855afa5050505050565b60b280611f6c83390190565b60008060208385031215611a7357600080fd5b823567ffffffffffffffff80821115611a8b57600080fd5b818501915085601f830112611a9f57600080fd5b813581811115611aae57600080fd5b866020828501011115611ac057600080fd5b60209290920196919550909350505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611b2a577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5060010190565b60208152816020820152818360408301376000818301604090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101919050565b600060208284031215611b9057600080fd5b815167ffffffffffffffff81168114611ba857600080fd5b9392505050565b600060208284031215611bc157600080fd5b5051919050565b600060208284031215611bda57600080fd5b81518015158114611ba857600080fd5b60005b83811015611c05578181015183820152602001611bed565b83811115611c14576000848401525b50505050565b60008151808452611c32816020860160208601611bea565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b604081526000611c776040830184611c1a565b8281036020840152600c81527f2e726f6f745f6b65795b305d000000000000000000000000000000000000000060208201526040810191505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611d2c57611d2c611cb6565b604052919050565b60006020808385031215611d4757600080fd5b825167ffffffffffffffff80821115611d5f57600080fd5b8185019150601f8681840112611d7457600080fd5b825182811115611d8657611d86611cb6565b8060051b611d95868201611ce5565b918252848101860191868101908a841115611daf57600080fd5b87870192505b83831015611e5a57825186811115611dcd5760008081fd5b8701603f81018c13611ddf5760008081fd5b88810151604088821115611df557611df5611cb6565b611e248b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08a85011601611ce5565b8281528e82848601011115611e395760008081fd5b611e48838d8301848701611bea565b85525050509187019190870190611db5565b9a9950505050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602081526000611ba86020830184611c1a565b604081526000611ebd6040830185611c1a565b905073ffffffffffffffffffffffffffffffffffffffff831660208301529392505050565b604081526000611ef56040830185611c1a565b90508260208301529392505050565b604081526000611f176040830185611c1a565b905082151560208301529392505050565b606081526000611f3b6060830186611c1a565b8281036020840152611f4d8186611c1a565b90508281036040840152611f618185611c1a565b969550505050505056fe608060405234801561001057600080fd5b506040516100b23803806100b283398101604081905261002f91610037565b600055610050565b60006020828403121561004957600080fd5b5051919050565b60548061005e6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063c298557814602d575b600080fd5b603560005481565b60405190815260200160405180910390f3fea164736f6c634300080f000aa164736f6c634300080f000a","sourceMap":"2541:3359:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2775:22;;;;;;;;;160:25:1;;;148:2;133:18;2775:22:0;;;;;;;5405:95;;;;;;:::i;:::-;;:::i;:::-;;5814:84;;;;;;:::i;:::-;;:::i;5607:98::-;;;;;;:::i;:::-;;:::i;5256:143::-;;;;;;:::i;:::-;;:::i;3903:1258::-;;;:::i;2887:949::-;;;:::i;5405:95::-;5459:7;:9;;;:7;:9;;;:::i;:::-;;;;;;5478:15;5490:2;;5478:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;5478:11:0;;-1:-1:-1;;;5478:15:0:i;:::-;5405:95;;:::o;5814:84::-;5876:15;5888:2;;5876:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;5876:11:0;;-1:-1:-1;;;5876:15:0:i;5607:98::-;5663:7;:9;;;:7;:9;;;:::i;:::-;;;;-1:-1:-1;;5682:16:0;;;;;:4;;:12;;:16;;5695:2;;;;5682:16;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5607:98;;:::o;5256:143::-;5315:15;5327:2;;5315:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;5315:11:0;;-1:-1:-1;;;5315:15:0:i;:::-;5340:52;;;;;;;;;;;;;;;;;;5380:10;5340:11;:52::i;3903:1258::-;3944:63;;;;;;;;;;;;;;;;3979:26;;;;;3999:4;3979:26;;;1747:74:1;3944:63:0;;;3979:11;;;;1720:18:1;;3979:26:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;3971:35;;3944:11;:63::i;:::-;4018:29;;;;;;;;;;;;;;;;;;:11;:29::i;:::-;2634:28;2626:37;;4057:12;;;:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;4081:26:0;;;;;2327:2:1;4081:26:0;;;2309:21:1;2366:2;2346:18;;;2339:30;2405:14;2385:18;;;2378:42;4081:4:0;;-1:-1:-1;4081:10:0;;-1:-1:-1;2437:18:1;;4081:26:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;4117:26:0;;;;;2668:2:1;4117:26:0;;;2650:21:1;2707:2;2687:18;;;2680:30;2746:14;2726:18;;;2719:42;4117:4:0;;-1:-1:-1;4117:10:0;;-1:-1:-1;2778:18:1;;4117:26:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4154:33;;;;;;;;;;;;;;;;;;:11;:33::i;:::-;4197:45;;;;;4231:8;4197:45;;;1747:74:1;4197:17:0;;;;1720:18:1;;4197:45:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;4252:29:0;;;;;3009:2:1;4252:29:0;;;2991:21:1;3048:2;3028:18;;;3021:30;3087:17;3067:18;;;3060:45;4252:4:0;;-1:-1:-1;4252:10:0;;-1:-1:-1;3122:18:1;;4252:29:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;4291:29:0;;;;;3353:2:1;4291:29:0;;;3335:21:1;3392:2;3372:18;;;3365:30;3431:17;3411:18;;;3404:45;4291:4:0;;-1:-1:-1;4291:10:0;;-1:-1:-1;3466:18:1;;4291:29:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;4330:31:0;;;;;3697:2:1;4330:31:0;;;3679:21:1;3736:2;3716:18;;;3709:30;3775:16;3755:18;;;3748:44;4330:4:0;;-1:-1:-1;4330:13:0;;-1:-1:-1;3809:18:1;;4330:31:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2634:28;2626:37;;4371:16;;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;4399:29:0;;;;;4040:2:1;4399:29:0;;;4022:21:1;4079:2;4059:18;;;4052:30;4118:17;4098:18;;;4091:45;4399:4:0;;-1:-1:-1;4399:10:0;;-1:-1:-1;4153:18:1;;4399:29:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4439;;;;;;;;;;;;;;;;;;:11;:29::i;:::-;4478:43;;;;;4512:6;4478:43;;;1747:74:1;4478:17:0;;;;1720:18:1;;4478:43:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;4531:22:0;;;;;4384:2:1;4531:22:0;;;4366:21:1;4423:1;4403:18;;;4396:29;4461:8;4441:18;;;4434:36;4531:4:0;;-1:-1:-1;4531:12:0;;-1:-1:-1;4487:18:1;;4531:22:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2634:28;2626:37;;4563:16;;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4592:34;;;;;;;;;;;;;;;;;;:11;:34::i;:::-;4636:40;;;;;4665:8;4636:40;;;1747:74:1;4636:12:0;;;;1720:18:1;;4636:40:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4686:8;4708:4;4697:16;;;;;:::i;:::-;160:25:1;;;148:2;133:18;4697:16:0;;;;;;;;;;;;;;;;;;;;;;;4686:27;;4731:1;:5;;;:7;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;4742:4;4731:15;4723:24;;;;;;4758:23;;;;;;;;;;;;;;;;;;:11;:23::i;:::-;4791:38;;;;;4820:6;4791:38;;;1747:74:1;4791:12:0;;;;1720:18:1;;4791:38:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4839:8;4883:2;4867:20;;4889:4;4850:44;;;;;:::i;:::-;160:25:1;;;148:2;133:18;4850:44:0;;;;;;;;;;;;;;;;;;;;;;;;;;;4839:55;;4912:1;:5;;;:7;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;4923:4;4912:15;4904:24;;;;;;4938:20;;;;;;;;;;;;;;;;;;:11;:20::i;:::-;2634:28;2626:37;;5042:12;;;:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5077:4;5066:16;;;;;:::i;:::-;160:25:1;;;148:2;133:18;5066:16:0;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;5093:61:0;;;;;;;;;;;;;;;;5126:26;;;;;5146:4;5126:26;;;1747:74:1;5093:61:0;;;5126:11;;;;1720:18:1;;5126:26:0;1601:226:1;2887:949:0;2928:31;;;;;;;;;5104:21:1;;;;5161:2;5141:18;;;5134:30;5200:14;5180:18;;;5173:42;2919:6:0;5267:20:1;;;5260:52;;;2919:6:0;2928:8;;;;5232:19:1;;2928:31:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;2919:40;;2969:37;;;;;;;;;;;;;;;;;;3004:1;2969:11;:37::i;:::-;3017:43;;;;;;;;;;;;;;;;;;3054:4;3017:11;:43::i;:::-;3070:57;;;;;;;;;;;;;;;;3100:26;;;;;3120:4;3100:26;;;1747:74:1;3070:57:0;;;3100:11;;;;1720:18:1;;3100:26:0;1601:226:1;3070:57:0;3137:47;;;;;;;;;;;;;;;;;;3172:10;3137:11;:47::i;:::-;3194:61;;;;;;;;;;;;;;;;3222:32;;;;;3242:10;3222:32;;;1747:74:1;3194:61:0;;;3222:11;;;;1720:18:1;;3222:32:0;1601:226:1;3194:61:0;3266:55;;;;;;;;;;;;;;;;;3354:38;;;;;3266:18;;3354:16;;;;:38;;3266:55;;3354:38;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;3331:61;;3402:37;;;;;;;;;;;;;;;;;;3422:4;3427:1;3422:7;;;;;;;;:::i;:::-;;;;;;;3431:4;3436:1;3431:7;;;;;;;;:::i;:::-;;;;;;;3402:11;:37::i;:::-;3450:27;;;;;9413:2:1;3450:27:0;;;9395:21:1;9452:2;9432:18;;;9425:30;9491:15;9471:18;;;9464:43;3450:4:0;;:10;;9524:18:1;;3450:27:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;3487:37:0;;;;;3517:4;3487:37;;;1747:74:1;3487:13:0;;-1:-1:-1;3487:13:0;;-1:-1:-1;1720:18:1;;3487:37:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;3534:26:0;;;;;9755:2:1;3534:26:0;;;9737:21:1;9794:2;9774:18;;;9767:30;9833:14;9813:18;;;9806:42;3534:4:0;;-1:-1:-1;3534:10:0;;-1:-1:-1;9865:18:1;;3534:26:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3570:59;;;;;;;;;;;;;;;;;;3617:10;3570:11;:59::i;:::-;3639:56;;;;;;;;;;;;;;;;;;3689:4;3639:11;:56::i;:::-;3705:26;;;;;10096:2:1;3705:26:0;;;10078:21:1;10135:2;10115:18;;;10108:30;10174:14;10154:18;;;10147:42;3705:4:0;;:10;;10206:18:1;;3705:26:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2634:28;2626:37;;3741:12;;;:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;3765:33:0;;;;;10437:2:1;3765:33:0;;;10419:21:1;10476:2;10456:18;;;10449:30;10515:21;10495:18;;;10488:49;3765:4:0;;-1:-1:-1;3765:10:0;;-1:-1:-1;10554:18:1;;3765:33:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3809:20;;;;;;;;;;;;;;;;;;:11;:20::i;:::-;2909:927;;;2887:949::o;1658:121::-;1713:59;1768:2;1729:42;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;1713:15;:59::i;:::-;1658:121;:::o;2081:145::-;2148:71;2211:2;2215;2164:54;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;2148:15;:71::i;1930:145::-;1997:71;2060:2;2064;2013:54;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;1997:15;:71::i;1785:139::-;1849:68;1909:2;1913;1865:51;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;1849:15;:68::i;2232:179::-;2323:81;2392:2;2396;2400;2339:64;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;1133:133;1204:55;1251:7;1370:14;;856:42;1543:2;1530:16;;1346:21;;1370:14;1530:16;856:42;1579:5;1568:68;1559:77;;1496:150;;1272:380;:::o;-1:-1:-1:-;;;;;;;;:::o;196:592:1:-;267:6;275;328:2;316:9;307:7;303:23;299:32;296:52;;;344:1;341;334:12;296:52;384:9;371:23;413:18;454:2;446:6;443:14;440:34;;;470:1;467;460:12;440:34;508:6;497:9;493:22;483:32;;553:7;546:4;542:2;538:13;534:27;524:55;;575:1;572;565:12;524:55;615:2;602:16;641:2;633:6;630:14;627:34;;;657:1;654;647:12;627:34;702:7;697:2;688:6;684:2;680:15;676:24;673:37;670:57;;;723:1;720;713:12;670:57;754:2;746:11;;;;;776:6;;-1:-1:-1;196:592:1;;-1:-1:-1;;;;196:592:1:o;793:349::-;832:3;863:66;856:5;853:77;850:257;;963:77;960:1;953:88;1064:4;1061:1;1054:15;1092:4;1089:1;1082:15;850:257;-1:-1:-1;1134:1:1;1123:13;;793:349::o;1147:449::-;1306:2;1295:9;1288:21;1345:6;1340:2;1329:9;1325:18;1318:34;1402:6;1394;1389:2;1378:9;1374:18;1361:48;1458:1;1429:22;;;1453:2;1425:31;;;1418:42;;;;1512:2;1500:15;;;1517:66;1496:88;1481:104;1477:113;;1147:449;-1:-1:-1;1147:449:1:o;1832:288::-;1901:6;1954:2;1942:9;1933:7;1929:23;1925:32;1922:52;;;1970:1;1967;1960:12;1922:52;2002:9;1996:16;2052:18;2045:5;2041:30;2034:5;2031:41;2021:69;;2086:1;2083;2076:12;2021:69;2109:5;1832:288;-1:-1:-1;;;1832:288:1:o;4709:184::-;4779:6;4832:2;4820:9;4811:7;4807:23;4803:32;4800:52;;;4848:1;4845;4838:12;4800:52;-1:-1:-1;4871:16:1;;4709:184;-1:-1:-1;4709:184:1:o;5323:277::-;5390:6;5443:2;5431:9;5422:7;5418:23;5414:32;5411:52;;;5459:1;5456;5449:12;5411:52;5491:9;5485:16;5544:5;5537:13;5530:21;5523:5;5520:32;5510:60;;5566:1;5563;5556:12;5605:258;5677:1;5687:113;5701:6;5698:1;5695:13;5687:113;;;5777:11;;;5771:18;5758:11;;;5751:39;5723:2;5716:10;5687:113;;;5818:6;5815:1;5812:13;5809:48;;;5853:1;5844:6;5839:3;5835:16;5828:27;5809:48;;5605:258;;;:::o;5868:317::-;5910:3;5948:5;5942:12;5975:6;5970:3;5963:19;5991:63;6047:6;6040:4;6035:3;6031:14;6024:4;6017:5;6013:16;5991:63;:::i;:::-;6099:2;6087:15;6104:66;6083:88;6074:98;;;;6174:4;6070:109;;5868:317;-1:-1:-1;;5868:317:1:o;6190:493::-;6440:2;6429:9;6422:21;6403:4;6466:45;6507:2;6496:9;6492:18;6484:6;6466:45;:::i;:::-;6559:9;6551:6;6547:22;6542:2;6531:9;6527:18;6520:50;6594:2;6586:6;6579:18;6630:14;6625:2;6617:6;6613:15;6606:39;6674:2;6666:6;6662:15;6654:23;;;6190:493;;;;:::o;6688:184::-;6740:77;6737:1;6730:88;6837:4;6834:1;6827:15;6861:4;6858:1;6851:15;6877:334;6948:2;6942:9;7004:2;6994:13;;7009:66;6990:86;6978:99;;7107:18;7092:34;;7128:22;;;7089:62;7086:88;;;7154:18;;:::i;:::-;7190:2;7183:22;6877:334;;-1:-1:-1;6877:334:1:o;7216:1801::-;7321:6;7352:2;7395;7383:9;7374:7;7370:23;7366:32;7363:52;;;7411:1;7408;7401:12;7363:52;7444:9;7438:16;7473:18;7514:2;7506:6;7503:14;7500:34;;;7530:1;7527;7520:12;7500:34;7568:6;7557:9;7553:22;7543:32;;7594:4;7634:7;7629:2;7625;7621:11;7617:25;7607:53;;7656:1;7653;7646:12;7607:53;7685:2;7679:9;7707:2;7703;7700:10;7697:36;;;7713:18;;:::i;:::-;7759:2;7756:1;7752:10;7782:28;7806:2;7802;7798:11;7782:28;:::i;:::-;7844:15;;;7914:11;;;7910:20;;;7875:12;;;;7942:19;;;7939:39;;;7974:1;7971;7964:12;7939:39;8006:2;8002;7998:11;7987:22;;8018:969;8034:6;8029:3;8026:15;8018:969;;;8113:3;8107:10;8149:2;8136:11;8133:19;8130:109;;;8193:1;8222:2;8218;8211:14;8130:109;8262:20;;8317:2;8309:11;;8305:25;-1:-1:-1;8295:123:1;;8372:1;8401:2;8397;8390:14;8295:123;8456:2;8452;8448:11;8442:18;8484:2;8510;8505:3;8502:11;8499:37;;;8516:18;;:::i;:::-;8562:111;8669:2;8600:66;8595:2;8590:3;8586:12;8582:85;8578:94;8562:111;:::i;:::-;8700:3;8693:5;8686:18;8747:7;8741:3;8735;8731:2;8727:12;8723:22;8720:35;8717:128;;;8797:1;8827:3;8822;8815:16;8717:128;8858:56;8910:3;8905:2;8898:5;8894:14;8888:3;8884:2;8880:12;8858:56;:::i;:::-;8927:18;;-1:-1:-1;;;8051:12:1;;;;8965;;;;8018:969;;;9006:5;7216:1801;-1:-1:-1;;;;;;;;;;7216:1801:1:o;9022:184::-;9074:77;9071:1;9064:88;9171:4;9168:1;9161:15;9195:4;9192:1;9185:15;10583:220;10732:2;10721:9;10714:21;10695:4;10752:45;10793:2;10782:9;10778:18;10770:6;10752:45;:::i;10808:340::-;10985:2;10974:9;10967:21;10948:4;11005:45;11046:2;11035:9;11031:18;11023:6;11005:45;:::i;:::-;10997:53;;11098:42;11090:6;11086:55;11081:2;11070:9;11066:18;11059:83;10808:340;;;;;:::o;11153:291::-;11330:2;11319:9;11312:21;11293:4;11350:45;11391:2;11380:9;11376:18;11368:6;11350:45;:::i;:::-;11342:53;;11431:6;11426:2;11415:9;11411:18;11404:34;11153:291;;;;;:::o;11449:301::-;11620:2;11609:9;11602:21;11583:4;11640:45;11681:2;11670:9;11666:18;11658:6;11640:45;:::i;:::-;11632:53;;11735:6;11728:14;11721:22;11716:2;11705:9;11701:18;11694:50;11449:301;;;;;:::o;11755:546::-;12000:2;11989:9;11982:21;11963:4;12026:45;12067:2;12056:9;12052:18;12044:6;12026:45;:::i;:::-;12119:9;12111:6;12107:22;12102:2;12091:9;12087:18;12080:50;12153:33;12179:6;12171;12153:33;:::i;:::-;12139:47;;12234:9;12226:6;12222:22;12217:2;12206:9;12202:18;12195:50;12262:33;12288:6;12280;12262:33;:::i;:::-;12254:41;11755:546;-1:-1:-1;;;;;;11755:546:1:o","linkReferences":{}},"methodIdentifiers":{"call1(string)":"7e79255d","call2(string)":"8d3ef7ca","callPure(string)":"7f8b915c","counter()":"61bc221a","hello(string)":"a777d0dc","nested1(string)":"a76ccdfa","nested2(string)":"dbf1282f","run()":"c0406226","runBroadcast()":"bef03abc"},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_v\",\"type\":\"string\"}],\"name\":\"call1\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_v\",\"type\":\"string\"}],\"name\":\"call2\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_v\",\"type\":\"string\"}],\"name\":\"callPure\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"counter\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_v\",\"type\":\"string\"}],\"name\":\"hello\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_v\",\"type\":\"string\"}],\"name\":\"nested1\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_v\",\"type\":\"string\"}],\"name\":\"nested2\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"run\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"runBroadcast\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"title\":\"ScriptExample\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"hello(string)\":{\"notice\":\"example external function, to force a CALL, and test vm.startPrank with.\"},\"run()\":{\"notice\":\"example function, runs through basic cheat-codes and console logs.\"},\"runBroadcast()\":{\"notice\":\"example function, to test vm.broadcast with.\"}},\"notice\":\"ScriptExample is an example script. The Go forge script code tests that it can run this.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"scripts/ScriptExample.s.sol\":\"ScriptExample\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[]},\"sources\":{\"scripts/ScriptExample.s.sol\":{\"keccak256\":\"0x8d1dfa41908e7ccc3a498a2a2aa51c5275bedbb904ce32d08f8598e36f896d8d\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://5117bb7158363cae8b9dc0508d2852692fd36172f1c699ff680afbb5acebe1f3\",\"dweb:/ipfs/QmQdahJ8SPKfJ4yea5Ge9qaj5qh1TxVffhHvaWytBaL95h\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.15+commit.e14f2714"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"string","name":"_v","type":"string"}],"stateMutability":"nonpayable","type":"function","name":"call1"},{"inputs":[{"internalType":"string","name":"_v","type":"string"}],"stateMutability":"nonpayable","type":"function","name":"call2"},{"inputs":[{"internalType":"string","name":"_v","type":"string"}],"stateMutability":"pure","type":"function","name":"callPure"},{"inputs":[],"stateMutability":"view","type":"function","name":"counter","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[{"internalType":"string","name":"_v","type":"string"}],"stateMutability":"view","type":"function","name":"hello"},{"inputs":[{"internalType":"string","name":"_v","type":"string"}],"stateMutability":"nonpayable","type":"function","name":"nested1"},{"inputs":[{"internalType":"string","name":"_v","type":"string"}],"stateMutability":"nonpayable","type":"function","name":"nested2"},{"inputs":[],"stateMutability":"nonpayable","type":"function","name":"run"},{"inputs":[],"stateMutability":"nonpayable","type":"function","name":"runBroadcast"}],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{"hello(string)":{"notice":"example external function, to force a CALL, and test vm.startPrank with."},"run()":{"notice":"example function, runs through basic cheat-codes and console logs."},"runBroadcast()":{"notice":"example function, to test vm.broadcast with."}},"version":1}},"settings":{"remappings":[],"optimizer":{"enabled":true,"runs":999999},"metadata":{"bytecodeHash":"none"},"compilationTarget":{"scripts/ScriptExample.s.sol":"ScriptExample"},"evmVersion":"london","libraries":{}},"sources":{"scripts/ScriptExample.s.sol":{"keccak256":"0x8d1dfa41908e7ccc3a498a2a2aa51c5275bedbb904ce32d08f8598e36f896d8d","urls":["bzz-raw://5117bb7158363cae8b9dc0508d2852692fd36172f1c699ff680afbb5acebe1f3","dweb:/ipfs/QmQdahJ8SPKfJ4yea5Ge9qaj5qh1TxVffhHvaWytBaL95h"],"license":"MIT"}},"version":1},"storageLayout":{"storage":[{"astId":215,"contract":"scripts/ScriptExample.s.sol:ScriptExample","label":"counter","offset":0,"slot":"0","type":"t_uint256"}],"types":{"t_uint256":{"encoding":"inplace","label":"uint256","numberOfBytes":"32"}}},"userdoc":{"version":1,"kind":"user","methods":{"hello(string)":{"notice":"example external function, to force a CALL, and test vm.startPrank with."},"run()":{"notice":"example function, runs through basic cheat-codes and console logs."},"runBroadcast()":{"notice":"example function, to test vm.broadcast with."}},"notice":"ScriptExample is an example script. The Go forge script code tests that it can run this."},"devdoc":{"version":1,"kind":"dev","title":"ScriptExample"},"ast":{"absolutePath":"scripts/ScriptExample.s.sol","id":720,"exportedSymbols":{"FooBar":[719],"ScriptExample":[706],"Vm":[55],"console":[192]},"nodeType":"SourceUnit","src":"32:5967:0","nodes":[{"id":1,"nodeType":"PragmaDirective","src":"32:23:0","nodes":[],"literals":["solidity","0.8",".15"]},{"id":55,"nodeType":"ContractDefinition","src":"120:616:0","nodes":[{"id":10,"nodeType":"FunctionDefinition","src":"139:91:0","nodes":[],"functionSelector":"4777f3cf","implemented":false,"kind":"function","modifiers":[],"name":"envOr","nameLocation":"148:5:0","parameters":{"id":6,"nodeType":"ParameterList","parameters":[{"constant":false,"id":3,"mutability":"mutable","name":"name","nameLocation":"170:4:0","nodeType":"VariableDeclaration","scope":10,"src":"154:20:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":2,"name":"string","nodeType":"ElementaryTypeName","src":"154:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":5,"mutability":"mutable","name":"defaultValue","nameLocation":"181:12:0","nodeType":"VariableDeclaration","scope":10,"src":"176:17:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":4,"name":"bool","nodeType":"ElementaryTypeName","src":"176:4:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"src":"153:41:0"},"returnParameters":{"id":9,"nodeType":"ParameterList","parameters":[{"constant":false,"id":8,"mutability":"mutable","name":"value","nameLocation":"223:5:0","nodeType":"VariableDeclaration","scope":10,"src":"218:10:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":7,"name":"bool","nodeType":"ElementaryTypeName","src":"218:4:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"src":"217:12:0"},"scope":55,"stateMutability":"view","virtual":false,"visibility":"external"},{"id":17,"nodeType":"FunctionDefinition","src":"235:72:0","nodes":[],"functionSelector":"2d0335ab","implemented":false,"kind":"function","modifiers":[],"name":"getNonce","nameLocation":"244:8:0","parameters":{"id":13,"nodeType":"ParameterList","parameters":[{"constant":false,"id":12,"mutability":"mutable","name":"account","nameLocation":"261:7:0","nodeType":"VariableDeclaration","scope":17,"src":"253:15:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":11,"name":"address","nodeType":"ElementaryTypeName","src":"253:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"252:17:0"},"returnParameters":{"id":16,"nodeType":"ParameterList","parameters":[{"constant":false,"id":15,"mutability":"mutable","name":"nonce","nameLocation":"300:5:0","nodeType":"VariableDeclaration","scope":17,"src":"293:12:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"},"typeName":{"id":14,"name":"uint64","nodeType":"ElementaryTypeName","src":"293:6:0","typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}},"visibility":"internal"}],"src":"292:14:0"},"scope":55,"stateMutability":"view","virtual":false,"visibility":"external"},{"id":27,"nodeType":"FunctionDefinition","src":"312:111:0","nodes":[],"functionSelector":"213e4198","implemented":false,"kind":"function","modifiers":[],"name":"parseJsonKeys","nameLocation":"321:13:0","parameters":{"id":22,"nodeType":"ParameterList","parameters":[{"constant":false,"id":19,"mutability":"mutable","name":"json","nameLocation":"351:4:0","nodeType":"VariableDeclaration","scope":27,"src":"335:20:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":18,"name":"string","nodeType":"ElementaryTypeName","src":"335:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":21,"mutability":"mutable","name":"key","nameLocation":"373:3:0","nodeType":"VariableDeclaration","scope":27,"src":"357:19:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":20,"name":"string","nodeType":"ElementaryTypeName","src":"357:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"334:43:0"},"returnParameters":{"id":26,"nodeType":"ParameterList","parameters":[{"constant":false,"id":25,"mutability":"mutable","name":"keys","nameLocation":"417:4:0","nodeType":"VariableDeclaration","scope":27,"src":"401:20:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string[]"},"typeName":{"baseType":{"id":23,"name":"string","nodeType":"ElementaryTypeName","src":"401:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"id":24,"nodeType":"ArrayTypeName","src":"401:8:0","typeDescriptions":{"typeIdentifier":"t_array$_t_string_storage_$dyn_storage_ptr","typeString":"string[]"}},"visibility":"internal"}],"src":"400:22:0"},"scope":55,"stateMutability":"pure","virtual":false,"visibility":"external"},{"id":32,"nodeType":"FunctionDefinition","src":"428:48:0","nodes":[],"functionSelector":"06447d56","implemented":false,"kind":"function","modifiers":[],"name":"startPrank","nameLocation":"437:10:0","parameters":{"id":30,"nodeType":"ParameterList","parameters":[{"constant":false,"id":29,"mutability":"mutable","name":"msgSender","nameLocation":"456:9:0","nodeType":"VariableDeclaration","scope":32,"src":"448:17:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":28,"name":"address","nodeType":"ElementaryTypeName","src":"448:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"447:19:0"},"returnParameters":{"id":31,"nodeType":"ParameterList","parameters":[],"src":"475:0:0"},"scope":55,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":35,"nodeType":"FunctionDefinition","src":"481:30:0","nodes":[],"functionSelector":"90c5013b","implemented":false,"kind":"function","modifiers":[],"name":"stopPrank","nameLocation":"490:9:0","parameters":{"id":33,"nodeType":"ParameterList","parameters":[],"src":"499:2:0"},"returnParameters":{"id":34,"nodeType":"ParameterList","parameters":[],"src":"510:0:0"},"scope":55,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":38,"nodeType":"FunctionDefinition","src":"516:30:0","nodes":[],"functionSelector":"afc98040","implemented":false,"kind":"function","modifiers":[],"name":"broadcast","nameLocation":"525:9:0","parameters":{"id":36,"nodeType":"ParameterList","parameters":[],"src":"534:2:0"},"returnParameters":{"id":37,"nodeType":"ParameterList","parameters":[],"src":"545:0:0"},"scope":55,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":43,"nodeType":"FunctionDefinition","src":"551:47:0","nodes":[],"functionSelector":"e6962cdb","implemented":false,"kind":"function","modifiers":[],"name":"broadcast","nameLocation":"560:9:0","parameters":{"id":41,"nodeType":"ParameterList","parameters":[{"constant":false,"id":40,"mutability":"mutable","name":"msgSender","nameLocation":"578:9:0","nodeType":"VariableDeclaration","scope":43,"src":"570:17:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":39,"name":"address","nodeType":"ElementaryTypeName","src":"570:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"569:19:0"},"returnParameters":{"id":42,"nodeType":"ParameterList","parameters":[],"src":"597:0:0"},"scope":55,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":48,"nodeType":"FunctionDefinition","src":"603:52:0","nodes":[],"functionSelector":"7fec2a8d","implemented":false,"kind":"function","modifiers":[],"name":"startBroadcast","nameLocation":"612:14:0","parameters":{"id":46,"nodeType":"ParameterList","parameters":[{"constant":false,"id":45,"mutability":"mutable","name":"msgSender","nameLocation":"635:9:0","nodeType":"VariableDeclaration","scope":48,"src":"627:17:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":44,"name":"address","nodeType":"ElementaryTypeName","src":"627:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"626:19:0"},"returnParameters":{"id":47,"nodeType":"ParameterList","parameters":[],"src":"654:0:0"},"scope":55,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":51,"nodeType":"FunctionDefinition","src":"660:35:0","nodes":[],"functionSelector":"7fb5297f","implemented":false,"kind":"function","modifiers":[],"name":"startBroadcast","nameLocation":"669:14:0","parameters":{"id":49,"nodeType":"ParameterList","parameters":[],"src":"683:2:0"},"returnParameters":{"id":50,"nodeType":"ParameterList","parameters":[],"src":"694:0:0"},"scope":55,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":54,"nodeType":"FunctionDefinition","src":"700:34:0","nodes":[],"functionSelector":"76eadd36","implemented":false,"kind":"function","modifiers":[],"name":"stopBroadcast","nameLocation":"709:13:0","parameters":{"id":52,"nodeType":"ParameterList","parameters":[],"src":"722:2:0"},"returnParameters":{"id":53,"nodeType":"ParameterList","parameters":[],"src":"733:0:0"},"scope":55,"stateMutability":"nonpayable","virtual":false,"visibility":"external"}],"abstract":false,"baseContracts":[],"canonicalName":"Vm","contractDependencies":[],"contractKind":"interface","fullyImplemented":false,"linearizedBaseContracts":[55],"name":"Vm","nameLocation":"130:2:0","scope":720,"usedErrors":[]},{"id":192,"nodeType":"ContractDefinition","src":"791:1622:0","nodes":[{"id":61,"nodeType":"VariableDeclaration","src":"813:86:0","nodes":[],"constant":true,"mutability":"constant","name":"CONSOLE_ADDRESS","nameLocation":"830:15:0","scope":192,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":56,"name":"address","nodeType":"ElementaryTypeName","src":"813:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"value":{"arguments":[{"hexValue":"307830303030303030303030303030303030303036333646366537333646366336353265366336663637","id":59,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"856:42:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"value":"0x000000000000000000636F6e736F6c652e6c6f67"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":58,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"848:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":57,"name":"address","nodeType":"ElementaryTypeName","src":"848:7:0","typeDescriptions":{}}},"id":60,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"848:51:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"},{"id":78,"nodeType":"FunctionDefinition","src":"906:221:0","nodes":[],"body":{"id":77,"nodeType":"Block","src":"1065:62:0","nodes":[],"statements":[{"AST":{"nodeType":"YulBlock","src":"1084:37:0","statements":[{"nodeType":"YulAssignment","src":"1098:13:0","value":{"name":"fnIn","nodeType":"YulIdentifier","src":"1107:4:0"},"variableNames":[{"name":"fnOut","nodeType":"YulIdentifier","src":"1098:5:0"}]}]},"evmVersion":"london","externalReferences":[{"declaration":67,"isOffset":false,"isSlot":false,"src":"1107:4:0","valueSize":1},{"declaration":74,"isOffset":false,"isSlot":false,"src":"1098:5:0","valueSize":1}],"id":76,"nodeType":"InlineAssembly","src":"1075:46:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"_castLogPayloadViewToPure","nameLocation":"915:25:0","parameters":{"id":68,"nodeType":"ParameterList","parameters":[{"constant":false,"id":67,"mutability":"mutable","name":"fnIn","nameLocation":"987:4:0","nodeType":"VariableDeclaration","scope":78,"src":"950:41:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_function_internal_view$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes) view"},"typeName":{"id":66,"nodeType":"FunctionTypeName","parameterTypes":{"id":64,"nodeType":"ParameterList","parameters":[{"constant":false,"id":63,"mutability":"mutable","name":"","nameLocation":"-1:-1:-1","nodeType":"VariableDeclaration","scope":66,"src":"959:12:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":62,"name":"bytes","nodeType":"ElementaryTypeName","src":"959:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"958:14:0"},"returnParameterTypes":{"id":65,"nodeType":"ParameterList","parameters":[],"src":"987:0:0"},"src":"950:41:0","stateMutability":"view","typeDescriptions":{"typeIdentifier":"t_function_internal_view$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes) view"},"visibility":"internal"},"visibility":"internal"}],"src":"940:57:0"},"returnParameters":{"id":75,"nodeType":"ParameterList","parameters":[{"constant":false,"id":74,"mutability":"mutable","name":"fnOut","nameLocation":"1058:5:0","nodeType":"VariableDeclaration","scope":78,"src":"1021:42:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes) pure"},"typeName":{"id":73,"nodeType":"FunctionTypeName","parameterTypes":{"id":71,"nodeType":"ParameterList","parameters":[{"constant":false,"id":70,"mutability":"mutable","name":"","nameLocation":"-1:-1:-1","nodeType":"VariableDeclaration","scope":73,"src":"1030:12:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":69,"name":"bytes","nodeType":"ElementaryTypeName","src":"1030:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"1029:14:0"},"returnParameterTypes":{"id":72,"nodeType":"ParameterList","parameters":[],"src":"1058:0:0"},"src":"1021:42:0","stateMutability":"pure","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes) pure"},"visibility":"internal"},"visibility":"internal"}],"src":"1020:44:0"},"scope":192,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":90,"nodeType":"FunctionDefinition","src":"1133:133:0","nodes":[],"body":{"id":89,"nodeType":"Block","src":"1194:72:0","nodes":[],"statements":[{"expression":{"arguments":[{"id":86,"name":"payload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":80,"src":"1251:7:0","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"arguments":[{"id":84,"name":"_sendLogPayloadView","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":106,"src":"1230:19:0","typeDescriptions":{"typeIdentifier":"t_function_internal_view$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) view"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_function_internal_view$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) view"}],"id":83,"name":"_castLogPayloadViewToPure","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":78,"src":"1204:25:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_function_internal_view$_t_bytes_memory_ptr_$returns$__$_$returns$_t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$_$","typeString":"function (function (bytes memory) view) pure returns (function (bytes memory) pure)"}},"id":85,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1204:46:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":87,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1204:55:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":88,"nodeType":"ExpressionStatement","src":"1204:55:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"_sendLogPayload","nameLocation":"1142:15:0","parameters":{"id":81,"nodeType":"ParameterList","parameters":[{"constant":false,"id":80,"mutability":"mutable","name":"payload","nameLocation":"1171:7:0","nodeType":"VariableDeclaration","scope":90,"src":"1158:20:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":79,"name":"bytes","nodeType":"ElementaryTypeName","src":"1158:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"1157:22:0"},"returnParameters":{"id":82,"nodeType":"ParameterList","parameters":[],"src":"1194:0:0"},"scope":192,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":106,"nodeType":"FunctionDefinition","src":"1272:380:0","nodes":[],"body":{"id":105,"nodeType":"Block","src":"1336:316:0","nodes":[],"statements":[{"assignments":[96],"declarations":[{"constant":false,"id":96,"mutability":"mutable","name":"payloadLength","nameLocation":"1354:13:0","nodeType":"VariableDeclaration","scope":105,"src":"1346:21:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":95,"name":"uint256","nodeType":"ElementaryTypeName","src":"1346:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"}],"id":99,"initialValue":{"expression":{"id":97,"name":"payload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":92,"src":"1370:7:0","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}},"id":98,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"length","nodeType":"MemberAccess","src":"1370:14:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"nodeType":"VariableDeclarationStatement","src":"1346:38:0"},{"assignments":[101],"declarations":[{"constant":false,"id":101,"mutability":"mutable","name":"consoleAddress","nameLocation":"1402:14:0","nodeType":"VariableDeclaration","scope":105,"src":"1394:22:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":100,"name":"address","nodeType":"ElementaryTypeName","src":"1394:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"id":103,"initialValue":{"id":102,"name":"CONSOLE_ADDRESS","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":61,"src":"1419:15:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"nodeType":"VariableDeclarationStatement","src":"1394:40:0"},{"AST":{"nodeType":"YulBlock","src":"1496:150:0","statements":[{"nodeType":"YulVariableDeclaration","src":"1510:36:0","value":{"arguments":[{"name":"payload","nodeType":"YulIdentifier","src":"1534:7:0"},{"kind":"number","nodeType":"YulLiteral","src":"1543:2:0","type":"","value":"32"}],"functionName":{"name":"add","nodeType":"YulIdentifier","src":"1530:3:0"},"nodeType":"YulFunctionCall","src":"1530:16:0"},"variables":[{"name":"payloadStart","nodeType":"YulTypedName","src":"1514:12:0","type":""}]},{"nodeType":"YulVariableDeclaration","src":"1559:77:0","value":{"arguments":[{"arguments":[],"functionName":{"name":"gas","nodeType":"YulIdentifier","src":"1579:3:0"},"nodeType":"YulFunctionCall","src":"1579:5:0"},{"name":"consoleAddress","nodeType":"YulIdentifier","src":"1586:14:0"},{"name":"payloadStart","nodeType":"YulIdentifier","src":"1602:12:0"},{"name":"payloadLength","nodeType":"YulIdentifier","src":"1616:13:0"},{"kind":"number","nodeType":"YulLiteral","src":"1631:1:0","type":"","value":"0"},{"kind":"number","nodeType":"YulLiteral","src":"1634:1:0","type":"","value":"0"}],"functionName":{"name":"staticcall","nodeType":"YulIdentifier","src":"1568:10:0"},"nodeType":"YulFunctionCall","src":"1568:68:0"},"variables":[{"name":"r","nodeType":"YulTypedName","src":"1563:1:0","type":""}]}]},"documentation":"@solidity memory-safe-assembly","evmVersion":"london","externalReferences":[{"declaration":101,"isOffset":false,"isSlot":false,"src":"1586:14:0","valueSize":1},{"declaration":92,"isOffset":false,"isSlot":false,"src":"1534:7:0","valueSize":1},{"declaration":96,"isOffset":false,"isSlot":false,"src":"1616:13:0","valueSize":1}],"id":104,"nodeType":"InlineAssembly","src":"1487:159:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"_sendLogPayloadView","nameLocation":"1281:19:0","parameters":{"id":93,"nodeType":"ParameterList","parameters":[{"constant":false,"id":92,"mutability":"mutable","name":"payload","nameLocation":"1314:7:0","nodeType":"VariableDeclaration","scope":106,"src":"1301:20:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":91,"name":"bytes","nodeType":"ElementaryTypeName","src":"1301:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"1300:22:0"},"returnParameters":{"id":94,"nodeType":"ParameterList","parameters":[],"src":"1336:0:0"},"scope":192,"stateMutability":"view","virtual":false,"visibility":"private"},{"id":120,"nodeType":"FunctionDefinition","src":"1658:121:0","nodes":[],"body":{"id":119,"nodeType":"Block","src":"1703:76:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e6729","id":114,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"1753:13:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_41304facd9323d75b11bcdd609cb38effffdb05710f7caf0e9b16c6d9d709f50","typeString":"literal_string \"log(string)\""},"value":"log(string)"},{"id":115,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":108,"src":"1768:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_41304facd9323d75b11bcdd609cb38effffdb05710f7caf0e9b16c6d9d709f50","typeString":"literal_string \"log(string)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}],"expression":{"id":112,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"1729:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":113,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"1729:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":116,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1729:42:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":111,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":90,"src":"1713:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":117,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1713:59:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":118,"nodeType":"ExpressionStatement","src":"1713:59:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"1667:3:0","parameters":{"id":109,"nodeType":"ParameterList","parameters":[{"constant":false,"id":108,"mutability":"mutable","name":"p0","nameLocation":"1685:2:0","nodeType":"VariableDeclaration","scope":120,"src":"1671:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":107,"name":"string","nodeType":"ElementaryTypeName","src":"1671:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"1670:18:0"},"returnParameters":{"id":110,"nodeType":"ParameterList","parameters":[],"src":"1703:0:0"},"scope":192,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":137,"nodeType":"FunctionDefinition","src":"1785:139:0","nodes":[],"body":{"id":136,"nodeType":"Block","src":"1839:85:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e672c626f6f6c29","id":130,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"1889:18:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_c3b556354c088fbb43886eb83c2a04bc7089663f964d22be308197a236f5b870","typeString":"literal_string \"log(string,bool)\""},"value":"log(string,bool)"},{"id":131,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":122,"src":"1909:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":132,"name":"p1","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":124,"src":"1913:2:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_c3b556354c088fbb43886eb83c2a04bc7089663f964d22be308197a236f5b870","typeString":"literal_string \"log(string,bool)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_bool","typeString":"bool"}],"expression":{"id":128,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"1865:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":129,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"1865:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":133,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1865:51:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":127,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":90,"src":"1849:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":134,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1849:68:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":135,"nodeType":"ExpressionStatement","src":"1849:68:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"1794:3:0","parameters":{"id":125,"nodeType":"ParameterList","parameters":[{"constant":false,"id":122,"mutability":"mutable","name":"p0","nameLocation":"1812:2:0","nodeType":"VariableDeclaration","scope":137,"src":"1798:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":121,"name":"string","nodeType":"ElementaryTypeName","src":"1798:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":124,"mutability":"mutable","name":"p1","nameLocation":"1821:2:0","nodeType":"VariableDeclaration","scope":137,"src":"1816:7:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":123,"name":"bool","nodeType":"ElementaryTypeName","src":"1816:4:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"src":"1797:27:0"},"returnParameters":{"id":126,"nodeType":"ParameterList","parameters":[],"src":"1839:0:0"},"scope":192,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":154,"nodeType":"FunctionDefinition","src":"1930:145:0","nodes":[],"body":{"id":153,"nodeType":"Block","src":"1987:88:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e672c75696e7432353629","id":147,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2037:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_b60e72ccf6d57ab53eb84d7e94a9545806ed7f93c4d5673f11a64f03471e584e","typeString":"literal_string \"log(string,uint256)\""},"value":"log(string,uint256)"},{"id":148,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":139,"src":"2060:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":149,"name":"p1","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":141,"src":"2064:2:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_b60e72ccf6d57ab53eb84d7e94a9545806ed7f93c4d5673f11a64f03471e584e","typeString":"literal_string \"log(string,uint256)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_uint256","typeString":"uint256"}],"expression":{"id":145,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"2013:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":146,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"2013:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":150,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2013:54:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":144,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":90,"src":"1997:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":151,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1997:71:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":152,"nodeType":"ExpressionStatement","src":"1997:71:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"1939:3:0","parameters":{"id":142,"nodeType":"ParameterList","parameters":[{"constant":false,"id":139,"mutability":"mutable","name":"p0","nameLocation":"1957:2:0","nodeType":"VariableDeclaration","scope":154,"src":"1943:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":138,"name":"string","nodeType":"ElementaryTypeName","src":"1943:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":141,"mutability":"mutable","name":"p1","nameLocation":"1969:2:0","nodeType":"VariableDeclaration","scope":154,"src":"1961:10:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":140,"name":"uint256","nodeType":"ElementaryTypeName","src":"1961:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"}],"src":"1942:30:0"},"returnParameters":{"id":143,"nodeType":"ParameterList","parameters":[],"src":"1987:0:0"},"scope":192,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":171,"nodeType":"FunctionDefinition","src":"2081:145:0","nodes":[],"body":{"id":170,"nodeType":"Block","src":"2138:88:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e672c6164647265737329","id":164,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2188:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_319af333460570a1937bf195dd33445c0d0951c59127da6f1f038b9fdce3fd72","typeString":"literal_string \"log(string,address)\""},"value":"log(string,address)"},{"id":165,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":156,"src":"2211:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":166,"name":"p1","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":158,"src":"2215:2:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_319af333460570a1937bf195dd33445c0d0951c59127da6f1f038b9fdce3fd72","typeString":"literal_string \"log(string,address)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":162,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"2164:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":163,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"2164:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":167,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2164:54:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":161,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":90,"src":"2148:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":168,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2148:71:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":169,"nodeType":"ExpressionStatement","src":"2148:71:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"2090:3:0","parameters":{"id":159,"nodeType":"ParameterList","parameters":[{"constant":false,"id":156,"mutability":"mutable","name":"p0","nameLocation":"2108:2:0","nodeType":"VariableDeclaration","scope":171,"src":"2094:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":155,"name":"string","nodeType":"ElementaryTypeName","src":"2094:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":158,"mutability":"mutable","name":"p1","nameLocation":"2120:2:0","nodeType":"VariableDeclaration","scope":171,"src":"2112:10:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":157,"name":"address","nodeType":"ElementaryTypeName","src":"2112:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"2093:30:0"},"returnParameters":{"id":160,"nodeType":"ParameterList","parameters":[],"src":"2138:0:0"},"scope":192,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":191,"nodeType":"FunctionDefinition","src":"2232:179:0","nodes":[],"body":{"id":190,"nodeType":"Block","src":"2313:98:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e672c737472696e672c737472696e6729","id":183,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2363:27:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_2ced7cef693312206c21f0e92e3b54e2e16bf33db5eec350c78866822c665e1f","typeString":"literal_string \"log(string,string,string)\""},"value":"log(string,string,string)"},{"id":184,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"2392:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":185,"name":"p1","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":175,"src":"2396:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":186,"name":"p2","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":177,"src":"2400:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_2ced7cef693312206c21f0e92e3b54e2e16bf33db5eec350c78866822c665e1f","typeString":"literal_string \"log(string,string,string)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}],"expression":{"id":181,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"2339:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":182,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"2339:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":187,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2339:64:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":180,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":90,"src":"2323:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":188,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2323:81:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":189,"nodeType":"ExpressionStatement","src":"2323:81:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"2241:3:0","parameters":{"id":178,"nodeType":"ParameterList","parameters":[{"constant":false,"id":173,"mutability":"mutable","name":"p0","nameLocation":"2259:2:0","nodeType":"VariableDeclaration","scope":191,"src":"2245:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":172,"name":"string","nodeType":"ElementaryTypeName","src":"2245:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":175,"mutability":"mutable","name":"p1","nameLocation":"2277:2:0","nodeType":"VariableDeclaration","scope":191,"src":"2263:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":174,"name":"string","nodeType":"ElementaryTypeName","src":"2263:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":177,"mutability":"mutable","name":"p2","nameLocation":"2295:2:0","nodeType":"VariableDeclaration","scope":191,"src":"2281:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":176,"name":"string","nodeType":"ElementaryTypeName","src":"2281:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"2244:54:0"},"returnParameters":{"id":179,"nodeType":"ParameterList","parameters":[],"src":"2313:0:0"},"scope":192,"stateMutability":"pure","virtual":false,"visibility":"internal"}],"abstract":false,"baseContracts":[],"canonicalName":"console","contractDependencies":[],"contractKind":"library","fullyImplemented":true,"linearizedBaseContracts":[192],"name":"console","nameLocation":"799:7:0","scope":720,"usedErrors":[]},{"id":706,"nodeType":"ContractDefinition","src":"2541:3359:0","nodes":[{"id":207,"nodeType":"VariableDeclaration","src":"2571:94:0","nodes":[],"constant":true,"mutability":"constant","name":"VM_ADDRESS","nameLocation":"2597:10:0","scope":706,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":194,"name":"address","nodeType":"ElementaryTypeName","src":"2571:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"value":{"arguments":[{"arguments":[{"arguments":[{"arguments":[{"hexValue":"6865766d20636865617420636f6465","id":202,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2644:17:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d","typeString":"literal_string \"hevm cheat code\""},"value":"hevm cheat code"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d","typeString":"literal_string \"hevm cheat code\""}],"id":201,"name":"keccak256","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-8,"src":"2634:9:0","typeDescriptions":{"typeIdentifier":"t_function_keccak256_pure$_t_bytes_memory_ptr_$returns$_t_bytes32_$","typeString":"function (bytes memory) pure returns (bytes32)"}},"id":203,"isConstant":false,"isLValue":false,"isPure":true,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2634:28:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes32","typeString":"bytes32"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes32","typeString":"bytes32"}],"id":200,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2626:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint256_$","typeString":"type(uint256)"},"typeName":{"id":199,"name":"uint256","nodeType":"ElementaryTypeName","src":"2626:7:0","typeDescriptions":{}}},"id":204,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2626:37:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint256","typeString":"uint256"}],"id":198,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2618:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":197,"name":"uint160","nodeType":"ElementaryTypeName","src":"2618:7:0","typeDescriptions":{}}},"id":205,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2618:46:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":196,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2610:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":195,"name":"address","nodeType":"ElementaryTypeName","src":"2610:7:0","typeDescriptions":{}}},"id":206,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2610:55:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"},{"id":213,"nodeType":"VariableDeclaration","src":"2671:40:0","nodes":[],"constant":true,"mutability":"constant","name":"vm","nameLocation":"2692:2:0","scope":706,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"},"typeName":{"id":209,"nodeType":"UserDefinedTypeName","pathNode":{"id":208,"name":"Vm","nodeType":"IdentifierPath","referencedDeclaration":55,"src":"2671:2:0"},"referencedDeclaration":55,"src":"2671:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"value":{"arguments":[{"id":211,"name":"VM_ADDRESS","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":207,"src":"2700:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":210,"name":"Vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":55,"src":"2697:2:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_Vm_$55_$","typeString":"type(contract Vm)"}},"id":212,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2697:14:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"visibility":"internal"},{"id":215,"nodeType":"VariableDeclaration","src":"2775:22:0","nodes":[],"constant":false,"functionSelector":"61bc221a","mutability":"mutable","name":"counter","nameLocation":"2790:7:0","scope":706,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":214,"name":"uint256","nodeType":"ElementaryTypeName","src":"2775:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"public"},{"id":378,"nodeType":"FunctionDefinition","src":"2887:949:0","nodes":[],"body":{"id":377,"nodeType":"Block","src":"2909:927:0","nodes":[],"statements":[{"assignments":[220],"declarations":[{"constant":false,"id":220,"mutability":"mutable","name":"x","nameLocation":"2924:1:0","nodeType":"VariableDeclaration","scope":377,"src":"2919:6:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":219,"name":"bool","nodeType":"ElementaryTypeName","src":"2919:4:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"id":226,"initialValue":{"arguments":[{"hexValue":"4558414d504c455f424f4f4c","id":223,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2937:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_a634dae177a0e138ae7aaa2afae347412e148992e88c7aabd33ee71be146cb7f","typeString":"literal_string \"EXAMPLE_BOOL\""},"value":"EXAMPLE_BOOL"},{"hexValue":"66616c7365","id":224,"isConstant":false,"isLValue":false,"isPure":true,"kind":"bool","lValueRequested":false,"nodeType":"Literal","src":"2953:5:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"value":"false"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_a634dae177a0e138ae7aaa2afae347412e148992e88c7aabd33ee71be146cb7f","typeString":"literal_string \"EXAMPLE_BOOL\""},{"typeIdentifier":"t_bool","typeString":"bool"}],"expression":{"id":221,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"2928:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":222,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"envOr","nodeType":"MemberAccess","referencedDeclaration":10,"src":"2928:8:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$_t_bool_$returns$_t_bool_$","typeString":"function (string memory,bool) view external returns (bool)"}},"id":225,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2928:31:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"nodeType":"VariableDeclarationStatement","src":"2919:40:0"},{"expression":{"arguments":[{"hexValue":"626f6f6c2076616c75652066726f6d20656e76","id":230,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2981:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_5a607d0b5a1295325aa8901721d78ba402601bba6f62cebdd5235dd0204a590b","typeString":"literal_string \"bool value from env\""},"value":"bool value from env"},{"id":231,"name":"x","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":220,"src":"3004:1:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_5a607d0b5a1295325aa8901721d78ba402601bba6f62cebdd5235dd0204a590b","typeString":"literal_string \"bool value from env\""},{"typeIdentifier":"t_bool","typeString":"bool"}],"expression":{"id":227,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"2969:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":229,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":137,"src":"2969:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_bool_$returns$__$","typeString":"function (string memory,bool) pure"}},"id":232,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2969:37:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":233,"nodeType":"ExpressionStatement","src":"2969:37:0"},{"expression":{"arguments":[{"hexValue":"636f6e74726163742061646472","id":237,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3029:15:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_fa50728770d00fe8f6a0592f3565bbfaf063ee4077f1f5bbc003d091d33cd0c4","typeString":"literal_string \"contract addr\""},"value":"contract addr"},{"arguments":[{"id":240,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3054:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}],"id":239,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3046:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":238,"name":"address","nodeType":"ElementaryTypeName","src":"3046:7:0","typeDescriptions":{}}},"id":241,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3046:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_fa50728770d00fe8f6a0592f3565bbfaf063ee4077f1f5bbc003d091d33cd0c4","typeString":"literal_string \"contract addr\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":234,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3017:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":236,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":171,"src":"3017:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":242,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3017:43:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":243,"nodeType":"ExpressionStatement","src":"3017:43:0"},{"expression":{"arguments":[{"hexValue":"636f6e7472616374206e6f6e6365","id":247,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3082:16:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_3a23091615a5de8c0a35ffd8857a37e2c4e0b72f3ef8a34d6caf65efcd562e2f","typeString":"literal_string \"contract nonce\""},"value":"contract nonce"},{"arguments":[{"arguments":[{"id":252,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3120:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}],"id":251,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3112:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":250,"name":"address","nodeType":"ElementaryTypeName","src":"3112:7:0","typeDescriptions":{}}},"id":253,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3112:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":248,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"3100:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":249,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"getNonce","nodeType":"MemberAccess","referencedDeclaration":17,"src":"3100:11:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_address_$returns$_t_uint64_$","typeString":"function (address) view external returns (uint64)"}},"id":254,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3100:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_3a23091615a5de8c0a35ffd8857a37e2c4e0b72f3ef8a34d6caf65efcd562e2f","typeString":"literal_string \"contract nonce\""},{"typeIdentifier":"t_uint64","typeString":"uint64"}],"expression":{"id":244,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3070:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":246,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":154,"src":"3070:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_uint256_$returns$__$","typeString":"function (string memory,uint256) pure"}},"id":255,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3070:57:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":256,"nodeType":"ExpressionStatement","src":"3070:57:0"},{"expression":{"arguments":[{"hexValue":"73656e6465722061646472","id":260,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3149:13:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_8125ca2decf812b25b65606ff16dad37cb198ff0433485a7926e50feafacfc35","typeString":"literal_string \"sender addr\""},"value":"sender addr"},{"arguments":[{"expression":{"id":263,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"3172:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":264,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"sender","nodeType":"MemberAccess","src":"3172:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":262,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3164:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":261,"name":"address","nodeType":"ElementaryTypeName","src":"3164:7:0","typeDescriptions":{}}},"id":265,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3164:19:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_8125ca2decf812b25b65606ff16dad37cb198ff0433485a7926e50feafacfc35","typeString":"literal_string \"sender addr\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":257,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3137:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":259,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":171,"src":"3137:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":266,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3137:47:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":267,"nodeType":"ExpressionStatement","src":"3137:47:0"},{"expression":{"arguments":[{"hexValue":"73656e646572206e6f6e6365","id":271,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3206:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_db7deb43f2f9e0404016de53b7e64c4976b54149581f7534daae2551e8cf4e40","typeString":"literal_string \"sender nonce\""},"value":"sender nonce"},{"arguments":[{"arguments":[{"expression":{"id":276,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"3242:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":277,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"sender","nodeType":"MemberAccess","src":"3242:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":275,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3234:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":274,"name":"address","nodeType":"ElementaryTypeName","src":"3234:7:0","typeDescriptions":{}}},"id":278,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3234:19:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":272,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"3222:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":273,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"getNonce","nodeType":"MemberAccess","referencedDeclaration":17,"src":"3222:11:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_address_$returns$_t_uint64_$","typeString":"function (address) view external returns (uint64)"}},"id":279,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3222:32:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_db7deb43f2f9e0404016de53b7e64c4976b54149581f7534daae2551e8cf4e40","typeString":"literal_string \"sender nonce\""},{"typeIdentifier":"t_uint64","typeString":"uint64"}],"expression":{"id":268,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3194:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":270,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":154,"src":"3194:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_uint256_$returns$__$","typeString":"function (string memory,uint256) pure"}},"id":280,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3194:61:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":281,"nodeType":"ExpressionStatement","src":"3194:61:0"},{"assignments":[283],"declarations":[{"constant":false,"id":283,"mutability":"mutable","name":"json","nameLocation":"3280:4:0","nodeType":"VariableDeclaration","scope":377,"src":"3266:18:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":282,"name":"string","nodeType":"ElementaryTypeName","src":"3266:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"id":285,"initialValue":{"hexValue":"7b22726f6f745f6b6579223a205b7b2261223a20312c202262223a20327d5d7d","id":284,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3287:34:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_e95522e99766888d0261f55bd1eae5e3f3e26eaf009a16e2433eafaf0a4ecdf2","typeString":"literal_string \"{\"root_key\": [{\"a\": 1, \"b\": 2}]}\""},"value":"{\"root_key\": [{\"a\": 1, \"b\": 2}]}"},"nodeType":"VariableDeclarationStatement","src":"3266:55:0"},{"assignments":[290],"declarations":[{"constant":false,"id":290,"mutability":"mutable","name":"keys","nameLocation":"3347:4:0","nodeType":"VariableDeclaration","scope":377,"src":"3331:20:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string[]"},"typeName":{"baseType":{"id":288,"name":"string","nodeType":"ElementaryTypeName","src":"3331:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"id":289,"nodeType":"ArrayTypeName","src":"3331:8:0","typeDescriptions":{"typeIdentifier":"t_array$_t_string_storage_$dyn_storage_ptr","typeString":"string[]"}},"visibility":"internal"}],"id":296,"initialValue":{"arguments":[{"id":293,"name":"json","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":283,"src":"3371:4:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"hexValue":"2e726f6f745f6b65795b305d","id":294,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3377:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_d82f67100edb80050915e1ec4b565c9a8319a22efb1075e1298b7bb60101d266","typeString":"literal_string \".root_key[0]\""},"value":".root_key[0]"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_stringliteral_d82f67100edb80050915e1ec4b565c9a8319a22efb1075e1298b7bb60101d266","typeString":"literal_string \".root_key[0]\""}],"expression":{"id":291,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"3354:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":292,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"parseJsonKeys","nodeType":"MemberAccess","referencedDeclaration":27,"src":"3354:16:0","typeDescriptions":{"typeIdentifier":"t_function_external_pure$_t_string_memory_ptr_$_t_string_memory_ptr_$returns$_t_array$_t_string_memory_ptr_$dyn_memory_ptr_$","typeString":"function (string memory,string memory) pure external returns (string memory[] memory)"}},"id":295,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3354:38:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string memory[] memory"}},"nodeType":"VariableDeclarationStatement","src":"3331:61:0"},{"expression":{"arguments":[{"hexValue":"6b657973","id":300,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3414:6:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_f29790a80c4ce5f42f59892f424f9c92856c6b656c3378e2cf305b260c6f4195","typeString":"literal_string \"keys\""},"value":"keys"},{"baseExpression":{"id":301,"name":"keys","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":290,"src":"3422:4:0","typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string memory[] memory"}},"id":303,"indexExpression":{"hexValue":"30","id":302,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"3427:1:0","typeDescriptions":{"typeIdentifier":"t_rational_0_by_1","typeString":"int_const 0"},"value":"0"},"isConstant":false,"isLValue":true,"isPure":false,"lValueRequested":false,"nodeType":"IndexAccess","src":"3422:7:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"baseExpression":{"id":304,"name":"keys","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":290,"src":"3431:4:0","typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string memory[] memory"}},"id":306,"indexExpression":{"hexValue":"31","id":305,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"3436:1:0","typeDescriptions":{"typeIdentifier":"t_rational_1_by_1","typeString":"int_const 1"},"value":"1"},"isConstant":false,"isLValue":true,"isPure":false,"lValueRequested":false,"nodeType":"IndexAccess","src":"3431:7:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_f29790a80c4ce5f42f59892f424f9c92856c6b656c3378e2cf305b260c6f4195","typeString":"literal_string \"keys\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}],"expression":{"id":297,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3402:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":299,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":191,"src":"3402:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_string_memory_ptr_$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory,string memory,string memory) pure"}},"id":307,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3402:37:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":308,"nodeType":"ExpressionStatement","src":"3402:37:0"},{"expression":{"arguments":[{"hexValue":"66726f6d206f726967696e616c","id":312,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3461:15:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_77928970c8757d110f3c23e003246f49e0de890480ba9717ba659b2f56f316b2","typeString":"literal_string \"from original\""},"value":"from original"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_77928970c8757d110f3c23e003246f49e0de890480ba9717ba659b2f56f316b2","typeString":"literal_string \"from original\""}],"expression":{"id":309,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3450:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":311,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"hello","nodeType":"MemberAccess","referencedDeclaration":633,"src":"3450:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) view external"}},"id":313,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3450:27:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":314,"nodeType":"ExpressionStatement","src":"3450:27:0"},{"expression":{"arguments":[{"arguments":[{"arguments":[{"hexValue":"30783432","id":322,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"3517:4:0","typeDescriptions":{"typeIdentifier":"t_rational_66_by_1","typeString":"int_const 66"},"value":"0x42"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_66_by_1","typeString":"int_const 66"}],"id":321,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3509:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":320,"name":"uint160","nodeType":"ElementaryTypeName","src":"3509:7:0","typeDescriptions":{}}},"id":323,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3509:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":319,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3501:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":318,"name":"address","nodeType":"ElementaryTypeName","src":"3501:7:0","typeDescriptions":{}}},"id":324,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3501:22:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":315,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"3487:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":317,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"startPrank","nodeType":"MemberAccess","referencedDeclaration":32,"src":"3487:13:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_address_$returns$__$","typeString":"function (address) external"}},"id":325,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3487:37:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":326,"nodeType":"ExpressionStatement","src":"3487:37:0"},{"expression":{"arguments":[{"hexValue":"66726f6d207072616e6b2031","id":330,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3545:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_42b34abfe37a8b0add910cda7b4a379e6538fa7a1dcafce47a02bd38f6c88e2a","typeString":"literal_string \"from prank 1\""},"value":"from prank 1"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_42b34abfe37a8b0add910cda7b4a379e6538fa7a1dcafce47a02bd38f6c88e2a","typeString":"literal_string \"from prank 1\""}],"expression":{"id":327,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3534:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":329,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"hello","nodeType":"MemberAccess","referencedDeclaration":633,"src":"3534:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) view external"}},"id":331,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3534:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":332,"nodeType":"ExpressionStatement","src":"3534:26:0"},{"expression":{"arguments":[{"hexValue":"706172656e742073636f7065206d73672e73656e646572","id":336,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3582:25:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_83ec9246154d8845de47aafc5c2865c9985d2efe84472c27283879f2fbf5cc94","typeString":"literal_string \"parent scope msg.sender\""},"value":"parent scope msg.sender"},{"arguments":[{"expression":{"id":339,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"3617:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":340,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"sender","nodeType":"MemberAccess","src":"3617:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":338,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3609:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":337,"name":"address","nodeType":"ElementaryTypeName","src":"3609:7:0","typeDescriptions":{}}},"id":341,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3609:19:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_83ec9246154d8845de47aafc5c2865c9985d2efe84472c27283879f2fbf5cc94","typeString":"literal_string \"parent scope msg.sender\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":333,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3570:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":335,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":171,"src":"3570:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":342,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3570:59:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":343,"nodeType":"ExpressionStatement","src":"3570:59:0"},{"expression":{"arguments":[{"hexValue":"706172656e742073636f706520636f6e74726163742e61646472","id":347,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3651:28:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_97df66250e0b2b48f0ec8d0e01eb1b8ca012d95f1572895622aa1ea433e5570f","typeString":"literal_string \"parent scope contract.addr\""},"value":"parent scope contract.addr"},{"arguments":[{"id":350,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3689:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}],"id":349,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3681:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":348,"name":"address","nodeType":"ElementaryTypeName","src":"3681:7:0","typeDescriptions":{}}},"id":351,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3681:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_97df66250e0b2b48f0ec8d0e01eb1b8ca012d95f1572895622aa1ea433e5570f","typeString":"literal_string \"parent scope contract.addr\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":344,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3639:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":346,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":171,"src":"3639:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":352,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3639:56:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":353,"nodeType":"ExpressionStatement","src":"3639:56:0"},{"expression":{"arguments":[{"hexValue":"66726f6d207072616e6b2032","id":357,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3716:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_a38a34f8cad750a79aa097a92971f8f405b51ee9d53d25c5b14fc129ba3684bb","typeString":"literal_string \"from prank 2\""},"value":"from prank 2"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_a38a34f8cad750a79aa097a92971f8f405b51ee9d53d25c5b14fc129ba3684bb","typeString":"literal_string \"from prank 2\""}],"expression":{"id":354,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3705:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":356,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"hello","nodeType":"MemberAccess","referencedDeclaration":633,"src":"3705:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) view external"}},"id":358,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3705:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":359,"nodeType":"ExpressionStatement","src":"3705:26:0"},{"expression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":360,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"3741:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":362,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"stopPrank","nodeType":"MemberAccess","referencedDeclaration":35,"src":"3741:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$__$returns$__$","typeString":"function () external"}},"id":363,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3741:14:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":364,"nodeType":"ExpressionStatement","src":"3741:14:0"},{"expression":{"arguments":[{"hexValue":"66726f6d206f726967696e616c20616761696e","id":368,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3776:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_0c805c6579e20a9c4c8e11aeab23330910a9f2da629191dc119d1730e8ed6860","typeString":"literal_string \"from original again\""},"value":"from original again"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_0c805c6579e20a9c4c8e11aeab23330910a9f2da629191dc119d1730e8ed6860","typeString":"literal_string \"from original again\""}],"expression":{"id":365,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3765:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":367,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"hello","nodeType":"MemberAccess","referencedDeclaration":633,"src":"3765:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) view external"}},"id":369,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3765:33:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":370,"nodeType":"ExpressionStatement","src":"3765:33:0"},{"expression":{"arguments":[{"hexValue":"646f6e6521","id":374,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3821:7:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_080382d5c9e9e7c5e3d1d33f5e7422740375955180fadff167d8130e0c35f3fc","typeString":"literal_string \"done!\""},"value":"done!"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_080382d5c9e9e7c5e3d1d33f5e7422740375955180fadff167d8130e0c35f3fc","typeString":"literal_string \"done!\""}],"expression":{"id":371,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3809:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":373,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"3809:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":375,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3809:20:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":376,"nodeType":"ExpressionStatement","src":"3809:20:0"}]},"documentation":{"id":216,"nodeType":"StructuredDocumentation","src":"2804:78:0","text":"@notice example function, runs through basic cheat-codes and console logs."},"functionSelector":"c0406226","implemented":true,"kind":"function","modifiers":[],"name":"run","nameLocation":"2896:3:0","parameters":{"id":217,"nodeType":"ParameterList","parameters":[],"src":"2899:2:0"},"returnParameters":{"id":218,"nodeType":"ParameterList","parameters":[],"src":"2909:0:0"},"scope":706,"stateMutability":"nonpayable","virtual":false,"visibility":"public"},{"id":609,"nodeType":"FunctionDefinition","src":"3903:1258:0","nodes":[],"body":{"id":608,"nodeType":"Block","src":"3934:1227:0","nodes":[],"statements":[{"expression":{"arguments":[{"hexValue":"6e6f6e6365207374617274","id":385,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3956:13:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_71efc69b9a13b6bc1e9a14d766ff01c79022262c6daa6532fb5dfb14f8511a20","typeString":"literal_string \"nonce start\""},"value":"nonce start"},{"arguments":[{"arguments":[{"arguments":[{"id":392,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3999:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}],"id":391,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3991:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":390,"name":"address","nodeType":"ElementaryTypeName","src":"3991:7:0","typeDescriptions":{}}},"id":393,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3991:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":388,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"3979:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":389,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"getNonce","nodeType":"MemberAccess","referencedDeclaration":17,"src":"3979:11:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_address_$returns$_t_uint64_$","typeString":"function (address) view external returns (uint64)"}},"id":394,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3979:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint64","typeString":"uint64"}],"id":387,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3971:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint256_$","typeString":"type(uint256)"},"typeName":{"id":386,"name":"uint256","nodeType":"ElementaryTypeName","src":"3971:7:0","typeDescriptions":{}}},"id":395,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3971:35:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_71efc69b9a13b6bc1e9a14d766ff01c79022262c6daa6532fb5dfb14f8511a20","typeString":"literal_string \"nonce start\""},{"typeIdentifier":"t_uint256","typeString":"uint256"}],"expression":{"id":382,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3944:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":384,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":154,"src":"3944:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_uint256_$returns$__$","typeString":"function (string memory,uint256) pure"}},"id":396,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3944:63:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":397,"nodeType":"ExpressionStatement","src":"3944:63:0"},{"expression":{"arguments":[{"hexValue":"74657374696e672073696e676c65","id":401,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4030:16:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_b75103528423218e7569082dad569ed0d2ce7c0ac770c0812b220e2d369fe474","typeString":"literal_string \"testing single\""},"value":"testing single"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_b75103528423218e7569082dad569ed0d2ce7c0ac770c0812b220e2d369fe474","typeString":"literal_string \"testing single\""}],"expression":{"id":398,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"4018:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":400,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"4018:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":402,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4018:29:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":403,"nodeType":"ExpressionStatement","src":"4018:29:0"},{"expression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":404,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"4057:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":406,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"broadcast","nodeType":"MemberAccess","referencedDeclaration":38,"src":"4057:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$__$returns$__$","typeString":"function () external"}},"id":407,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4057:14:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":408,"nodeType":"ExpressionStatement","src":"4057:14:0"},{"expression":{"arguments":[{"hexValue":"73696e676c655f63616c6c31","id":412,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4092:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_5e1cad6d7a968cfacf2731373e1248ffb11f4886bced66a02a6de1a67ac8f777","typeString":"literal_string \"single_call1\""},"value":"single_call1"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_5e1cad6d7a968cfacf2731373e1248ffb11f4886bced66a02a6de1a67ac8f777","typeString":"literal_string \"single_call1\""}],"expression":{"id":409,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"4081:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":411,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"call1","nodeType":"MemberAccess","referencedDeclaration":648,"src":"4081:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) external"}},"id":413,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4081:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":414,"nodeType":"ExpressionStatement","src":"4081:26:0"},{"expression":{"arguments":[{"hexValue":"73696e676c655f63616c6c32","id":418,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4128:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_b37ddaf5d00ad9e6371de3fb71b91eef731fae1e86b768666380f7d44e1ada25","typeString":"literal_string \"single_call2\""},"value":"single_call2"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_b37ddaf5d00ad9e6371de3fb71b91eef731fae1e86b768666380f7d44e1ada25","typeString":"literal_string \"single_call2\""}],"expression":{"id":415,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"4117:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":417,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"call2","nodeType":"MemberAccess","referencedDeclaration":663,"src":"4117:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) external"}},"id":419,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4117:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":420,"nodeType":"ExpressionStatement","src":"4117:26:0"},{"expression":{"arguments":[{"hexValue":"74657374696e672073746172742f73746f70","id":424,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4166:20:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_778e886e3a1c3c5096aca76228832105f3f9269f362effd0e8ce3737787cb784","typeString":"literal_string \"testing start/stop\""},"value":"testing start/stop"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_778e886e3a1c3c5096aca76228832105f3f9269f362effd0e8ce3737787cb784","typeString":"literal_string \"testing start/stop\""}],"expression":{"id":421,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"4154:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":423,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"4154:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":425,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4154:33:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":426,"nodeType":"ExpressionStatement","src":"4154:33:0"},{"expression":{"arguments":[{"arguments":[{"arguments":[{"hexValue":"3078633066666565","id":434,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4231:8:0","typeDescriptions":{"typeIdentifier":"t_rational_12648430_by_1","typeString":"int_const 12648430"},"value":"0xc0ffee"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_12648430_by_1","typeString":"int_const 12648430"}],"id":433,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4223:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":432,"name":"uint160","nodeType":"ElementaryTypeName","src":"4223:7:0","typeDescriptions":{}}},"id":435,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4223:17:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":431,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4215:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":430,"name":"address","nodeType":"ElementaryTypeName","src":"4215:7:0","typeDescriptions":{}}},"id":436,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4215:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":427,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"4197:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":429,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"startBroadcast","nodeType":"MemberAccess","referencedDeclaration":48,"src":"4197:17:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_address_$returns$__$","typeString":"function (address) external"}},"id":437,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4197:45:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":438,"nodeType":"ExpressionStatement","src":"4197:45:0"},{"expression":{"arguments":[{"hexValue":"737461727473746f705f63616c6c31","id":442,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4263:17:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_2fc2682edf10ed478ee3b9a190f6b1c88bb492b300935ce44545a1613cf8f041","typeString":"literal_string \"startstop_call1\""},"value":"startstop_call1"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_2fc2682edf10ed478ee3b9a190f6b1c88bb492b300935ce44545a1613cf8f041","typeString":"literal_string \"startstop_call1\""}],"expression":{"id":439,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"4252:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":441,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"call1","nodeType":"MemberAccess","referencedDeclaration":648,"src":"4252:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) external"}},"id":443,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4252:29:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":444,"nodeType":"ExpressionStatement","src":"4252:29:0"},{"expression":{"arguments":[{"hexValue":"737461727473746f705f63616c6c32","id":448,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4302:17:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_1a6fd77f04b28bf45d6d0e2dd4c65c0bbfeba174f849e43bb67ebca1c019cda4","typeString":"literal_string \"startstop_call2\""},"value":"startstop_call2"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_1a6fd77f04b28bf45d6d0e2dd4c65c0bbfeba174f849e43bb67ebca1c019cda4","typeString":"literal_string \"startstop_call2\""}],"expression":{"id":445,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"4291:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":447,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"call2","nodeType":"MemberAccess","referencedDeclaration":663,"src":"4291:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) external"}},"id":449,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4291:29:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":450,"nodeType":"ExpressionStatement","src":"4291:29:0"},{"expression":{"arguments":[{"hexValue":"737461727473746f705f70757265","id":454,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4344:16:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_b6e9eb1efd186b1d92b54da45026aa97a178e6eaffdf9dbf9f666fc751fb0ff9","typeString":"literal_string \"startstop_pure\""},"value":"startstop_pure"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_b6e9eb1efd186b1d92b54da45026aa97a178e6eaffdf9dbf9f666fc751fb0ff9","typeString":"literal_string \"startstop_pure\""}],"expression":{"id":451,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"4330:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":453,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"callPure","nodeType":"MemberAccess","referencedDeclaration":705,"src":"4330:13:0","typeDescriptions":{"typeIdentifier":"t_function_external_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure external"}},"id":455,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4330:31:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":456,"nodeType":"ExpressionStatement","src":"4330:31:0"},{"expression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":457,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"4371:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":459,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"stopBroadcast","nodeType":"MemberAccess","referencedDeclaration":54,"src":"4371:16:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$__$returns$__$","typeString":"function () external"}},"id":460,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4371:18:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":461,"nodeType":"ExpressionStatement","src":"4371:18:0"},{"expression":{"arguments":[{"hexValue":"737461727473746f705f63616c6c33","id":465,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4410:17:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_8eb502bfdc4adda22bd960aa2ae13ce4c0ed8cc3b3791ed65e321a38cdd36f72","typeString":"literal_string \"startstop_call3\""},"value":"startstop_call3"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_8eb502bfdc4adda22bd960aa2ae13ce4c0ed8cc3b3791ed65e321a38cdd36f72","typeString":"literal_string \"startstop_call3\""}],"expression":{"id":462,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"4399:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":464,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"call1","nodeType":"MemberAccess","referencedDeclaration":648,"src":"4399:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) external"}},"id":466,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4399:29:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":467,"nodeType":"ExpressionStatement","src":"4399:29:0"},{"expression":{"arguments":[{"hexValue":"74657374696e67206e6573746564","id":471,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4451:16:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_f92f19f7a5b5b9ce341188bf4e15925f184cdb5ac135c4846ced718f259dbde5","typeString":"literal_string \"testing nested\""},"value":"testing nested"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_f92f19f7a5b5b9ce341188bf4e15925f184cdb5ac135c4846ced718f259dbde5","typeString":"literal_string \"testing nested\""}],"expression":{"id":468,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"4439:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":470,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"4439:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":472,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4439:29:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":473,"nodeType":"ExpressionStatement","src":"4439:29:0"},{"expression":{"arguments":[{"arguments":[{"arguments":[{"hexValue":"307831323334","id":481,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4512:6:0","typeDescriptions":{"typeIdentifier":"t_rational_4660_by_1","typeString":"int_const 4660"},"value":"0x1234"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_4660_by_1","typeString":"int_const 4660"}],"id":480,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4504:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":479,"name":"uint160","nodeType":"ElementaryTypeName","src":"4504:7:0","typeDescriptions":{}}},"id":482,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4504:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":478,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4496:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":477,"name":"address","nodeType":"ElementaryTypeName","src":"4496:7:0","typeDescriptions":{}}},"id":483,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4496:24:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":474,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"4478:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":476,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"startBroadcast","nodeType":"MemberAccess","referencedDeclaration":48,"src":"4478:17:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_address_$returns$__$","typeString":"function (address) external"}},"id":484,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4478:43:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":485,"nodeType":"ExpressionStatement","src":"4478:43:0"},{"expression":{"arguments":[{"hexValue":"6e6573746564","id":489,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4544:8:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_4d5b14044d78fbf0c9dd8b9c49e35f09ee5a6f5b1b3b8117b5d0e15c8dd2cb09","typeString":"literal_string \"nested\""},"value":"nested"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_4d5b14044d78fbf0c9dd8b9c49e35f09ee5a6f5b1b3b8117b5d0e15c8dd2cb09","typeString":"literal_string \"nested\""}],"expression":{"id":486,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"4531:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":488,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"nested1","nodeType":"MemberAccess","referencedDeclaration":678,"src":"4531:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) external"}},"id":490,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4531:22:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":491,"nodeType":"ExpressionStatement","src":"4531:22:0"},{"expression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":492,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"4563:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":494,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"stopBroadcast","nodeType":"MemberAccess","referencedDeclaration":54,"src":"4563:16:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$__$returns$__$","typeString":"function () external"}},"id":495,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4563:18:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":496,"nodeType":"ExpressionStatement","src":"4563:18:0"},{"expression":{"arguments":[{"hexValue":"636f6e7472616374206465706c6f796d656e74","id":500,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4604:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_aaf9be86adf9b6872d87eed3526f7c55f3c5d61f4e4dd6d55ef2fcbb8ad0bd57","typeString":"literal_string \"contract deployment\""},"value":"contract deployment"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_aaf9be86adf9b6872d87eed3526f7c55f3c5d61f4e4dd6d55ef2fcbb8ad0bd57","typeString":"literal_string \"contract deployment\""}],"expression":{"id":497,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"4592:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":499,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"4592:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":501,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4592:34:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":502,"nodeType":"ExpressionStatement","src":"4592:34:0"},{"expression":{"arguments":[{"arguments":[{"arguments":[{"hexValue":"3078313233343536","id":510,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4665:8:0","typeDescriptions":{"typeIdentifier":"t_rational_1193046_by_1","typeString":"int_const 1193046"},"value":"0x123456"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_1193046_by_1","typeString":"int_const 1193046"}],"id":509,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4657:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":508,"name":"uint160","nodeType":"ElementaryTypeName","src":"4657:7:0","typeDescriptions":{}}},"id":511,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4657:17:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":507,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4649:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":506,"name":"address","nodeType":"ElementaryTypeName","src":"4649:7:0","typeDescriptions":{}}},"id":512,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4649:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":503,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"4636:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":505,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"broadcast","nodeType":"MemberAccess","referencedDeclaration":43,"src":"4636:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_address_$returns$__$","typeString":"function (address) external"}},"id":513,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4636:40:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":514,"nodeType":"ExpressionStatement","src":"4636:40:0"},{"assignments":[517],"declarations":[{"constant":false,"id":517,"mutability":"mutable","name":"x","nameLocation":"4693:1:0","nodeType":"VariableDeclaration","scope":608,"src":"4686:8:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"},"typeName":{"id":516,"nodeType":"UserDefinedTypeName","pathNode":{"id":515,"name":"FooBar","nodeType":"IdentifierPath","referencedDeclaration":719,"src":"4686:6:0"},"referencedDeclaration":719,"src":"4686:6:0","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}},"visibility":"internal"}],"id":523,"initialValue":{"arguments":[{"hexValue":"31323334","id":521,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4708:4:0","typeDescriptions":{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"},"value":"1234"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"}],"id":520,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"NewExpression","src":"4697:10:0","typeDescriptions":{"typeIdentifier":"t_function_creation_nonpayable$_t_uint256_$returns$_t_contract$_FooBar_$719_$","typeString":"function (uint256) returns (contract FooBar)"},"typeName":{"id":519,"nodeType":"UserDefinedTypeName","pathNode":{"id":518,"name":"FooBar","nodeType":"IdentifierPath","referencedDeclaration":719,"src":"4701:6:0"},"referencedDeclaration":719,"src":"4701:6:0","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}}},"id":522,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4697:16:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}},"nodeType":"VariableDeclarationStatement","src":"4686:27:0"},{"expression":{"arguments":[{"commonType":{"typeIdentifier":"t_uint256","typeString":"uint256"},"id":529,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"leftExpression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":525,"name":"x","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":517,"src":"4731:1:0","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}},"id":526,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"foo","nodeType":"MemberAccess","referencedDeclaration":708,"src":"4731:5:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$__$returns$_t_uint256_$","typeString":"function () view external returns (uint256)"}},"id":527,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4731:7:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"nodeType":"BinaryOperation","operator":"==","rightExpression":{"hexValue":"31323334","id":528,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4742:4:0","typeDescriptions":{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"},"value":"1234"},"src":"4731:15:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bool","typeString":"bool"}],"id":524,"name":"require","nodeType":"Identifier","overloadedDeclarations":[-18,-18],"referencedDeclaration":-18,"src":"4723:7:0","typeDescriptions":{"typeIdentifier":"t_function_require_pure$_t_bool_$returns$__$","typeString":"function (bool) pure"}},"id":530,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4723:24:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":531,"nodeType":"ExpressionStatement","src":"4723:24:0"},{"expression":{"arguments":[{"hexValue":"6372656174652032","id":535,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4770:10:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_4411d6d4ffcd00382a95255a63761e69de9810e1236042a5c64948a7b6c04daa","typeString":"literal_string \"create 2\""},"value":"create 2"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_4411d6d4ffcd00382a95255a63761e69de9810e1236042a5c64948a7b6c04daa","typeString":"literal_string \"create 2\""}],"expression":{"id":532,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"4758:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":534,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"4758:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":536,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4758:23:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":537,"nodeType":"ExpressionStatement","src":"4758:23:0"},{"expression":{"arguments":[{"arguments":[{"arguments":[{"hexValue":"307863616665","id":545,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4820:6:0","typeDescriptions":{"typeIdentifier":"t_rational_51966_by_1","typeString":"int_const 51966"},"value":"0xcafe"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_51966_by_1","typeString":"int_const 51966"}],"id":544,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4812:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":543,"name":"uint160","nodeType":"ElementaryTypeName","src":"4812:7:0","typeDescriptions":{}}},"id":546,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4812:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":542,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4804:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":541,"name":"address","nodeType":"ElementaryTypeName","src":"4804:7:0","typeDescriptions":{}}},"id":547,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4804:24:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":538,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"4791:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":540,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"broadcast","nodeType":"MemberAccess","referencedDeclaration":43,"src":"4791:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_address_$returns$__$","typeString":"function (address) external"}},"id":548,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4791:38:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":549,"nodeType":"ExpressionStatement","src":"4791:38:0"},{"assignments":[552],"declarations":[{"constant":false,"id":552,"mutability":"mutable","name":"y","nameLocation":"4846:1:0","nodeType":"VariableDeclaration","scope":608,"src":"4839:8:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"},"typeName":{"id":551,"nodeType":"UserDefinedTypeName","pathNode":{"id":550,"name":"FooBar","nodeType":"IdentifierPath","referencedDeclaration":719,"src":"4839:6:0"},"referencedDeclaration":719,"src":"4839:6:0","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}},"visibility":"internal"}],"id":566,"initialValue":{"arguments":[{"hexValue":"31323334","id":564,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4889:4:0","typeDescriptions":{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"},"value":"1234"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"}],"id":555,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"NewExpression","src":"4850:10:0","typeDescriptions":{"typeIdentifier":"t_function_creation_nonpayable$_t_uint256_$returns$_t_contract$_FooBar_$719_$","typeString":"function (uint256) returns (contract FooBar)"},"typeName":{"id":554,"nodeType":"UserDefinedTypeName","pathNode":{"id":553,"name":"FooBar","nodeType":"IdentifierPath","referencedDeclaration":719,"src":"4854:6:0"},"referencedDeclaration":719,"src":"4854:6:0","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}}},"id":563,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"names":["salt"],"nodeType":"FunctionCallOptions","options":[{"arguments":[{"arguments":[{"hexValue":"3432","id":560,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4883:2:0","typeDescriptions":{"typeIdentifier":"t_rational_42_by_1","typeString":"int_const 42"},"value":"42"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_42_by_1","typeString":"int_const 42"}],"id":559,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4875:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint256_$","typeString":"type(uint256)"},"typeName":{"id":558,"name":"uint256","nodeType":"ElementaryTypeName","src":"4875:7:0","typeDescriptions":{}}},"id":561,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4875:11:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint256","typeString":"uint256"}],"id":557,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4867:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_bytes32_$","typeString":"type(bytes32)"},"typeName":{"id":556,"name":"bytes32","nodeType":"ElementaryTypeName","src":"4867:7:0","typeDescriptions":{}}},"id":562,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4867:20:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes32","typeString":"bytes32"}}],"src":"4850:38:0","typeDescriptions":{"typeIdentifier":"t_function_creation_nonpayable$_t_uint256_$returns$_t_contract$_FooBar_$719_$salt","typeString":"function (uint256) returns (contract FooBar)"}},"id":565,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4850:44:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}},"nodeType":"VariableDeclarationStatement","src":"4839:55:0"},{"expression":{"arguments":[{"commonType":{"typeIdentifier":"t_uint256","typeString":"uint256"},"id":572,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"leftExpression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":568,"name":"y","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":552,"src":"4912:1:0","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}},"id":569,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"foo","nodeType":"MemberAccess","referencedDeclaration":708,"src":"4912:5:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$__$returns$_t_uint256_$","typeString":"function () view external returns (uint256)"}},"id":570,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4912:7:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"nodeType":"BinaryOperation","operator":"==","rightExpression":{"hexValue":"31323334","id":571,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4923:4:0","typeDescriptions":{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"},"value":"1234"},"src":"4912:15:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bool","typeString":"bool"}],"id":567,"name":"require","nodeType":"Identifier","overloadedDeclarations":[-18,-18],"referencedDeclaration":-18,"src":"4904:7:0","typeDescriptions":{"typeIdentifier":"t_function_require_pure$_t_bool_$returns$__$","typeString":"function (bool) pure"}},"id":573,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4904:24:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":574,"nodeType":"ExpressionStatement","src":"4904:24:0"},{"expression":{"arguments":[{"hexValue":"646f6e6521","id":578,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4950:7:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_080382d5c9e9e7c5e3d1d33f5e7422740375955180fadff167d8130e0c35f3fc","typeString":"literal_string \"done!\""},"value":"done!"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_080382d5c9e9e7c5e3d1d33f5e7422740375955180fadff167d8130e0c35f3fc","typeString":"literal_string \"done!\""}],"expression":{"id":575,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"4938:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":577,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"4938:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":579,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4938:20:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":580,"nodeType":"ExpressionStatement","src":"4938:20:0"},{"expression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":581,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"5042:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":583,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"broadcast","nodeType":"MemberAccess","referencedDeclaration":38,"src":"5042:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$__$returns$__$","typeString":"function () external"}},"id":584,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5042:14:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":585,"nodeType":"ExpressionStatement","src":"5042:14:0"},{"expression":{"arguments":[{"hexValue":"31323334","id":589,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"5077:4:0","typeDescriptions":{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"},"value":"1234"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"}],"id":588,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"NewExpression","src":"5066:10:0","typeDescriptions":{"typeIdentifier":"t_function_creation_nonpayable$_t_uint256_$returns$_t_contract$_FooBar_$719_$","typeString":"function (uint256) returns (contract FooBar)"},"typeName":{"id":587,"nodeType":"UserDefinedTypeName","pathNode":{"id":586,"name":"FooBar","nodeType":"IdentifierPath","referencedDeclaration":719,"src":"5070:6:0"},"referencedDeclaration":719,"src":"5070:6:0","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}}},"id":590,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5066:16:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}},"id":591,"nodeType":"ExpressionStatement","src":"5066:16:0"},{"expression":{"arguments":[{"hexValue":"6e6f6e636520656e64","id":595,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"5105:11:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_fa629e6661ad2a2bdb09cf9a3a276ce0d722482ae5c2887650751be0938847e8","typeString":"literal_string \"nonce end\""},"value":"nonce end"},{"arguments":[{"arguments":[{"arguments":[{"id":602,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"5146:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}],"id":601,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"5138:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":600,"name":"address","nodeType":"ElementaryTypeName","src":"5138:7:0","typeDescriptions":{}}},"id":603,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5138:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":598,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"5126:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":599,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"getNonce","nodeType":"MemberAccess","referencedDeclaration":17,"src":"5126:11:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_address_$returns$_t_uint64_$","typeString":"function (address) view external returns (uint64)"}},"id":604,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5126:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint64","typeString":"uint64"}],"id":597,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"5118:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint256_$","typeString":"type(uint256)"},"typeName":{"id":596,"name":"uint256","nodeType":"ElementaryTypeName","src":"5118:7:0","typeDescriptions":{}}},"id":605,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5118:35:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_fa629e6661ad2a2bdb09cf9a3a276ce0d722482ae5c2887650751be0938847e8","typeString":"literal_string \"nonce end\""},{"typeIdentifier":"t_uint256","typeString":"uint256"}],"expression":{"id":592,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"5093:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":594,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":154,"src":"5093:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_uint256_$returns$__$","typeString":"function (string memory,uint256) pure"}},"id":606,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5093:61:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":607,"nodeType":"ExpressionStatement","src":"5093:61:0"}]},"documentation":{"id":379,"nodeType":"StructuredDocumentation","src":"3842:56:0","text":"@notice example function, to test vm.broadcast with."},"functionSelector":"bef03abc","implemented":true,"kind":"function","modifiers":[],"name":"runBroadcast","nameLocation":"3912:12:0","parameters":{"id":380,"nodeType":"ParameterList","parameters":[],"src":"3924:2:0"},"returnParameters":{"id":381,"nodeType":"ParameterList","parameters":[],"src":"3934:0:0"},"scope":706,"stateMutability":"nonpayable","virtual":false,"visibility":"public"},{"id":633,"nodeType":"FunctionDefinition","src":"5256:143:0","nodes":[],"body":{"id":632,"nodeType":"Block","src":"5305:94:0","nodes":[],"statements":[{"expression":{"arguments":[{"id":618,"name":"_v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":612,"src":"5327:2:0","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}],"expression":{"id":615,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"5315:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":617,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"5315:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":619,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5315:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":620,"nodeType":"ExpressionStatement","src":"5315:15:0"},{"expression":{"arguments":[{"hexValue":"68656c6c6f206d73672e73656e646572","id":624,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"5352:18:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_b3cc13bc51228b2c4c4334d82a4772908254dc0e1c512893dd16208ef13efb8e","typeString":"literal_string \"hello msg.sender\""},"value":"hello msg.sender"},{"arguments":[{"expression":{"id":627,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"5380:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":628,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"sender","nodeType":"MemberAccess","src":"5380:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":626,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"5372:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":625,"name":"address","nodeType":"ElementaryTypeName","src":"5372:7:0","typeDescriptions":{}}},"id":629,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5372:19:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_b3cc13bc51228b2c4c4334d82a4772908254dc0e1c512893dd16208ef13efb8e","typeString":"literal_string \"hello msg.sender\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":621,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"5340:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":623,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":171,"src":"5340:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":630,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5340:52:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":631,"nodeType":"ExpressionStatement","src":"5340:52:0"}]},"documentation":{"id":610,"nodeType":"StructuredDocumentation","src":"5167:84:0","text":"@notice example external function, to force a CALL, and test vm.startPrank with."},"functionSelector":"a777d0dc","implemented":true,"kind":"function","modifiers":[],"name":"hello","nameLocation":"5265:5:0","parameters":{"id":613,"nodeType":"ParameterList","parameters":[{"constant":false,"id":612,"mutability":"mutable","name":"_v","nameLocation":"5287:2:0","nodeType":"VariableDeclaration","scope":633,"src":"5271:18:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":611,"name":"string","nodeType":"ElementaryTypeName","src":"5271:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"5270:20:0"},"returnParameters":{"id":614,"nodeType":"ParameterList","parameters":[],"src":"5305:0:0"},"scope":706,"stateMutability":"view","virtual":false,"visibility":"external"},{"id":648,"nodeType":"FunctionDefinition","src":"5405:95:0","nodes":[],"body":{"id":647,"nodeType":"Block","src":"5449:51:0","nodes":[],"statements":[{"expression":{"id":639,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"UnaryOperation","operator":"++","prefix":false,"src":"5459:9:0","subExpression":{"id":638,"name":"counter","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":215,"src":"5459:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"id":640,"nodeType":"ExpressionStatement","src":"5459:9:0"},{"expression":{"arguments":[{"id":644,"name":"_v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":635,"src":"5490:2:0","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}],"expression":{"id":641,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"5478:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":643,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"5478:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":645,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5478:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":646,"nodeType":"ExpressionStatement","src":"5478:15:0"}]},"functionSelector":"7e79255d","implemented":true,"kind":"function","modifiers":[],"name":"call1","nameLocation":"5414:5:0","parameters":{"id":636,"nodeType":"ParameterList","parameters":[{"constant":false,"id":635,"mutability":"mutable","name":"_v","nameLocation":"5436:2:0","nodeType":"VariableDeclaration","scope":648,"src":"5420:18:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":634,"name":"string","nodeType":"ElementaryTypeName","src":"5420:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"5419:20:0"},"returnParameters":{"id":637,"nodeType":"ParameterList","parameters":[],"src":"5449:0:0"},"scope":706,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":663,"nodeType":"FunctionDefinition","src":"5506:95:0","nodes":[],"body":{"id":662,"nodeType":"Block","src":"5550:51:0","nodes":[],"statements":[{"expression":{"id":654,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"UnaryOperation","operator":"++","prefix":false,"src":"5560:9:0","subExpression":{"id":653,"name":"counter","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":215,"src":"5560:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"id":655,"nodeType":"ExpressionStatement","src":"5560:9:0"},{"expression":{"arguments":[{"id":659,"name":"_v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":650,"src":"5591:2:0","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}],"expression":{"id":656,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"5579:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":658,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"5579:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":660,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5579:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":661,"nodeType":"ExpressionStatement","src":"5579:15:0"}]},"functionSelector":"8d3ef7ca","implemented":true,"kind":"function","modifiers":[],"name":"call2","nameLocation":"5515:5:0","parameters":{"id":651,"nodeType":"ParameterList","parameters":[{"constant":false,"id":650,"mutability":"mutable","name":"_v","nameLocation":"5537:2:0","nodeType":"VariableDeclaration","scope":663,"src":"5521:18:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":649,"name":"string","nodeType":"ElementaryTypeName","src":"5521:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"5520:20:0"},"returnParameters":{"id":652,"nodeType":"ParameterList","parameters":[],"src":"5550:0:0"},"scope":706,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":678,"nodeType":"FunctionDefinition","src":"5607:98:0","nodes":[],"body":{"id":677,"nodeType":"Block","src":"5653:52:0","nodes":[],"statements":[{"expression":{"id":669,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"UnaryOperation","operator":"++","prefix":false,"src":"5663:9:0","subExpression":{"id":668,"name":"counter","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":215,"src":"5663:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"id":670,"nodeType":"ExpressionStatement","src":"5663:9:0"},{"expression":{"arguments":[{"id":674,"name":"_v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":665,"src":"5695:2:0","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}],"expression":{"id":671,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"5682:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":673,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"nested2","nodeType":"MemberAccess","referencedDeclaration":693,"src":"5682:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) external"}},"id":675,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5682:16:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":676,"nodeType":"ExpressionStatement","src":"5682:16:0"}]},"functionSelector":"a76ccdfa","implemented":true,"kind":"function","modifiers":[],"name":"nested1","nameLocation":"5616:7:0","parameters":{"id":666,"nodeType":"ParameterList","parameters":[{"constant":false,"id":665,"mutability":"mutable","name":"_v","nameLocation":"5640:2:0","nodeType":"VariableDeclaration","scope":678,"src":"5624:18:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":664,"name":"string","nodeType":"ElementaryTypeName","src":"5624:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"5623:20:0"},"returnParameters":{"id":667,"nodeType":"ParameterList","parameters":[],"src":"5653:0:0"},"scope":706,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":693,"nodeType":"FunctionDefinition","src":"5711:97:0","nodes":[],"body":{"id":692,"nodeType":"Block","src":"5757:51:0","nodes":[],"statements":[{"expression":{"id":684,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"UnaryOperation","operator":"++","prefix":false,"src":"5767:9:0","subExpression":{"id":683,"name":"counter","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":215,"src":"5767:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"id":685,"nodeType":"ExpressionStatement","src":"5767:9:0"},{"expression":{"arguments":[{"id":689,"name":"_v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":680,"src":"5798:2:0","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}],"expression":{"id":686,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"5786:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":688,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"5786:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":690,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5786:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":691,"nodeType":"ExpressionStatement","src":"5786:15:0"}]},"functionSelector":"dbf1282f","implemented":true,"kind":"function","modifiers":[],"name":"nested2","nameLocation":"5720:7:0","parameters":{"id":681,"nodeType":"ParameterList","parameters":[{"constant":false,"id":680,"mutability":"mutable","name":"_v","nameLocation":"5744:2:0","nodeType":"VariableDeclaration","scope":693,"src":"5728:18:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":679,"name":"string","nodeType":"ElementaryTypeName","src":"5728:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"5727:20:0"},"returnParameters":{"id":682,"nodeType":"ParameterList","parameters":[],"src":"5757:0:0"},"scope":706,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":705,"nodeType":"FunctionDefinition","src":"5814:84:0","nodes":[],"body":{"id":704,"nodeType":"Block","src":"5866:32:0","nodes":[],"statements":[{"expression":{"arguments":[{"id":701,"name":"_v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":695,"src":"5888:2:0","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}],"expression":{"id":698,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"5876:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":700,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"5876:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":702,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5876:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":703,"nodeType":"ExpressionStatement","src":"5876:15:0"}]},"functionSelector":"7f8b915c","implemented":true,"kind":"function","modifiers":[],"name":"callPure","nameLocation":"5823:8:0","parameters":{"id":696,"nodeType":"ParameterList","parameters":[{"constant":false,"id":695,"mutability":"mutable","name":"_v","nameLocation":"5848:2:0","nodeType":"VariableDeclaration","scope":705,"src":"5832:18:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":694,"name":"string","nodeType":"ElementaryTypeName","src":"5832:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"5831:20:0"},"returnParameters":{"id":697,"nodeType":"ParameterList","parameters":[],"src":"5866:0:0"},"scope":706,"stateMutability":"pure","virtual":false,"visibility":"external"}],"abstract":false,"baseContracts":[],"canonicalName":"ScriptExample","contractDependencies":[719],"contractKind":"contract","documentation":{"id":193,"nodeType":"StructuredDocumentation","src":"2415:126:0","text":"@title ScriptExample\n @notice ScriptExample is an example script. The Go forge script code tests that it can run this."},"fullyImplemented":true,"linearizedBaseContracts":[706],"name":"ScriptExample","nameLocation":"2550:13:0","scope":720,"usedErrors":[]},{"id":719,"nodeType":"ContractDefinition","src":"5902:96:0","nodes":[{"id":708,"nodeType":"VariableDeclaration","src":"5924:18:0","nodes":[],"constant":false,"functionSelector":"c2985578","mutability":"mutable","name":"foo","nameLocation":"5939:3:0","scope":719,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":707,"name":"uint256","nodeType":"ElementaryTypeName","src":"5924:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"public"},{"id":718,"nodeType":"FunctionDefinition","src":"5949:47:0","nodes":[],"body":{"id":717,"nodeType":"Block","src":"5972:24:0","nodes":[],"statements":[{"expression":{"id":715,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"leftHandSide":{"id":713,"name":"foo","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":708,"src":"5982:3:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"nodeType":"Assignment","operator":"=","rightHandSide":{"id":714,"name":"v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":710,"src":"5988:1:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"src":"5982:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"id":716,"nodeType":"ExpressionStatement","src":"5982:7:0"}]},"implemented":true,"kind":"constructor","modifiers":[],"name":"","nameLocation":"-1:-1:-1","parameters":{"id":711,"nodeType":"ParameterList","parameters":[{"constant":false,"id":710,"mutability":"mutable","name":"v","nameLocation":"5969:1:0","nodeType":"VariableDeclaration","scope":718,"src":"5961:9:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":709,"name":"uint256","nodeType":"ElementaryTypeName","src":"5961:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"}],"src":"5960:11:0"},"returnParameters":{"id":712,"nodeType":"ParameterList","parameters":[],"src":"5972:0:0"},"scope":719,"stateMutability":"nonpayable","virtual":false,"visibility":"public"}],"abstract":false,"baseContracts":[],"canonicalName":"FooBar","contractDependencies":[],"contractKind":"contract","fullyImplemented":true,"linearizedBaseContracts":[719],"name":"FooBar","nameLocation":"5911:6:0","scope":720,"usedErrors":[]}],"license":"MIT"},"id":0} +\ No newline at end of file
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+0
+
-0
+ +
+ +
+
+
diff --git OP/op-chain-ops/script/testdata/test-artifacts/ScriptExample.s.sol/Vm.json CELO/op-chain-ops/script/testdata/test-artifacts/ScriptExample.s.sol/Vm.json +index c60108b595af11952081b7575e71071c913a0eb9..34175684c5aaa5bde50b9298f889eaaf3a951d04 100644 +--- OP/op-chain-ops/script/testdata/test-artifacts/ScriptExample.s.sol/Vm.json ++++ CELO/op-chain-ops/script/testdata/test-artifacts/ScriptExample.s.sol/Vm.json +@@ -1 +1 @@ +-{"abi":[{"type":"function","name":"envOr","inputs":[{"name":"name","type":"string","internalType":"string"},{"name":"defaultValue","type":"bool","internalType":"bool"}],"outputs":[{"name":"value","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"getNonce","inputs":[{"name":"account","type":"address","internalType":"address"}],"outputs":[{"name":"nonce","type":"uint64","internalType":"uint64"}],"stateMutability":"view"},{"type":"function","name":"parseJsonKeys","inputs":[{"name":"json","type":"string","internalType":"string"},{"name":"key","type":"string","internalType":"string"}],"outputs":[{"name":"keys","type":"string[]","internalType":"string[]"}],"stateMutability":"pure"},{"type":"function","name":"startPrank","inputs":[{"name":"msgSender","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"stopPrank","inputs":[],"outputs":[],"stateMutability":"nonpayable"}],"bytecode":{"object":"0x","sourceMap":"","linkReferences":{}},"deployedBytecode":{"object":"0x","sourceMap":"","linkReferences":{}},"methodIdentifiers":{"envOr(string,bool)":"4777f3cf","getNonce(address)":"2d0335ab","parseJsonKeys(string,string)":"213e4198","startPrank(address)":"06447d56","stopPrank()":"90c5013b"},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"defaultValue\",\"type\":\"bool\"}],\"name\":\"envOr\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"value\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getNonce\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"json\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"key\",\"type\":\"string\"}],\"name\":\"parseJsonKeys\",\"outputs\":[{\"internalType\":\"string[]\",\"name\":\"keys\",\"type\":\"string[]\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"msgSender\",\"type\":\"address\"}],\"name\":\"startPrank\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stopPrank\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"scripts/ScriptExample.s.sol\":\"Vm\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[]},\"sources\":{\"scripts/ScriptExample.s.sol\":{\"keccak256\":\"0x531a2ad96c1a2c0bbfa9ab0e1195cd32551b0c10e16e7d256ce5e4c0289a8089\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://24dc6c71502c01f43fb5e113786e377c3b4cafabd5c506067d229fcdd7b037fa\",\"dweb:/ipfs/QmZ9AuxNx9Ygescfg5M4p6Abc2CCwCMZpX5xU32Fz1r4kY\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.15+commit.e14f2714"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"bool","name":"defaultValue","type":"bool"}],"stateMutability":"view","type":"function","name":"envOr","outputs":[{"internalType":"bool","name":"value","type":"bool"}]},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"stateMutability":"view","type":"function","name":"getNonce","outputs":[{"internalType":"uint64","name":"nonce","type":"uint64"}]},{"inputs":[{"internalType":"string","name":"json","type":"string"},{"internalType":"string","name":"key","type":"string"}],"stateMutability":"pure","type":"function","name":"parseJsonKeys","outputs":[{"internalType":"string[]","name":"keys","type":"string[]"}]},{"inputs":[{"internalType":"address","name":"msgSender","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"startPrank"},{"inputs":[],"stateMutability":"nonpayable","type":"function","name":"stopPrank"}],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"remappings":[],"optimizer":{"enabled":true,"runs":999999},"metadata":{"bytecodeHash":"none"},"compilationTarget":{"scripts/ScriptExample.s.sol":"Vm"},"evmVersion":"london","libraries":{}},"sources":{"scripts/ScriptExample.s.sol":{"keccak256":"0x531a2ad96c1a2c0bbfa9ab0e1195cd32551b0c10e16e7d256ce5e4c0289a8089","urls":["bzz-raw://24dc6c71502c01f43fb5e113786e377c3b4cafabd5c506067d229fcdd7b037fa","dweb:/ipfs/QmZ9AuxNx9Ygescfg5M4p6Abc2CCwCMZpX5xU32Fz1r4kY"],"license":"MIT"}},"version":1},"storageLayout":{"storage":[],"types":{}},"userdoc":{"version":1,"kind":"user"},"devdoc":{"version":1,"kind":"dev"},"ast":{"absolutePath":"scripts/ScriptExample.s.sol","id":383,"exportedSymbols":{"ScriptExample":[382],"Vm":[36],"console":[173]},"nodeType":"SourceUnit","src":"32:3736:0","nodes":[{"id":1,"nodeType":"PragmaDirective","src":"32:23:0","nodes":[],"literals":["solidity","0.8",".15"]},{"id":36,"nodeType":"ContractDefinition","src":"120:393:0","nodes":[{"id":10,"nodeType":"FunctionDefinition","src":"139:91:0","nodes":[],"functionSelector":"4777f3cf","implemented":false,"kind":"function","modifiers":[],"name":"envOr","nameLocation":"148:5:0","parameters":{"id":6,"nodeType":"ParameterList","parameters":[{"constant":false,"id":3,"mutability":"mutable","name":"name","nameLocation":"170:4:0","nodeType":"VariableDeclaration","scope":10,"src":"154:20:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":2,"name":"string","nodeType":"ElementaryTypeName","src":"154:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":5,"mutability":"mutable","name":"defaultValue","nameLocation":"181:12:0","nodeType":"VariableDeclaration","scope":10,"src":"176:17:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":4,"name":"bool","nodeType":"ElementaryTypeName","src":"176:4:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"src":"153:41:0"},"returnParameters":{"id":9,"nodeType":"ParameterList","parameters":[{"constant":false,"id":8,"mutability":"mutable","name":"value","nameLocation":"223:5:0","nodeType":"VariableDeclaration","scope":10,"src":"218:10:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":7,"name":"bool","nodeType":"ElementaryTypeName","src":"218:4:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"src":"217:12:0"},"scope":36,"stateMutability":"view","virtual":false,"visibility":"external"},{"id":17,"nodeType":"FunctionDefinition","src":"235:72:0","nodes":[],"functionSelector":"2d0335ab","implemented":false,"kind":"function","modifiers":[],"name":"getNonce","nameLocation":"244:8:0","parameters":{"id":13,"nodeType":"ParameterList","parameters":[{"constant":false,"id":12,"mutability":"mutable","name":"account","nameLocation":"261:7:0","nodeType":"VariableDeclaration","scope":17,"src":"253:15:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":11,"name":"address","nodeType":"ElementaryTypeName","src":"253:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"252:17:0"},"returnParameters":{"id":16,"nodeType":"ParameterList","parameters":[{"constant":false,"id":15,"mutability":"mutable","name":"nonce","nameLocation":"300:5:0","nodeType":"VariableDeclaration","scope":17,"src":"293:12:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"},"typeName":{"id":14,"name":"uint64","nodeType":"ElementaryTypeName","src":"293:6:0","typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}},"visibility":"internal"}],"src":"292:14:0"},"scope":36,"stateMutability":"view","virtual":false,"visibility":"external"},{"id":27,"nodeType":"FunctionDefinition","src":"312:111:0","nodes":[],"functionSelector":"213e4198","implemented":false,"kind":"function","modifiers":[],"name":"parseJsonKeys","nameLocation":"321:13:0","parameters":{"id":22,"nodeType":"ParameterList","parameters":[{"constant":false,"id":19,"mutability":"mutable","name":"json","nameLocation":"351:4:0","nodeType":"VariableDeclaration","scope":27,"src":"335:20:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":18,"name":"string","nodeType":"ElementaryTypeName","src":"335:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":21,"mutability":"mutable","name":"key","nameLocation":"373:3:0","nodeType":"VariableDeclaration","scope":27,"src":"357:19:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":20,"name":"string","nodeType":"ElementaryTypeName","src":"357:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"334:43:0"},"returnParameters":{"id":26,"nodeType":"ParameterList","parameters":[{"constant":false,"id":25,"mutability":"mutable","name":"keys","nameLocation":"417:4:0","nodeType":"VariableDeclaration","scope":27,"src":"401:20:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string[]"},"typeName":{"baseType":{"id":23,"name":"string","nodeType":"ElementaryTypeName","src":"401:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"id":24,"nodeType":"ArrayTypeName","src":"401:8:0","typeDescriptions":{"typeIdentifier":"t_array$_t_string_storage_$dyn_storage_ptr","typeString":"string[]"}},"visibility":"internal"}],"src":"400:22:0"},"scope":36,"stateMutability":"pure","virtual":false,"visibility":"external"},{"id":32,"nodeType":"FunctionDefinition","src":"428:48:0","nodes":[],"functionSelector":"06447d56","implemented":false,"kind":"function","modifiers":[],"name":"startPrank","nameLocation":"437:10:0","parameters":{"id":30,"nodeType":"ParameterList","parameters":[{"constant":false,"id":29,"mutability":"mutable","name":"msgSender","nameLocation":"456:9:0","nodeType":"VariableDeclaration","scope":32,"src":"448:17:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":28,"name":"address","nodeType":"ElementaryTypeName","src":"448:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"447:19:0"},"returnParameters":{"id":31,"nodeType":"ParameterList","parameters":[],"src":"475:0:0"},"scope":36,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":35,"nodeType":"FunctionDefinition","src":"481:30:0","nodes":[],"functionSelector":"90c5013b","implemented":false,"kind":"function","modifiers":[],"name":"stopPrank","nameLocation":"490:9:0","parameters":{"id":33,"nodeType":"ParameterList","parameters":[],"src":"499:2:0"},"returnParameters":{"id":34,"nodeType":"ParameterList","parameters":[],"src":"510:0:0"},"scope":36,"stateMutability":"nonpayable","virtual":false,"visibility":"external"}],"abstract":false,"baseContracts":[],"canonicalName":"Vm","contractDependencies":[],"contractKind":"interface","fullyImplemented":false,"linearizedBaseContracts":[36],"name":"Vm","nameLocation":"130:2:0","scope":383,"usedErrors":[]},{"id":173,"nodeType":"ContractDefinition","src":"568:1622:0","nodes":[{"id":42,"nodeType":"VariableDeclaration","src":"590:86:0","nodes":[],"constant":true,"mutability":"constant","name":"CONSOLE_ADDRESS","nameLocation":"607:15:0","scope":173,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":37,"name":"address","nodeType":"ElementaryTypeName","src":"590:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"value":{"arguments":[{"hexValue":"307830303030303030303030303030303030303036333646366537333646366336353265366336663637","id":40,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"633:42:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"value":"0x000000000000000000636F6e736F6c652e6c6f67"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":39,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"625:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":38,"name":"address","nodeType":"ElementaryTypeName","src":"625:7:0","typeDescriptions":{}}},"id":41,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"625:51:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"},{"id":59,"nodeType":"FunctionDefinition","src":"683:221:0","nodes":[],"body":{"id":58,"nodeType":"Block","src":"842:62:0","nodes":[],"statements":[{"AST":{"nodeType":"YulBlock","src":"861:37:0","statements":[{"nodeType":"YulAssignment","src":"875:13:0","value":{"name":"fnIn","nodeType":"YulIdentifier","src":"884:4:0"},"variableNames":[{"name":"fnOut","nodeType":"YulIdentifier","src":"875:5:0"}]}]},"evmVersion":"london","externalReferences":[{"declaration":48,"isOffset":false,"isSlot":false,"src":"884:4:0","valueSize":1},{"declaration":55,"isOffset":false,"isSlot":false,"src":"875:5:0","valueSize":1}],"id":57,"nodeType":"InlineAssembly","src":"852:46:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"_castLogPayloadViewToPure","nameLocation":"692:25:0","parameters":{"id":49,"nodeType":"ParameterList","parameters":[{"constant":false,"id":48,"mutability":"mutable","name":"fnIn","nameLocation":"764:4:0","nodeType":"VariableDeclaration","scope":59,"src":"727:41:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_function_internal_view$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes) view"},"typeName":{"id":47,"nodeType":"FunctionTypeName","parameterTypes":{"id":45,"nodeType":"ParameterList","parameters":[{"constant":false,"id":44,"mutability":"mutable","name":"","nameLocation":"-1:-1:-1","nodeType":"VariableDeclaration","scope":47,"src":"736:12:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":43,"name":"bytes","nodeType":"ElementaryTypeName","src":"736:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"735:14:0"},"returnParameterTypes":{"id":46,"nodeType":"ParameterList","parameters":[],"src":"764:0:0"},"src":"727:41:0","stateMutability":"view","typeDescriptions":{"typeIdentifier":"t_function_internal_view$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes) view"},"visibility":"internal"},"visibility":"internal"}],"src":"717:57:0"},"returnParameters":{"id":56,"nodeType":"ParameterList","parameters":[{"constant":false,"id":55,"mutability":"mutable","name":"fnOut","nameLocation":"835:5:0","nodeType":"VariableDeclaration","scope":59,"src":"798:42:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes) pure"},"typeName":{"id":54,"nodeType":"FunctionTypeName","parameterTypes":{"id":52,"nodeType":"ParameterList","parameters":[{"constant":false,"id":51,"mutability":"mutable","name":"","nameLocation":"-1:-1:-1","nodeType":"VariableDeclaration","scope":54,"src":"807:12:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":50,"name":"bytes","nodeType":"ElementaryTypeName","src":"807:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"806:14:0"},"returnParameterTypes":{"id":53,"nodeType":"ParameterList","parameters":[],"src":"835:0:0"},"src":"798:42:0","stateMutability":"pure","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes) pure"},"visibility":"internal"},"visibility":"internal"}],"src":"797:44:0"},"scope":173,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":71,"nodeType":"FunctionDefinition","src":"910:133:0","nodes":[],"body":{"id":70,"nodeType":"Block","src":"971:72:0","nodes":[],"statements":[{"expression":{"arguments":[{"id":67,"name":"payload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":61,"src":"1028:7:0","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"arguments":[{"id":65,"name":"_sendLogPayloadView","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":87,"src":"1007:19:0","typeDescriptions":{"typeIdentifier":"t_function_internal_view$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) view"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_function_internal_view$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) view"}],"id":64,"name":"_castLogPayloadViewToPure","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":59,"src":"981:25:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_function_internal_view$_t_bytes_memory_ptr_$returns$__$_$returns$_t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$_$","typeString":"function (function (bytes memory) view) pure returns (function (bytes memory) pure)"}},"id":66,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"981:46:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":68,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"981:55:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":69,"nodeType":"ExpressionStatement","src":"981:55:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"_sendLogPayload","nameLocation":"919:15:0","parameters":{"id":62,"nodeType":"ParameterList","parameters":[{"constant":false,"id":61,"mutability":"mutable","name":"payload","nameLocation":"948:7:0","nodeType":"VariableDeclaration","scope":71,"src":"935:20:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":60,"name":"bytes","nodeType":"ElementaryTypeName","src":"935:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"934:22:0"},"returnParameters":{"id":63,"nodeType":"ParameterList","parameters":[],"src":"971:0:0"},"scope":173,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":87,"nodeType":"FunctionDefinition","src":"1049:380:0","nodes":[],"body":{"id":86,"nodeType":"Block","src":"1113:316:0","nodes":[],"statements":[{"assignments":[77],"declarations":[{"constant":false,"id":77,"mutability":"mutable","name":"payloadLength","nameLocation":"1131:13:0","nodeType":"VariableDeclaration","scope":86,"src":"1123:21:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":76,"name":"uint256","nodeType":"ElementaryTypeName","src":"1123:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"}],"id":80,"initialValue":{"expression":{"id":78,"name":"payload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":73,"src":"1147:7:0","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}},"id":79,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"length","nodeType":"MemberAccess","src":"1147:14:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"nodeType":"VariableDeclarationStatement","src":"1123:38:0"},{"assignments":[82],"declarations":[{"constant":false,"id":82,"mutability":"mutable","name":"consoleAddress","nameLocation":"1179:14:0","nodeType":"VariableDeclaration","scope":86,"src":"1171:22:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":81,"name":"address","nodeType":"ElementaryTypeName","src":"1171:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"id":84,"initialValue":{"id":83,"name":"CONSOLE_ADDRESS","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":42,"src":"1196:15:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"nodeType":"VariableDeclarationStatement","src":"1171:40:0"},{"AST":{"nodeType":"YulBlock","src":"1273:150:0","statements":[{"nodeType":"YulVariableDeclaration","src":"1287:36:0","value":{"arguments":[{"name":"payload","nodeType":"YulIdentifier","src":"1311:7:0"},{"kind":"number","nodeType":"YulLiteral","src":"1320:2:0","type":"","value":"32"}],"functionName":{"name":"add","nodeType":"YulIdentifier","src":"1307:3:0"},"nodeType":"YulFunctionCall","src":"1307:16:0"},"variables":[{"name":"payloadStart","nodeType":"YulTypedName","src":"1291:12:0","type":""}]},{"nodeType":"YulVariableDeclaration","src":"1336:77:0","value":{"arguments":[{"arguments":[],"functionName":{"name":"gas","nodeType":"YulIdentifier","src":"1356:3:0"},"nodeType":"YulFunctionCall","src":"1356:5:0"},{"name":"consoleAddress","nodeType":"YulIdentifier","src":"1363:14:0"},{"name":"payloadStart","nodeType":"YulIdentifier","src":"1379:12:0"},{"name":"payloadLength","nodeType":"YulIdentifier","src":"1393:13:0"},{"kind":"number","nodeType":"YulLiteral","src":"1408:1:0","type":"","value":"0"},{"kind":"number","nodeType":"YulLiteral","src":"1411:1:0","type":"","value":"0"}],"functionName":{"name":"staticcall","nodeType":"YulIdentifier","src":"1345:10:0"},"nodeType":"YulFunctionCall","src":"1345:68:0"},"variables":[{"name":"r","nodeType":"YulTypedName","src":"1340:1:0","type":""}]}]},"documentation":"@solidity memory-safe-assembly","evmVersion":"london","externalReferences":[{"declaration":82,"isOffset":false,"isSlot":false,"src":"1363:14:0","valueSize":1},{"declaration":73,"isOffset":false,"isSlot":false,"src":"1311:7:0","valueSize":1},{"declaration":77,"isOffset":false,"isSlot":false,"src":"1393:13:0","valueSize":1}],"id":85,"nodeType":"InlineAssembly","src":"1264:159:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"_sendLogPayloadView","nameLocation":"1058:19:0","parameters":{"id":74,"nodeType":"ParameterList","parameters":[{"constant":false,"id":73,"mutability":"mutable","name":"payload","nameLocation":"1091:7:0","nodeType":"VariableDeclaration","scope":87,"src":"1078:20:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":72,"name":"bytes","nodeType":"ElementaryTypeName","src":"1078:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"1077:22:0"},"returnParameters":{"id":75,"nodeType":"ParameterList","parameters":[],"src":"1113:0:0"},"scope":173,"stateMutability":"view","virtual":false,"visibility":"private"},{"id":101,"nodeType":"FunctionDefinition","src":"1435:121:0","nodes":[],"body":{"id":100,"nodeType":"Block","src":"1480:76:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e6729","id":95,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"1530:13:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_41304facd9323d75b11bcdd609cb38effffdb05710f7caf0e9b16c6d9d709f50","typeString":"literal_string \"log(string)\""},"value":"log(string)"},{"id":96,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":89,"src":"1545:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_41304facd9323d75b11bcdd609cb38effffdb05710f7caf0e9b16c6d9d709f50","typeString":"literal_string \"log(string)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}],"expression":{"id":93,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"1506:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":94,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"1506:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":97,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1506:42:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":92,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":71,"src":"1490:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":98,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1490:59:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":99,"nodeType":"ExpressionStatement","src":"1490:59:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"1444:3:0","parameters":{"id":90,"nodeType":"ParameterList","parameters":[{"constant":false,"id":89,"mutability":"mutable","name":"p0","nameLocation":"1462:2:0","nodeType":"VariableDeclaration","scope":101,"src":"1448:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":88,"name":"string","nodeType":"ElementaryTypeName","src":"1448:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"1447:18:0"},"returnParameters":{"id":91,"nodeType":"ParameterList","parameters":[],"src":"1480:0:0"},"scope":173,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":118,"nodeType":"FunctionDefinition","src":"1562:139:0","nodes":[],"body":{"id":117,"nodeType":"Block","src":"1616:85:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e672c626f6f6c29","id":111,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"1666:18:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_c3b556354c088fbb43886eb83c2a04bc7089663f964d22be308197a236f5b870","typeString":"literal_string \"log(string,bool)\""},"value":"log(string,bool)"},{"id":112,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":103,"src":"1686:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":113,"name":"p1","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":105,"src":"1690:2:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_c3b556354c088fbb43886eb83c2a04bc7089663f964d22be308197a236f5b870","typeString":"literal_string \"log(string,bool)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_bool","typeString":"bool"}],"expression":{"id":109,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"1642:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":110,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"1642:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":114,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1642:51:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":108,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":71,"src":"1626:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":115,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1626:68:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":116,"nodeType":"ExpressionStatement","src":"1626:68:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"1571:3:0","parameters":{"id":106,"nodeType":"ParameterList","parameters":[{"constant":false,"id":103,"mutability":"mutable","name":"p0","nameLocation":"1589:2:0","nodeType":"VariableDeclaration","scope":118,"src":"1575:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":102,"name":"string","nodeType":"ElementaryTypeName","src":"1575:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":105,"mutability":"mutable","name":"p1","nameLocation":"1598:2:0","nodeType":"VariableDeclaration","scope":118,"src":"1593:7:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":104,"name":"bool","nodeType":"ElementaryTypeName","src":"1593:4:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"src":"1574:27:0"},"returnParameters":{"id":107,"nodeType":"ParameterList","parameters":[],"src":"1616:0:0"},"scope":173,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":135,"nodeType":"FunctionDefinition","src":"1707:145:0","nodes":[],"body":{"id":134,"nodeType":"Block","src":"1764:88:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e672c75696e7432353629","id":128,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"1814:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_b60e72ccf6d57ab53eb84d7e94a9545806ed7f93c4d5673f11a64f03471e584e","typeString":"literal_string \"log(string,uint256)\""},"value":"log(string,uint256)"},{"id":129,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":120,"src":"1837:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":130,"name":"p1","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":122,"src":"1841:2:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_b60e72ccf6d57ab53eb84d7e94a9545806ed7f93c4d5673f11a64f03471e584e","typeString":"literal_string \"log(string,uint256)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_uint256","typeString":"uint256"}],"expression":{"id":126,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"1790:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":127,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"1790:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":131,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1790:54:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":125,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":71,"src":"1774:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":132,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1774:71:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":133,"nodeType":"ExpressionStatement","src":"1774:71:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"1716:3:0","parameters":{"id":123,"nodeType":"ParameterList","parameters":[{"constant":false,"id":120,"mutability":"mutable","name":"p0","nameLocation":"1734:2:0","nodeType":"VariableDeclaration","scope":135,"src":"1720:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":119,"name":"string","nodeType":"ElementaryTypeName","src":"1720:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":122,"mutability":"mutable","name":"p1","nameLocation":"1746:2:0","nodeType":"VariableDeclaration","scope":135,"src":"1738:10:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":121,"name":"uint256","nodeType":"ElementaryTypeName","src":"1738:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"}],"src":"1719:30:0"},"returnParameters":{"id":124,"nodeType":"ParameterList","parameters":[],"src":"1764:0:0"},"scope":173,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":152,"nodeType":"FunctionDefinition","src":"1858:145:0","nodes":[],"body":{"id":151,"nodeType":"Block","src":"1915:88:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e672c6164647265737329","id":145,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"1965:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_319af333460570a1937bf195dd33445c0d0951c59127da6f1f038b9fdce3fd72","typeString":"literal_string \"log(string,address)\""},"value":"log(string,address)"},{"id":146,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":137,"src":"1988:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":147,"name":"p1","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":139,"src":"1992:2:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_319af333460570a1937bf195dd33445c0d0951c59127da6f1f038b9fdce3fd72","typeString":"literal_string \"log(string,address)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":143,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"1941:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":144,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"1941:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":148,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1941:54:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":142,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":71,"src":"1925:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":149,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1925:71:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":150,"nodeType":"ExpressionStatement","src":"1925:71:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"1867:3:0","parameters":{"id":140,"nodeType":"ParameterList","parameters":[{"constant":false,"id":137,"mutability":"mutable","name":"p0","nameLocation":"1885:2:0","nodeType":"VariableDeclaration","scope":152,"src":"1871:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":136,"name":"string","nodeType":"ElementaryTypeName","src":"1871:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":139,"mutability":"mutable","name":"p1","nameLocation":"1897:2:0","nodeType":"VariableDeclaration","scope":152,"src":"1889:10:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":138,"name":"address","nodeType":"ElementaryTypeName","src":"1889:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"1870:30:0"},"returnParameters":{"id":141,"nodeType":"ParameterList","parameters":[],"src":"1915:0:0"},"scope":173,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":172,"nodeType":"FunctionDefinition","src":"2009:179:0","nodes":[],"body":{"id":171,"nodeType":"Block","src":"2090:98:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e672c737472696e672c737472696e6729","id":164,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2140:27:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_2ced7cef693312206c21f0e92e3b54e2e16bf33db5eec350c78866822c665e1f","typeString":"literal_string \"log(string,string,string)\""},"value":"log(string,string,string)"},{"id":165,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":154,"src":"2169:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":166,"name":"p1","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":156,"src":"2173:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":167,"name":"p2","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":158,"src":"2177:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_2ced7cef693312206c21f0e92e3b54e2e16bf33db5eec350c78866822c665e1f","typeString":"literal_string \"log(string,string,string)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}],"expression":{"id":162,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"2116:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":163,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"2116:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":168,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2116:64:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":161,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":71,"src":"2100:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":169,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2100:81:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":170,"nodeType":"ExpressionStatement","src":"2100:81:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"2018:3:0","parameters":{"id":159,"nodeType":"ParameterList","parameters":[{"constant":false,"id":154,"mutability":"mutable","name":"p0","nameLocation":"2036:2:0","nodeType":"VariableDeclaration","scope":172,"src":"2022:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":153,"name":"string","nodeType":"ElementaryTypeName","src":"2022:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":156,"mutability":"mutable","name":"p1","nameLocation":"2054:2:0","nodeType":"VariableDeclaration","scope":172,"src":"2040:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":155,"name":"string","nodeType":"ElementaryTypeName","src":"2040:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":158,"mutability":"mutable","name":"p2","nameLocation":"2072:2:0","nodeType":"VariableDeclaration","scope":172,"src":"2058:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":157,"name":"string","nodeType":"ElementaryTypeName","src":"2058:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"2021:54:0"},"returnParameters":{"id":160,"nodeType":"ParameterList","parameters":[],"src":"2090:0:0"},"scope":173,"stateMutability":"pure","virtual":false,"visibility":"internal"}],"abstract":false,"baseContracts":[],"canonicalName":"console","contractDependencies":[],"contractKind":"library","fullyImplemented":true,"linearizedBaseContracts":[173],"name":"console","nameLocation":"576:7:0","scope":383,"usedErrors":[]},{"id":382,"nodeType":"ContractDefinition","src":"2318:1449:0","nodes":[{"id":188,"nodeType":"VariableDeclaration","src":"2348:94:0","nodes":[],"constant":true,"mutability":"constant","name":"VM_ADDRESS","nameLocation":"2374:10:0","scope":382,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":175,"name":"address","nodeType":"ElementaryTypeName","src":"2348:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"value":{"arguments":[{"arguments":[{"arguments":[{"arguments":[{"hexValue":"6865766d20636865617420636f6465","id":183,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2421:17:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d","typeString":"literal_string \"hevm cheat code\""},"value":"hevm cheat code"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d","typeString":"literal_string \"hevm cheat code\""}],"id":182,"name":"keccak256","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-8,"src":"2411:9:0","typeDescriptions":{"typeIdentifier":"t_function_keccak256_pure$_t_bytes_memory_ptr_$returns$_t_bytes32_$","typeString":"function (bytes memory) pure returns (bytes32)"}},"id":184,"isConstant":false,"isLValue":false,"isPure":true,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2411:28:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes32","typeString":"bytes32"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes32","typeString":"bytes32"}],"id":181,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2403:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint256_$","typeString":"type(uint256)"},"typeName":{"id":180,"name":"uint256","nodeType":"ElementaryTypeName","src":"2403:7:0","typeDescriptions":{}}},"id":185,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2403:37:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint256","typeString":"uint256"}],"id":179,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2395:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":178,"name":"uint160","nodeType":"ElementaryTypeName","src":"2395:7:0","typeDescriptions":{}}},"id":186,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2395:46:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":177,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2387:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":176,"name":"address","nodeType":"ElementaryTypeName","src":"2387:7:0","typeDescriptions":{}}},"id":187,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2387:55:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"},{"id":194,"nodeType":"VariableDeclaration","src":"2448:40:0","nodes":[],"constant":true,"mutability":"constant","name":"vm","nameLocation":"2469:2:0","scope":382,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$36","typeString":"contract Vm"},"typeName":{"id":190,"nodeType":"UserDefinedTypeName","pathNode":{"id":189,"name":"Vm","nodeType":"IdentifierPath","referencedDeclaration":36,"src":"2448:2:0"},"referencedDeclaration":36,"src":"2448:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$36","typeString":"contract Vm"}},"value":{"arguments":[{"id":192,"name":"VM_ADDRESS","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":188,"src":"2477:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":191,"name":"Vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":36,"src":"2474:2:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_Vm_$36_$","typeString":"type(contract Vm)"}},"id":193,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2474:14:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$36","typeString":"contract Vm"}},"visibility":"internal"},{"id":357,"nodeType":"FunctionDefinition","src":"2578:949:0","nodes":[],"body":{"id":356,"nodeType":"Block","src":"2600:927:0","nodes":[],"statements":[{"assignments":[199],"declarations":[{"constant":false,"id":199,"mutability":"mutable","name":"x","nameLocation":"2615:1:0","nodeType":"VariableDeclaration","scope":356,"src":"2610:6:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":198,"name":"bool","nodeType":"ElementaryTypeName","src":"2610:4:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"id":205,"initialValue":{"arguments":[{"hexValue":"4558414d504c455f424f4f4c","id":202,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2628:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_a634dae177a0e138ae7aaa2afae347412e148992e88c7aabd33ee71be146cb7f","typeString":"literal_string \"EXAMPLE_BOOL\""},"value":"EXAMPLE_BOOL"},{"hexValue":"66616c7365","id":203,"isConstant":false,"isLValue":false,"isPure":true,"kind":"bool","lValueRequested":false,"nodeType":"Literal","src":"2644:5:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"value":"false"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_a634dae177a0e138ae7aaa2afae347412e148992e88c7aabd33ee71be146cb7f","typeString":"literal_string \"EXAMPLE_BOOL\""},{"typeIdentifier":"t_bool","typeString":"bool"}],"expression":{"id":200,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":194,"src":"2619:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$36","typeString":"contract Vm"}},"id":201,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"envOr","nodeType":"MemberAccess","referencedDeclaration":10,"src":"2619:8:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$_t_bool_$returns$_t_bool_$","typeString":"function (string memory,bool) view external returns (bool)"}},"id":204,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2619:31:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"nodeType":"VariableDeclarationStatement","src":"2610:40:0"},{"expression":{"arguments":[{"hexValue":"626f6f6c2076616c75652066726f6d20656e76","id":209,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2672:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_5a607d0b5a1295325aa8901721d78ba402601bba6f62cebdd5235dd0204a590b","typeString":"literal_string \"bool value from env\""},"value":"bool value from env"},{"id":210,"name":"x","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":199,"src":"2695:1:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_5a607d0b5a1295325aa8901721d78ba402601bba6f62cebdd5235dd0204a590b","typeString":"literal_string \"bool value from env\""},{"typeIdentifier":"t_bool","typeString":"bool"}],"expression":{"id":206,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"2660:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":208,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":118,"src":"2660:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_bool_$returns$__$","typeString":"function (string memory,bool) pure"}},"id":211,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2660:37:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":212,"nodeType":"ExpressionStatement","src":"2660:37:0"},{"expression":{"arguments":[{"hexValue":"636f6e74726163742061646472","id":216,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2720:15:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_fa50728770d00fe8f6a0592f3565bbfaf063ee4077f1f5bbc003d091d33cd0c4","typeString":"literal_string \"contract addr\""},"value":"contract addr"},{"arguments":[{"id":219,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"2745:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}],"id":218,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2737:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":217,"name":"address","nodeType":"ElementaryTypeName","src":"2737:7:0","typeDescriptions":{}}},"id":220,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2737:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_fa50728770d00fe8f6a0592f3565bbfaf063ee4077f1f5bbc003d091d33cd0c4","typeString":"literal_string \"contract addr\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":213,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"2708:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":215,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":152,"src":"2708:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":221,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2708:43:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":222,"nodeType":"ExpressionStatement","src":"2708:43:0"},{"expression":{"arguments":[{"hexValue":"636f6e7472616374206e6f6e6365","id":226,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2773:16:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_3a23091615a5de8c0a35ffd8857a37e2c4e0b72f3ef8a34d6caf65efcd562e2f","typeString":"literal_string \"contract nonce\""},"value":"contract nonce"},{"arguments":[{"arguments":[{"id":231,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"2811:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}],"id":230,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2803:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":229,"name":"address","nodeType":"ElementaryTypeName","src":"2803:7:0","typeDescriptions":{}}},"id":232,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2803:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":227,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":194,"src":"2791:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$36","typeString":"contract Vm"}},"id":228,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"getNonce","nodeType":"MemberAccess","referencedDeclaration":17,"src":"2791:11:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_address_$returns$_t_uint64_$","typeString":"function (address) view external returns (uint64)"}},"id":233,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2791:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_3a23091615a5de8c0a35ffd8857a37e2c4e0b72f3ef8a34d6caf65efcd562e2f","typeString":"literal_string \"contract nonce\""},{"typeIdentifier":"t_uint64","typeString":"uint64"}],"expression":{"id":223,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"2761:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":225,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":135,"src":"2761:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_uint256_$returns$__$","typeString":"function (string memory,uint256) pure"}},"id":234,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2761:57:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":235,"nodeType":"ExpressionStatement","src":"2761:57:0"},{"expression":{"arguments":[{"hexValue":"73656e6465722061646472","id":239,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2840:13:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_8125ca2decf812b25b65606ff16dad37cb198ff0433485a7926e50feafacfc35","typeString":"literal_string \"sender addr\""},"value":"sender addr"},{"arguments":[{"expression":{"id":242,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"2863:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":243,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"sender","nodeType":"MemberAccess","src":"2863:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":241,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2855:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":240,"name":"address","nodeType":"ElementaryTypeName","src":"2855:7:0","typeDescriptions":{}}},"id":244,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2855:19:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_8125ca2decf812b25b65606ff16dad37cb198ff0433485a7926e50feafacfc35","typeString":"literal_string \"sender addr\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":236,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"2828:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":238,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":152,"src":"2828:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":245,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2828:47:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":246,"nodeType":"ExpressionStatement","src":"2828:47:0"},{"expression":{"arguments":[{"hexValue":"73656e646572206e6f6e6365","id":250,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2897:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_db7deb43f2f9e0404016de53b7e64c4976b54149581f7534daae2551e8cf4e40","typeString":"literal_string \"sender nonce\""},"value":"sender nonce"},{"arguments":[{"arguments":[{"expression":{"id":255,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"2933:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":256,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"sender","nodeType":"MemberAccess","src":"2933:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":254,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2925:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":253,"name":"address","nodeType":"ElementaryTypeName","src":"2925:7:0","typeDescriptions":{}}},"id":257,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2925:19:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":251,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":194,"src":"2913:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$36","typeString":"contract Vm"}},"id":252,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"getNonce","nodeType":"MemberAccess","referencedDeclaration":17,"src":"2913:11:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_address_$returns$_t_uint64_$","typeString":"function (address) view external returns (uint64)"}},"id":258,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2913:32:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_db7deb43f2f9e0404016de53b7e64c4976b54149581f7534daae2551e8cf4e40","typeString":"literal_string \"sender nonce\""},{"typeIdentifier":"t_uint64","typeString":"uint64"}],"expression":{"id":247,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"2885:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":249,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":135,"src":"2885:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_uint256_$returns$__$","typeString":"function (string memory,uint256) pure"}},"id":259,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2885:61:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":260,"nodeType":"ExpressionStatement","src":"2885:61:0"},{"assignments":[262],"declarations":[{"constant":false,"id":262,"mutability":"mutable","name":"json","nameLocation":"2971:4:0","nodeType":"VariableDeclaration","scope":356,"src":"2957:18:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":261,"name":"string","nodeType":"ElementaryTypeName","src":"2957:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"id":264,"initialValue":{"hexValue":"7b22726f6f745f6b6579223a205b7b2261223a20312c202262223a20327d5d7d","id":263,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2978:34:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_e95522e99766888d0261f55bd1eae5e3f3e26eaf009a16e2433eafaf0a4ecdf2","typeString":"literal_string \"{\"root_key\": [{\"a\": 1, \"b\": 2}]}\""},"value":"{\"root_key\": [{\"a\": 1, \"b\": 2}]}"},"nodeType":"VariableDeclarationStatement","src":"2957:55:0"},{"assignments":[269],"declarations":[{"constant":false,"id":269,"mutability":"mutable","name":"keys","nameLocation":"3038:4:0","nodeType":"VariableDeclaration","scope":356,"src":"3022:20:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string[]"},"typeName":{"baseType":{"id":267,"name":"string","nodeType":"ElementaryTypeName","src":"3022:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"id":268,"nodeType":"ArrayTypeName","src":"3022:8:0","typeDescriptions":{"typeIdentifier":"t_array$_t_string_storage_$dyn_storage_ptr","typeString":"string[]"}},"visibility":"internal"}],"id":275,"initialValue":{"arguments":[{"id":272,"name":"json","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":262,"src":"3062:4:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"hexValue":"2e726f6f745f6b65795b305d","id":273,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3068:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_d82f67100edb80050915e1ec4b565c9a8319a22efb1075e1298b7bb60101d266","typeString":"literal_string \".root_key[0]\""},"value":".root_key[0]"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_stringliteral_d82f67100edb80050915e1ec4b565c9a8319a22efb1075e1298b7bb60101d266","typeString":"literal_string \".root_key[0]\""}],"expression":{"id":270,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":194,"src":"3045:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$36","typeString":"contract Vm"}},"id":271,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"parseJsonKeys","nodeType":"MemberAccess","referencedDeclaration":27,"src":"3045:16:0","typeDescriptions":{"typeIdentifier":"t_function_external_pure$_t_string_memory_ptr_$_t_string_memory_ptr_$returns$_t_array$_t_string_memory_ptr_$dyn_memory_ptr_$","typeString":"function (string memory,string memory) pure external returns (string memory[] memory)"}},"id":274,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3045:38:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string memory[] memory"}},"nodeType":"VariableDeclarationStatement","src":"3022:61:0"},{"expression":{"arguments":[{"hexValue":"6b657973","id":279,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3105:6:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_f29790a80c4ce5f42f59892f424f9c92856c6b656c3378e2cf305b260c6f4195","typeString":"literal_string \"keys\""},"value":"keys"},{"baseExpression":{"id":280,"name":"keys","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":269,"src":"3113:4:0","typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string memory[] memory"}},"id":282,"indexExpression":{"hexValue":"30","id":281,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"3118:1:0","typeDescriptions":{"typeIdentifier":"t_rational_0_by_1","typeString":"int_const 0"},"value":"0"},"isConstant":false,"isLValue":true,"isPure":false,"lValueRequested":false,"nodeType":"IndexAccess","src":"3113:7:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"baseExpression":{"id":283,"name":"keys","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":269,"src":"3122:4:0","typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string memory[] memory"}},"id":285,"indexExpression":{"hexValue":"31","id":284,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"3127:1:0","typeDescriptions":{"typeIdentifier":"t_rational_1_by_1","typeString":"int_const 1"},"value":"1"},"isConstant":false,"isLValue":true,"isPure":false,"lValueRequested":false,"nodeType":"IndexAccess","src":"3122:7:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_f29790a80c4ce5f42f59892f424f9c92856c6b656c3378e2cf305b260c6f4195","typeString":"literal_string \"keys\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}],"expression":{"id":276,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"3093:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":278,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":172,"src":"3093:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_string_memory_ptr_$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory,string memory,string memory) pure"}},"id":286,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3093:37:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":287,"nodeType":"ExpressionStatement","src":"3093:37:0"},{"expression":{"arguments":[{"hexValue":"66726f6d206f726967696e616c","id":291,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3152:15:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_77928970c8757d110f3c23e003246f49e0de890480ba9717ba659b2f56f316b2","typeString":"literal_string \"from original\""},"value":"from original"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_77928970c8757d110f3c23e003246f49e0de890480ba9717ba659b2f56f316b2","typeString":"literal_string \"from original\""}],"expression":{"id":288,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3141:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}},"id":290,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"hello","nodeType":"MemberAccess","referencedDeclaration":381,"src":"3141:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) view external"}},"id":292,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3141:27:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":293,"nodeType":"ExpressionStatement","src":"3141:27:0"},{"expression":{"arguments":[{"arguments":[{"arguments":[{"hexValue":"30783432","id":301,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"3208:4:0","typeDescriptions":{"typeIdentifier":"t_rational_66_by_1","typeString":"int_const 66"},"value":"0x42"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_66_by_1","typeString":"int_const 66"}],"id":300,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3200:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":299,"name":"uint160","nodeType":"ElementaryTypeName","src":"3200:7:0","typeDescriptions":{}}},"id":302,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3200:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":298,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3192:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":297,"name":"address","nodeType":"ElementaryTypeName","src":"3192:7:0","typeDescriptions":{}}},"id":303,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3192:22:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":294,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":194,"src":"3178:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$36","typeString":"contract Vm"}},"id":296,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"startPrank","nodeType":"MemberAccess","referencedDeclaration":32,"src":"3178:13:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_address_$returns$__$","typeString":"function (address) external"}},"id":304,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3178:37:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":305,"nodeType":"ExpressionStatement","src":"3178:37:0"},{"expression":{"arguments":[{"hexValue":"66726f6d207072616e6b2031","id":309,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3236:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_42b34abfe37a8b0add910cda7b4a379e6538fa7a1dcafce47a02bd38f6c88e2a","typeString":"literal_string \"from prank 1\""},"value":"from prank 1"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_42b34abfe37a8b0add910cda7b4a379e6538fa7a1dcafce47a02bd38f6c88e2a","typeString":"literal_string \"from prank 1\""}],"expression":{"id":306,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3225:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}},"id":308,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"hello","nodeType":"MemberAccess","referencedDeclaration":381,"src":"3225:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) view external"}},"id":310,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3225:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":311,"nodeType":"ExpressionStatement","src":"3225:26:0"},{"expression":{"arguments":[{"hexValue":"706172656e742073636f7065206d73672e73656e646572","id":315,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3273:25:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_83ec9246154d8845de47aafc5c2865c9985d2efe84472c27283879f2fbf5cc94","typeString":"literal_string \"parent scope msg.sender\""},"value":"parent scope msg.sender"},{"arguments":[{"expression":{"id":318,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"3308:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":319,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"sender","nodeType":"MemberAccess","src":"3308:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":317,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3300:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":316,"name":"address","nodeType":"ElementaryTypeName","src":"3300:7:0","typeDescriptions":{}}},"id":320,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3300:19:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_83ec9246154d8845de47aafc5c2865c9985d2efe84472c27283879f2fbf5cc94","typeString":"literal_string \"parent scope msg.sender\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":312,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"3261:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":314,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":152,"src":"3261:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":321,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3261:59:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":322,"nodeType":"ExpressionStatement","src":"3261:59:0"},{"expression":{"arguments":[{"hexValue":"706172656e742073636f706520636f6e74726163742e61646472","id":326,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3342:28:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_97df66250e0b2b48f0ec8d0e01eb1b8ca012d95f1572895622aa1ea433e5570f","typeString":"literal_string \"parent scope contract.addr\""},"value":"parent scope contract.addr"},{"arguments":[{"id":329,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3380:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}],"id":328,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3372:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":327,"name":"address","nodeType":"ElementaryTypeName","src":"3372:7:0","typeDescriptions":{}}},"id":330,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3372:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_97df66250e0b2b48f0ec8d0e01eb1b8ca012d95f1572895622aa1ea433e5570f","typeString":"literal_string \"parent scope contract.addr\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":323,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"3330:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":325,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":152,"src":"3330:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":331,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3330:56:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":332,"nodeType":"ExpressionStatement","src":"3330:56:0"},{"expression":{"arguments":[{"hexValue":"66726f6d207072616e6b2032","id":336,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3407:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_a38a34f8cad750a79aa097a92971f8f405b51ee9d53d25c5b14fc129ba3684bb","typeString":"literal_string \"from prank 2\""},"value":"from prank 2"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_a38a34f8cad750a79aa097a92971f8f405b51ee9d53d25c5b14fc129ba3684bb","typeString":"literal_string \"from prank 2\""}],"expression":{"id":333,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3396:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}},"id":335,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"hello","nodeType":"MemberAccess","referencedDeclaration":381,"src":"3396:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) view external"}},"id":337,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3396:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":338,"nodeType":"ExpressionStatement","src":"3396:26:0"},{"expression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":339,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":194,"src":"3432:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$36","typeString":"contract Vm"}},"id":341,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"stopPrank","nodeType":"MemberAccess","referencedDeclaration":35,"src":"3432:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$__$returns$__$","typeString":"function () external"}},"id":342,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3432:14:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":343,"nodeType":"ExpressionStatement","src":"3432:14:0"},{"expression":{"arguments":[{"hexValue":"66726f6d206f726967696e616c20616761696e","id":347,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3467:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_0c805c6579e20a9c4c8e11aeab23330910a9f2da629191dc119d1730e8ed6860","typeString":"literal_string \"from original again\""},"value":"from original again"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_0c805c6579e20a9c4c8e11aeab23330910a9f2da629191dc119d1730e8ed6860","typeString":"literal_string \"from original again\""}],"expression":{"id":344,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3456:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}},"id":346,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"hello","nodeType":"MemberAccess","referencedDeclaration":381,"src":"3456:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) view external"}},"id":348,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3456:33:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":349,"nodeType":"ExpressionStatement","src":"3456:33:0"},{"expression":{"arguments":[{"hexValue":"646f6e6521","id":353,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3512:7:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_080382d5c9e9e7c5e3d1d33f5e7422740375955180fadff167d8130e0c35f3fc","typeString":"literal_string \"done!\""},"value":"done!"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_080382d5c9e9e7c5e3d1d33f5e7422740375955180fadff167d8130e0c35f3fc","typeString":"literal_string \"done!\""}],"expression":{"id":350,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"3500:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":352,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":101,"src":"3500:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":354,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3500:20:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":355,"nodeType":"ExpressionStatement","src":"3500:20:0"}]},"documentation":{"id":195,"nodeType":"StructuredDocumentation","src":"2495:78:0","text":"@notice example function, runs through basic cheat-codes and console logs."},"functionSelector":"c0406226","implemented":true,"kind":"function","modifiers":[],"name":"run","nameLocation":"2587:3:0","parameters":{"id":196,"nodeType":"ParameterList","parameters":[],"src":"2590:2:0"},"returnParameters":{"id":197,"nodeType":"ParameterList","parameters":[],"src":"2600:0:0"},"scope":382,"stateMutability":"nonpayable","virtual":false,"visibility":"public"},{"id":381,"nodeType":"FunctionDefinition","src":"3622:143:0","nodes":[],"body":{"id":380,"nodeType":"Block","src":"3671:94:0","nodes":[],"statements":[{"expression":{"arguments":[{"id":366,"name":"_v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":360,"src":"3693:2:0","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}],"expression":{"id":363,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"3681:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":365,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":101,"src":"3681:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":367,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3681:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":368,"nodeType":"ExpressionStatement","src":"3681:15:0"},{"expression":{"arguments":[{"hexValue":"68656c6c6f206d73672e73656e646572","id":372,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3718:18:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_b3cc13bc51228b2c4c4334d82a4772908254dc0e1c512893dd16208ef13efb8e","typeString":"literal_string \"hello msg.sender\""},"value":"hello msg.sender"},{"arguments":[{"expression":{"id":375,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"3746:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":376,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"sender","nodeType":"MemberAccess","src":"3746:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":374,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3738:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":373,"name":"address","nodeType":"ElementaryTypeName","src":"3738:7:0","typeDescriptions":{}}},"id":377,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3738:19:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_b3cc13bc51228b2c4c4334d82a4772908254dc0e1c512893dd16208ef13efb8e","typeString":"literal_string \"hello msg.sender\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":369,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"3706:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":371,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":152,"src":"3706:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":378,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3706:52:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":379,"nodeType":"ExpressionStatement","src":"3706:52:0"}]},"documentation":{"id":358,"nodeType":"StructuredDocumentation","src":"3533:84:0","text":"@notice example external function, to force a CALL, and test vm.startPrank with."},"functionSelector":"a777d0dc","implemented":true,"kind":"function","modifiers":[],"name":"hello","nameLocation":"3631:5:0","parameters":{"id":361,"nodeType":"ParameterList","parameters":[{"constant":false,"id":360,"mutability":"mutable","name":"_v","nameLocation":"3653:2:0","nodeType":"VariableDeclaration","scope":381,"src":"3637:18:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":359,"name":"string","nodeType":"ElementaryTypeName","src":"3637:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"3636:20:0"},"returnParameters":{"id":362,"nodeType":"ParameterList","parameters":[],"src":"3671:0:0"},"scope":382,"stateMutability":"view","virtual":false,"visibility":"external"}],"abstract":false,"baseContracts":[],"canonicalName":"ScriptExample","contractDependencies":[],"contractKind":"contract","documentation":{"id":174,"nodeType":"StructuredDocumentation","src":"2192:126:0","text":"@title ScriptExample\n @notice ScriptExample is an example script. The Go forge script code tests that it can run this."},"fullyImplemented":true,"linearizedBaseContracts":[382],"name":"ScriptExample","nameLocation":"2327:13:0","scope":383,"usedErrors":[]}],"license":"MIT"},"id":0} +\ No newline at end of file ++{"abi":[{"type":"function","name":"broadcast","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"broadcast","inputs":[{"name":"msgSender","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"envOr","inputs":[{"name":"name","type":"string","internalType":"string"},{"name":"defaultValue","type":"bool","internalType":"bool"}],"outputs":[{"name":"value","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"getNonce","inputs":[{"name":"account","type":"address","internalType":"address"}],"outputs":[{"name":"nonce","type":"uint64","internalType":"uint64"}],"stateMutability":"view"},{"type":"function","name":"parseJsonKeys","inputs":[{"name":"json","type":"string","internalType":"string"},{"name":"key","type":"string","internalType":"string"}],"outputs":[{"name":"keys","type":"string[]","internalType":"string[]"}],"stateMutability":"pure"},{"type":"function","name":"startBroadcast","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"startBroadcast","inputs":[{"name":"msgSender","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"startPrank","inputs":[{"name":"msgSender","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"stopBroadcast","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"stopPrank","inputs":[],"outputs":[],"stateMutability":"nonpayable"}],"bytecode":{"object":"0x","sourceMap":"","linkReferences":{}},"deployedBytecode":{"object":"0x","sourceMap":"","linkReferences":{}},"methodIdentifiers":{"broadcast()":"afc98040","broadcast(address)":"e6962cdb","envOr(string,bool)":"4777f3cf","getNonce(address)":"2d0335ab","parseJsonKeys(string,string)":"213e4198","startBroadcast()":"7fb5297f","startBroadcast(address)":"7fec2a8d","startPrank(address)":"06447d56","stopBroadcast()":"76eadd36","stopPrank()":"90c5013b"},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"broadcast\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"msgSender\",\"type\":\"address\"}],\"name\":\"broadcast\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"defaultValue\",\"type\":\"bool\"}],\"name\":\"envOr\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"value\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getNonce\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"json\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"key\",\"type\":\"string\"}],\"name\":\"parseJsonKeys\",\"outputs\":[{\"internalType\":\"string[]\",\"name\":\"keys\",\"type\":\"string[]\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"startBroadcast\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"msgSender\",\"type\":\"address\"}],\"name\":\"startBroadcast\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"msgSender\",\"type\":\"address\"}],\"name\":\"startPrank\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stopBroadcast\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"stopPrank\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"scripts/ScriptExample.s.sol\":\"Vm\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[]},\"sources\":{\"scripts/ScriptExample.s.sol\":{\"keccak256\":\"0x8d1dfa41908e7ccc3a498a2a2aa51c5275bedbb904ce32d08f8598e36f896d8d\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://5117bb7158363cae8b9dc0508d2852692fd36172f1c699ff680afbb5acebe1f3\",\"dweb:/ipfs/QmQdahJ8SPKfJ4yea5Ge9qaj5qh1TxVffhHvaWytBaL95h\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.15+commit.e14f2714"},"language":"Solidity","output":{"abi":[{"inputs":[],"stateMutability":"nonpayable","type":"function","name":"broadcast"},{"inputs":[{"internalType":"address","name":"msgSender","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"broadcast"},{"inputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"bool","name":"defaultValue","type":"bool"}],"stateMutability":"view","type":"function","name":"envOr","outputs":[{"internalType":"bool","name":"value","type":"bool"}]},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"stateMutability":"view","type":"function","name":"getNonce","outputs":[{"internalType":"uint64","name":"nonce","type":"uint64"}]},{"inputs":[{"internalType":"string","name":"json","type":"string"},{"internalType":"string","name":"key","type":"string"}],"stateMutability":"pure","type":"function","name":"parseJsonKeys","outputs":[{"internalType":"string[]","name":"keys","type":"string[]"}]},{"inputs":[],"stateMutability":"nonpayable","type":"function","name":"startBroadcast"},{"inputs":[{"internalType":"address","name":"msgSender","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"startBroadcast"},{"inputs":[{"internalType":"address","name":"msgSender","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"startPrank"},{"inputs":[],"stateMutability":"nonpayable","type":"function","name":"stopBroadcast"},{"inputs":[],"stateMutability":"nonpayable","type":"function","name":"stopPrank"}],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"remappings":[],"optimizer":{"enabled":true,"runs":999999},"metadata":{"bytecodeHash":"none"},"compilationTarget":{"scripts/ScriptExample.s.sol":"Vm"},"evmVersion":"london","libraries":{}},"sources":{"scripts/ScriptExample.s.sol":{"keccak256":"0x8d1dfa41908e7ccc3a498a2a2aa51c5275bedbb904ce32d08f8598e36f896d8d","urls":["bzz-raw://5117bb7158363cae8b9dc0508d2852692fd36172f1c699ff680afbb5acebe1f3","dweb:/ipfs/QmQdahJ8SPKfJ4yea5Ge9qaj5qh1TxVffhHvaWytBaL95h"],"license":"MIT"}},"version":1},"storageLayout":{"storage":[],"types":{}},"userdoc":{"version":1,"kind":"user"},"devdoc":{"version":1,"kind":"dev"},"ast":{"absolutePath":"scripts/ScriptExample.s.sol","id":720,"exportedSymbols":{"FooBar":[719],"ScriptExample":[706],"Vm":[55],"console":[192]},"nodeType":"SourceUnit","src":"32:5967:0","nodes":[{"id":1,"nodeType":"PragmaDirective","src":"32:23:0","nodes":[],"literals":["solidity","0.8",".15"]},{"id":55,"nodeType":"ContractDefinition","src":"120:616:0","nodes":[{"id":10,"nodeType":"FunctionDefinition","src":"139:91:0","nodes":[],"functionSelector":"4777f3cf","implemented":false,"kind":"function","modifiers":[],"name":"envOr","nameLocation":"148:5:0","parameters":{"id":6,"nodeType":"ParameterList","parameters":[{"constant":false,"id":3,"mutability":"mutable","name":"name","nameLocation":"170:4:0","nodeType":"VariableDeclaration","scope":10,"src":"154:20:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":2,"name":"string","nodeType":"ElementaryTypeName","src":"154:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":5,"mutability":"mutable","name":"defaultValue","nameLocation":"181:12:0","nodeType":"VariableDeclaration","scope":10,"src":"176:17:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":4,"name":"bool","nodeType":"ElementaryTypeName","src":"176:4:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"src":"153:41:0"},"returnParameters":{"id":9,"nodeType":"ParameterList","parameters":[{"constant":false,"id":8,"mutability":"mutable","name":"value","nameLocation":"223:5:0","nodeType":"VariableDeclaration","scope":10,"src":"218:10:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":7,"name":"bool","nodeType":"ElementaryTypeName","src":"218:4:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"src":"217:12:0"},"scope":55,"stateMutability":"view","virtual":false,"visibility":"external"},{"id":17,"nodeType":"FunctionDefinition","src":"235:72:0","nodes":[],"functionSelector":"2d0335ab","implemented":false,"kind":"function","modifiers":[],"name":"getNonce","nameLocation":"244:8:0","parameters":{"id":13,"nodeType":"ParameterList","parameters":[{"constant":false,"id":12,"mutability":"mutable","name":"account","nameLocation":"261:7:0","nodeType":"VariableDeclaration","scope":17,"src":"253:15:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":11,"name":"address","nodeType":"ElementaryTypeName","src":"253:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"252:17:0"},"returnParameters":{"id":16,"nodeType":"ParameterList","parameters":[{"constant":false,"id":15,"mutability":"mutable","name":"nonce","nameLocation":"300:5:0","nodeType":"VariableDeclaration","scope":17,"src":"293:12:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"},"typeName":{"id":14,"name":"uint64","nodeType":"ElementaryTypeName","src":"293:6:0","typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}},"visibility":"internal"}],"src":"292:14:0"},"scope":55,"stateMutability":"view","virtual":false,"visibility":"external"},{"id":27,"nodeType":"FunctionDefinition","src":"312:111:0","nodes":[],"functionSelector":"213e4198","implemented":false,"kind":"function","modifiers":[],"name":"parseJsonKeys","nameLocation":"321:13:0","parameters":{"id":22,"nodeType":"ParameterList","parameters":[{"constant":false,"id":19,"mutability":"mutable","name":"json","nameLocation":"351:4:0","nodeType":"VariableDeclaration","scope":27,"src":"335:20:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":18,"name":"string","nodeType":"ElementaryTypeName","src":"335:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":21,"mutability":"mutable","name":"key","nameLocation":"373:3:0","nodeType":"VariableDeclaration","scope":27,"src":"357:19:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":20,"name":"string","nodeType":"ElementaryTypeName","src":"357:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"334:43:0"},"returnParameters":{"id":26,"nodeType":"ParameterList","parameters":[{"constant":false,"id":25,"mutability":"mutable","name":"keys","nameLocation":"417:4:0","nodeType":"VariableDeclaration","scope":27,"src":"401:20:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string[]"},"typeName":{"baseType":{"id":23,"name":"string","nodeType":"ElementaryTypeName","src":"401:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"id":24,"nodeType":"ArrayTypeName","src":"401:8:0","typeDescriptions":{"typeIdentifier":"t_array$_t_string_storage_$dyn_storage_ptr","typeString":"string[]"}},"visibility":"internal"}],"src":"400:22:0"},"scope":55,"stateMutability":"pure","virtual":false,"visibility":"external"},{"id":32,"nodeType":"FunctionDefinition","src":"428:48:0","nodes":[],"functionSelector":"06447d56","implemented":false,"kind":"function","modifiers":[],"name":"startPrank","nameLocation":"437:10:0","parameters":{"id":30,"nodeType":"ParameterList","parameters":[{"constant":false,"id":29,"mutability":"mutable","name":"msgSender","nameLocation":"456:9:0","nodeType":"VariableDeclaration","scope":32,"src":"448:17:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":28,"name":"address","nodeType":"ElementaryTypeName","src":"448:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"447:19:0"},"returnParameters":{"id":31,"nodeType":"ParameterList","parameters":[],"src":"475:0:0"},"scope":55,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":35,"nodeType":"FunctionDefinition","src":"481:30:0","nodes":[],"functionSelector":"90c5013b","implemented":false,"kind":"function","modifiers":[],"name":"stopPrank","nameLocation":"490:9:0","parameters":{"id":33,"nodeType":"ParameterList","parameters":[],"src":"499:2:0"},"returnParameters":{"id":34,"nodeType":"ParameterList","parameters":[],"src":"510:0:0"},"scope":55,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":38,"nodeType":"FunctionDefinition","src":"516:30:0","nodes":[],"functionSelector":"afc98040","implemented":false,"kind":"function","modifiers":[],"name":"broadcast","nameLocation":"525:9:0","parameters":{"id":36,"nodeType":"ParameterList","parameters":[],"src":"534:2:0"},"returnParameters":{"id":37,"nodeType":"ParameterList","parameters":[],"src":"545:0:0"},"scope":55,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":43,"nodeType":"FunctionDefinition","src":"551:47:0","nodes":[],"functionSelector":"e6962cdb","implemented":false,"kind":"function","modifiers":[],"name":"broadcast","nameLocation":"560:9:0","parameters":{"id":41,"nodeType":"ParameterList","parameters":[{"constant":false,"id":40,"mutability":"mutable","name":"msgSender","nameLocation":"578:9:0","nodeType":"VariableDeclaration","scope":43,"src":"570:17:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":39,"name":"address","nodeType":"ElementaryTypeName","src":"570:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"569:19:0"},"returnParameters":{"id":42,"nodeType":"ParameterList","parameters":[],"src":"597:0:0"},"scope":55,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":48,"nodeType":"FunctionDefinition","src":"603:52:0","nodes":[],"functionSelector":"7fec2a8d","implemented":false,"kind":"function","modifiers":[],"name":"startBroadcast","nameLocation":"612:14:0","parameters":{"id":46,"nodeType":"ParameterList","parameters":[{"constant":false,"id":45,"mutability":"mutable","name":"msgSender","nameLocation":"635:9:0","nodeType":"VariableDeclaration","scope":48,"src":"627:17:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":44,"name":"address","nodeType":"ElementaryTypeName","src":"627:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"626:19:0"},"returnParameters":{"id":47,"nodeType":"ParameterList","parameters":[],"src":"654:0:0"},"scope":55,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":51,"nodeType":"FunctionDefinition","src":"660:35:0","nodes":[],"functionSelector":"7fb5297f","implemented":false,"kind":"function","modifiers":[],"name":"startBroadcast","nameLocation":"669:14:0","parameters":{"id":49,"nodeType":"ParameterList","parameters":[],"src":"683:2:0"},"returnParameters":{"id":50,"nodeType":"ParameterList","parameters":[],"src":"694:0:0"},"scope":55,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":54,"nodeType":"FunctionDefinition","src":"700:34:0","nodes":[],"functionSelector":"76eadd36","implemented":false,"kind":"function","modifiers":[],"name":"stopBroadcast","nameLocation":"709:13:0","parameters":{"id":52,"nodeType":"ParameterList","parameters":[],"src":"722:2:0"},"returnParameters":{"id":53,"nodeType":"ParameterList","parameters":[],"src":"733:0:0"},"scope":55,"stateMutability":"nonpayable","virtual":false,"visibility":"external"}],"abstract":false,"baseContracts":[],"canonicalName":"Vm","contractDependencies":[],"contractKind":"interface","fullyImplemented":false,"linearizedBaseContracts":[55],"name":"Vm","nameLocation":"130:2:0","scope":720,"usedErrors":[]},{"id":192,"nodeType":"ContractDefinition","src":"791:1622:0","nodes":[{"id":61,"nodeType":"VariableDeclaration","src":"813:86:0","nodes":[],"constant":true,"mutability":"constant","name":"CONSOLE_ADDRESS","nameLocation":"830:15:0","scope":192,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":56,"name":"address","nodeType":"ElementaryTypeName","src":"813:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"value":{"arguments":[{"hexValue":"307830303030303030303030303030303030303036333646366537333646366336353265366336663637","id":59,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"856:42:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"value":"0x000000000000000000636F6e736F6c652e6c6f67"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":58,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"848:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":57,"name":"address","nodeType":"ElementaryTypeName","src":"848:7:0","typeDescriptions":{}}},"id":60,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"848:51:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"},{"id":78,"nodeType":"FunctionDefinition","src":"906:221:0","nodes":[],"body":{"id":77,"nodeType":"Block","src":"1065:62:0","nodes":[],"statements":[{"AST":{"nodeType":"YulBlock","src":"1084:37:0","statements":[{"nodeType":"YulAssignment","src":"1098:13:0","value":{"name":"fnIn","nodeType":"YulIdentifier","src":"1107:4:0"},"variableNames":[{"name":"fnOut","nodeType":"YulIdentifier","src":"1098:5:0"}]}]},"evmVersion":"london","externalReferences":[{"declaration":67,"isOffset":false,"isSlot":false,"src":"1107:4:0","valueSize":1},{"declaration":74,"isOffset":false,"isSlot":false,"src":"1098:5:0","valueSize":1}],"id":76,"nodeType":"InlineAssembly","src":"1075:46:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"_castLogPayloadViewToPure","nameLocation":"915:25:0","parameters":{"id":68,"nodeType":"ParameterList","parameters":[{"constant":false,"id":67,"mutability":"mutable","name":"fnIn","nameLocation":"987:4:0","nodeType":"VariableDeclaration","scope":78,"src":"950:41:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_function_internal_view$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes) view"},"typeName":{"id":66,"nodeType":"FunctionTypeName","parameterTypes":{"id":64,"nodeType":"ParameterList","parameters":[{"constant":false,"id":63,"mutability":"mutable","name":"","nameLocation":"-1:-1:-1","nodeType":"VariableDeclaration","scope":66,"src":"959:12:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":62,"name":"bytes","nodeType":"ElementaryTypeName","src":"959:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"958:14:0"},"returnParameterTypes":{"id":65,"nodeType":"ParameterList","parameters":[],"src":"987:0:0"},"src":"950:41:0","stateMutability":"view","typeDescriptions":{"typeIdentifier":"t_function_internal_view$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes) view"},"visibility":"internal"},"visibility":"internal"}],"src":"940:57:0"},"returnParameters":{"id":75,"nodeType":"ParameterList","parameters":[{"constant":false,"id":74,"mutability":"mutable","name":"fnOut","nameLocation":"1058:5:0","nodeType":"VariableDeclaration","scope":78,"src":"1021:42:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes) pure"},"typeName":{"id":73,"nodeType":"FunctionTypeName","parameterTypes":{"id":71,"nodeType":"ParameterList","parameters":[{"constant":false,"id":70,"mutability":"mutable","name":"","nameLocation":"-1:-1:-1","nodeType":"VariableDeclaration","scope":73,"src":"1030:12:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":69,"name":"bytes","nodeType":"ElementaryTypeName","src":"1030:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"1029:14:0"},"returnParameterTypes":{"id":72,"nodeType":"ParameterList","parameters":[],"src":"1058:0:0"},"src":"1021:42:0","stateMutability":"pure","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes) pure"},"visibility":"internal"},"visibility":"internal"}],"src":"1020:44:0"},"scope":192,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":90,"nodeType":"FunctionDefinition","src":"1133:133:0","nodes":[],"body":{"id":89,"nodeType":"Block","src":"1194:72:0","nodes":[],"statements":[{"expression":{"arguments":[{"id":86,"name":"payload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":80,"src":"1251:7:0","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"arguments":[{"id":84,"name":"_sendLogPayloadView","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":106,"src":"1230:19:0","typeDescriptions":{"typeIdentifier":"t_function_internal_view$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) view"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_function_internal_view$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) view"}],"id":83,"name":"_castLogPayloadViewToPure","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":78,"src":"1204:25:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_function_internal_view$_t_bytes_memory_ptr_$returns$__$_$returns$_t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$_$","typeString":"function (function (bytes memory) view) pure returns (function (bytes memory) pure)"}},"id":85,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1204:46:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":87,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1204:55:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":88,"nodeType":"ExpressionStatement","src":"1204:55:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"_sendLogPayload","nameLocation":"1142:15:0","parameters":{"id":81,"nodeType":"ParameterList","parameters":[{"constant":false,"id":80,"mutability":"mutable","name":"payload","nameLocation":"1171:7:0","nodeType":"VariableDeclaration","scope":90,"src":"1158:20:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":79,"name":"bytes","nodeType":"ElementaryTypeName","src":"1158:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"1157:22:0"},"returnParameters":{"id":82,"nodeType":"ParameterList","parameters":[],"src":"1194:0:0"},"scope":192,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":106,"nodeType":"FunctionDefinition","src":"1272:380:0","nodes":[],"body":{"id":105,"nodeType":"Block","src":"1336:316:0","nodes":[],"statements":[{"assignments":[96],"declarations":[{"constant":false,"id":96,"mutability":"mutable","name":"payloadLength","nameLocation":"1354:13:0","nodeType":"VariableDeclaration","scope":105,"src":"1346:21:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":95,"name":"uint256","nodeType":"ElementaryTypeName","src":"1346:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"}],"id":99,"initialValue":{"expression":{"id":97,"name":"payload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":92,"src":"1370:7:0","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}},"id":98,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"length","nodeType":"MemberAccess","src":"1370:14:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"nodeType":"VariableDeclarationStatement","src":"1346:38:0"},{"assignments":[101],"declarations":[{"constant":false,"id":101,"mutability":"mutable","name":"consoleAddress","nameLocation":"1402:14:0","nodeType":"VariableDeclaration","scope":105,"src":"1394:22:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":100,"name":"address","nodeType":"ElementaryTypeName","src":"1394:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"id":103,"initialValue":{"id":102,"name":"CONSOLE_ADDRESS","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":61,"src":"1419:15:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"nodeType":"VariableDeclarationStatement","src":"1394:40:0"},{"AST":{"nodeType":"YulBlock","src":"1496:150:0","statements":[{"nodeType":"YulVariableDeclaration","src":"1510:36:0","value":{"arguments":[{"name":"payload","nodeType":"YulIdentifier","src":"1534:7:0"},{"kind":"number","nodeType":"YulLiteral","src":"1543:2:0","type":"","value":"32"}],"functionName":{"name":"add","nodeType":"YulIdentifier","src":"1530:3:0"},"nodeType":"YulFunctionCall","src":"1530:16:0"},"variables":[{"name":"payloadStart","nodeType":"YulTypedName","src":"1514:12:0","type":""}]},{"nodeType":"YulVariableDeclaration","src":"1559:77:0","value":{"arguments":[{"arguments":[],"functionName":{"name":"gas","nodeType":"YulIdentifier","src":"1579:3:0"},"nodeType":"YulFunctionCall","src":"1579:5:0"},{"name":"consoleAddress","nodeType":"YulIdentifier","src":"1586:14:0"},{"name":"payloadStart","nodeType":"YulIdentifier","src":"1602:12:0"},{"name":"payloadLength","nodeType":"YulIdentifier","src":"1616:13:0"},{"kind":"number","nodeType":"YulLiteral","src":"1631:1:0","type":"","value":"0"},{"kind":"number","nodeType":"YulLiteral","src":"1634:1:0","type":"","value":"0"}],"functionName":{"name":"staticcall","nodeType":"YulIdentifier","src":"1568:10:0"},"nodeType":"YulFunctionCall","src":"1568:68:0"},"variables":[{"name":"r","nodeType":"YulTypedName","src":"1563:1:0","type":""}]}]},"documentation":"@solidity memory-safe-assembly","evmVersion":"london","externalReferences":[{"declaration":101,"isOffset":false,"isSlot":false,"src":"1586:14:0","valueSize":1},{"declaration":92,"isOffset":false,"isSlot":false,"src":"1534:7:0","valueSize":1},{"declaration":96,"isOffset":false,"isSlot":false,"src":"1616:13:0","valueSize":1}],"id":104,"nodeType":"InlineAssembly","src":"1487:159:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"_sendLogPayloadView","nameLocation":"1281:19:0","parameters":{"id":93,"nodeType":"ParameterList","parameters":[{"constant":false,"id":92,"mutability":"mutable","name":"payload","nameLocation":"1314:7:0","nodeType":"VariableDeclaration","scope":106,"src":"1301:20:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":91,"name":"bytes","nodeType":"ElementaryTypeName","src":"1301:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"1300:22:0"},"returnParameters":{"id":94,"nodeType":"ParameterList","parameters":[],"src":"1336:0:0"},"scope":192,"stateMutability":"view","virtual":false,"visibility":"private"},{"id":120,"nodeType":"FunctionDefinition","src":"1658:121:0","nodes":[],"body":{"id":119,"nodeType":"Block","src":"1703:76:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e6729","id":114,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"1753:13:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_41304facd9323d75b11bcdd609cb38effffdb05710f7caf0e9b16c6d9d709f50","typeString":"literal_string \"log(string)\""},"value":"log(string)"},{"id":115,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":108,"src":"1768:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_41304facd9323d75b11bcdd609cb38effffdb05710f7caf0e9b16c6d9d709f50","typeString":"literal_string \"log(string)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}],"expression":{"id":112,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"1729:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":113,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"1729:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":116,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1729:42:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":111,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":90,"src":"1713:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":117,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1713:59:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":118,"nodeType":"ExpressionStatement","src":"1713:59:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"1667:3:0","parameters":{"id":109,"nodeType":"ParameterList","parameters":[{"constant":false,"id":108,"mutability":"mutable","name":"p0","nameLocation":"1685:2:0","nodeType":"VariableDeclaration","scope":120,"src":"1671:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":107,"name":"string","nodeType":"ElementaryTypeName","src":"1671:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"1670:18:0"},"returnParameters":{"id":110,"nodeType":"ParameterList","parameters":[],"src":"1703:0:0"},"scope":192,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":137,"nodeType":"FunctionDefinition","src":"1785:139:0","nodes":[],"body":{"id":136,"nodeType":"Block","src":"1839:85:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e672c626f6f6c29","id":130,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"1889:18:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_c3b556354c088fbb43886eb83c2a04bc7089663f964d22be308197a236f5b870","typeString":"literal_string \"log(string,bool)\""},"value":"log(string,bool)"},{"id":131,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":122,"src":"1909:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":132,"name":"p1","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":124,"src":"1913:2:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_c3b556354c088fbb43886eb83c2a04bc7089663f964d22be308197a236f5b870","typeString":"literal_string \"log(string,bool)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_bool","typeString":"bool"}],"expression":{"id":128,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"1865:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":129,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"1865:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":133,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1865:51:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":127,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":90,"src":"1849:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":134,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1849:68:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":135,"nodeType":"ExpressionStatement","src":"1849:68:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"1794:3:0","parameters":{"id":125,"nodeType":"ParameterList","parameters":[{"constant":false,"id":122,"mutability":"mutable","name":"p0","nameLocation":"1812:2:0","nodeType":"VariableDeclaration","scope":137,"src":"1798:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":121,"name":"string","nodeType":"ElementaryTypeName","src":"1798:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":124,"mutability":"mutable","name":"p1","nameLocation":"1821:2:0","nodeType":"VariableDeclaration","scope":137,"src":"1816:7:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":123,"name":"bool","nodeType":"ElementaryTypeName","src":"1816:4:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"src":"1797:27:0"},"returnParameters":{"id":126,"nodeType":"ParameterList","parameters":[],"src":"1839:0:0"},"scope":192,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":154,"nodeType":"FunctionDefinition","src":"1930:145:0","nodes":[],"body":{"id":153,"nodeType":"Block","src":"1987:88:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e672c75696e7432353629","id":147,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2037:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_b60e72ccf6d57ab53eb84d7e94a9545806ed7f93c4d5673f11a64f03471e584e","typeString":"literal_string \"log(string,uint256)\""},"value":"log(string,uint256)"},{"id":148,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":139,"src":"2060:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":149,"name":"p1","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":141,"src":"2064:2:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_b60e72ccf6d57ab53eb84d7e94a9545806ed7f93c4d5673f11a64f03471e584e","typeString":"literal_string \"log(string,uint256)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_uint256","typeString":"uint256"}],"expression":{"id":145,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"2013:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":146,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"2013:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":150,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2013:54:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":144,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":90,"src":"1997:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":151,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1997:71:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":152,"nodeType":"ExpressionStatement","src":"1997:71:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"1939:3:0","parameters":{"id":142,"nodeType":"ParameterList","parameters":[{"constant":false,"id":139,"mutability":"mutable","name":"p0","nameLocation":"1957:2:0","nodeType":"VariableDeclaration","scope":154,"src":"1943:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":138,"name":"string","nodeType":"ElementaryTypeName","src":"1943:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":141,"mutability":"mutable","name":"p1","nameLocation":"1969:2:0","nodeType":"VariableDeclaration","scope":154,"src":"1961:10:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":140,"name":"uint256","nodeType":"ElementaryTypeName","src":"1961:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"}],"src":"1942:30:0"},"returnParameters":{"id":143,"nodeType":"ParameterList","parameters":[],"src":"1987:0:0"},"scope":192,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":171,"nodeType":"FunctionDefinition","src":"2081:145:0","nodes":[],"body":{"id":170,"nodeType":"Block","src":"2138:88:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e672c6164647265737329","id":164,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2188:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_319af333460570a1937bf195dd33445c0d0951c59127da6f1f038b9fdce3fd72","typeString":"literal_string \"log(string,address)\""},"value":"log(string,address)"},{"id":165,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":156,"src":"2211:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":166,"name":"p1","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":158,"src":"2215:2:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_319af333460570a1937bf195dd33445c0d0951c59127da6f1f038b9fdce3fd72","typeString":"literal_string \"log(string,address)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":162,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"2164:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":163,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"2164:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":167,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2164:54:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":161,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":90,"src":"2148:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":168,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2148:71:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":169,"nodeType":"ExpressionStatement","src":"2148:71:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"2090:3:0","parameters":{"id":159,"nodeType":"ParameterList","parameters":[{"constant":false,"id":156,"mutability":"mutable","name":"p0","nameLocation":"2108:2:0","nodeType":"VariableDeclaration","scope":171,"src":"2094:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":155,"name":"string","nodeType":"ElementaryTypeName","src":"2094:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":158,"mutability":"mutable","name":"p1","nameLocation":"2120:2:0","nodeType":"VariableDeclaration","scope":171,"src":"2112:10:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":157,"name":"address","nodeType":"ElementaryTypeName","src":"2112:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"2093:30:0"},"returnParameters":{"id":160,"nodeType":"ParameterList","parameters":[],"src":"2138:0:0"},"scope":192,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":191,"nodeType":"FunctionDefinition","src":"2232:179:0","nodes":[],"body":{"id":190,"nodeType":"Block","src":"2313:98:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e672c737472696e672c737472696e6729","id":183,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2363:27:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_2ced7cef693312206c21f0e92e3b54e2e16bf33db5eec350c78866822c665e1f","typeString":"literal_string \"log(string,string,string)\""},"value":"log(string,string,string)"},{"id":184,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"2392:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":185,"name":"p1","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":175,"src":"2396:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":186,"name":"p2","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":177,"src":"2400:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_2ced7cef693312206c21f0e92e3b54e2e16bf33db5eec350c78866822c665e1f","typeString":"literal_string \"log(string,string,string)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}],"expression":{"id":181,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"2339:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":182,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"2339:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":187,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2339:64:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":180,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":90,"src":"2323:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":188,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2323:81:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":189,"nodeType":"ExpressionStatement","src":"2323:81:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"2241:3:0","parameters":{"id":178,"nodeType":"ParameterList","parameters":[{"constant":false,"id":173,"mutability":"mutable","name":"p0","nameLocation":"2259:2:0","nodeType":"VariableDeclaration","scope":191,"src":"2245:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":172,"name":"string","nodeType":"ElementaryTypeName","src":"2245:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":175,"mutability":"mutable","name":"p1","nameLocation":"2277:2:0","nodeType":"VariableDeclaration","scope":191,"src":"2263:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":174,"name":"string","nodeType":"ElementaryTypeName","src":"2263:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":177,"mutability":"mutable","name":"p2","nameLocation":"2295:2:0","nodeType":"VariableDeclaration","scope":191,"src":"2281:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":176,"name":"string","nodeType":"ElementaryTypeName","src":"2281:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"2244:54:0"},"returnParameters":{"id":179,"nodeType":"ParameterList","parameters":[],"src":"2313:0:0"},"scope":192,"stateMutability":"pure","virtual":false,"visibility":"internal"}],"abstract":false,"baseContracts":[],"canonicalName":"console","contractDependencies":[],"contractKind":"library","fullyImplemented":true,"linearizedBaseContracts":[192],"name":"console","nameLocation":"799:7:0","scope":720,"usedErrors":[]},{"id":706,"nodeType":"ContractDefinition","src":"2541:3359:0","nodes":[{"id":207,"nodeType":"VariableDeclaration","src":"2571:94:0","nodes":[],"constant":true,"mutability":"constant","name":"VM_ADDRESS","nameLocation":"2597:10:0","scope":706,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":194,"name":"address","nodeType":"ElementaryTypeName","src":"2571:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"value":{"arguments":[{"arguments":[{"arguments":[{"arguments":[{"hexValue":"6865766d20636865617420636f6465","id":202,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2644:17:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d","typeString":"literal_string \"hevm cheat code\""},"value":"hevm cheat code"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d","typeString":"literal_string \"hevm cheat code\""}],"id":201,"name":"keccak256","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-8,"src":"2634:9:0","typeDescriptions":{"typeIdentifier":"t_function_keccak256_pure$_t_bytes_memory_ptr_$returns$_t_bytes32_$","typeString":"function (bytes memory) pure returns (bytes32)"}},"id":203,"isConstant":false,"isLValue":false,"isPure":true,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2634:28:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes32","typeString":"bytes32"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes32","typeString":"bytes32"}],"id":200,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2626:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint256_$","typeString":"type(uint256)"},"typeName":{"id":199,"name":"uint256","nodeType":"ElementaryTypeName","src":"2626:7:0","typeDescriptions":{}}},"id":204,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2626:37:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint256","typeString":"uint256"}],"id":198,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2618:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":197,"name":"uint160","nodeType":"ElementaryTypeName","src":"2618:7:0","typeDescriptions":{}}},"id":205,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2618:46:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":196,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2610:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":195,"name":"address","nodeType":"ElementaryTypeName","src":"2610:7:0","typeDescriptions":{}}},"id":206,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2610:55:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"},{"id":213,"nodeType":"VariableDeclaration","src":"2671:40:0","nodes":[],"constant":true,"mutability":"constant","name":"vm","nameLocation":"2692:2:0","scope":706,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"},"typeName":{"id":209,"nodeType":"UserDefinedTypeName","pathNode":{"id":208,"name":"Vm","nodeType":"IdentifierPath","referencedDeclaration":55,"src":"2671:2:0"},"referencedDeclaration":55,"src":"2671:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"value":{"arguments":[{"id":211,"name":"VM_ADDRESS","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":207,"src":"2700:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":210,"name":"Vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":55,"src":"2697:2:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_Vm_$55_$","typeString":"type(contract Vm)"}},"id":212,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2697:14:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"visibility":"internal"},{"id":215,"nodeType":"VariableDeclaration","src":"2775:22:0","nodes":[],"constant":false,"functionSelector":"61bc221a","mutability":"mutable","name":"counter","nameLocation":"2790:7:0","scope":706,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":214,"name":"uint256","nodeType":"ElementaryTypeName","src":"2775:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"public"},{"id":378,"nodeType":"FunctionDefinition","src":"2887:949:0","nodes":[],"body":{"id":377,"nodeType":"Block","src":"2909:927:0","nodes":[],"statements":[{"assignments":[220],"declarations":[{"constant":false,"id":220,"mutability":"mutable","name":"x","nameLocation":"2924:1:0","nodeType":"VariableDeclaration","scope":377,"src":"2919:6:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":219,"name":"bool","nodeType":"ElementaryTypeName","src":"2919:4:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"id":226,"initialValue":{"arguments":[{"hexValue":"4558414d504c455f424f4f4c","id":223,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2937:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_a634dae177a0e138ae7aaa2afae347412e148992e88c7aabd33ee71be146cb7f","typeString":"literal_string \"EXAMPLE_BOOL\""},"value":"EXAMPLE_BOOL"},{"hexValue":"66616c7365","id":224,"isConstant":false,"isLValue":false,"isPure":true,"kind":"bool","lValueRequested":false,"nodeType":"Literal","src":"2953:5:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"value":"false"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_a634dae177a0e138ae7aaa2afae347412e148992e88c7aabd33ee71be146cb7f","typeString":"literal_string \"EXAMPLE_BOOL\""},{"typeIdentifier":"t_bool","typeString":"bool"}],"expression":{"id":221,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"2928:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":222,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"envOr","nodeType":"MemberAccess","referencedDeclaration":10,"src":"2928:8:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$_t_bool_$returns$_t_bool_$","typeString":"function (string memory,bool) view external returns (bool)"}},"id":225,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2928:31:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"nodeType":"VariableDeclarationStatement","src":"2919:40:0"},{"expression":{"arguments":[{"hexValue":"626f6f6c2076616c75652066726f6d20656e76","id":230,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2981:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_5a607d0b5a1295325aa8901721d78ba402601bba6f62cebdd5235dd0204a590b","typeString":"literal_string \"bool value from env\""},"value":"bool value from env"},{"id":231,"name":"x","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":220,"src":"3004:1:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_5a607d0b5a1295325aa8901721d78ba402601bba6f62cebdd5235dd0204a590b","typeString":"literal_string \"bool value from env\""},{"typeIdentifier":"t_bool","typeString":"bool"}],"expression":{"id":227,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"2969:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":229,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":137,"src":"2969:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_bool_$returns$__$","typeString":"function (string memory,bool) pure"}},"id":232,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2969:37:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":233,"nodeType":"ExpressionStatement","src":"2969:37:0"},{"expression":{"arguments":[{"hexValue":"636f6e74726163742061646472","id":237,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3029:15:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_fa50728770d00fe8f6a0592f3565bbfaf063ee4077f1f5bbc003d091d33cd0c4","typeString":"literal_string \"contract addr\""},"value":"contract addr"},{"arguments":[{"id":240,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3054:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}],"id":239,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3046:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":238,"name":"address","nodeType":"ElementaryTypeName","src":"3046:7:0","typeDescriptions":{}}},"id":241,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3046:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_fa50728770d00fe8f6a0592f3565bbfaf063ee4077f1f5bbc003d091d33cd0c4","typeString":"literal_string \"contract addr\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":234,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3017:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":236,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":171,"src":"3017:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":242,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3017:43:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":243,"nodeType":"ExpressionStatement","src":"3017:43:0"},{"expression":{"arguments":[{"hexValue":"636f6e7472616374206e6f6e6365","id":247,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3082:16:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_3a23091615a5de8c0a35ffd8857a37e2c4e0b72f3ef8a34d6caf65efcd562e2f","typeString":"literal_string \"contract nonce\""},"value":"contract nonce"},{"arguments":[{"arguments":[{"id":252,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3120:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}],"id":251,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3112:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":250,"name":"address","nodeType":"ElementaryTypeName","src":"3112:7:0","typeDescriptions":{}}},"id":253,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3112:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":248,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"3100:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":249,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"getNonce","nodeType":"MemberAccess","referencedDeclaration":17,"src":"3100:11:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_address_$returns$_t_uint64_$","typeString":"function (address) view external returns (uint64)"}},"id":254,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3100:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_3a23091615a5de8c0a35ffd8857a37e2c4e0b72f3ef8a34d6caf65efcd562e2f","typeString":"literal_string \"contract nonce\""},{"typeIdentifier":"t_uint64","typeString":"uint64"}],"expression":{"id":244,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3070:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":246,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":154,"src":"3070:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_uint256_$returns$__$","typeString":"function (string memory,uint256) pure"}},"id":255,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3070:57:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":256,"nodeType":"ExpressionStatement","src":"3070:57:0"},{"expression":{"arguments":[{"hexValue":"73656e6465722061646472","id":260,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3149:13:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_8125ca2decf812b25b65606ff16dad37cb198ff0433485a7926e50feafacfc35","typeString":"literal_string \"sender addr\""},"value":"sender addr"},{"arguments":[{"expression":{"id":263,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"3172:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":264,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"sender","nodeType":"MemberAccess","src":"3172:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":262,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3164:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":261,"name":"address","nodeType":"ElementaryTypeName","src":"3164:7:0","typeDescriptions":{}}},"id":265,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3164:19:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_8125ca2decf812b25b65606ff16dad37cb198ff0433485a7926e50feafacfc35","typeString":"literal_string \"sender addr\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":257,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3137:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":259,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":171,"src":"3137:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":266,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3137:47:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":267,"nodeType":"ExpressionStatement","src":"3137:47:0"},{"expression":{"arguments":[{"hexValue":"73656e646572206e6f6e6365","id":271,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3206:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_db7deb43f2f9e0404016de53b7e64c4976b54149581f7534daae2551e8cf4e40","typeString":"literal_string \"sender nonce\""},"value":"sender nonce"},{"arguments":[{"arguments":[{"expression":{"id":276,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"3242:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":277,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"sender","nodeType":"MemberAccess","src":"3242:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":275,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3234:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":274,"name":"address","nodeType":"ElementaryTypeName","src":"3234:7:0","typeDescriptions":{}}},"id":278,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3234:19:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":272,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"3222:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":273,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"getNonce","nodeType":"MemberAccess","referencedDeclaration":17,"src":"3222:11:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_address_$returns$_t_uint64_$","typeString":"function (address) view external returns (uint64)"}},"id":279,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3222:32:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_db7deb43f2f9e0404016de53b7e64c4976b54149581f7534daae2551e8cf4e40","typeString":"literal_string \"sender nonce\""},{"typeIdentifier":"t_uint64","typeString":"uint64"}],"expression":{"id":268,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3194:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":270,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":154,"src":"3194:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_uint256_$returns$__$","typeString":"function (string memory,uint256) pure"}},"id":280,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3194:61:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":281,"nodeType":"ExpressionStatement","src":"3194:61:0"},{"assignments":[283],"declarations":[{"constant":false,"id":283,"mutability":"mutable","name":"json","nameLocation":"3280:4:0","nodeType":"VariableDeclaration","scope":377,"src":"3266:18:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":282,"name":"string","nodeType":"ElementaryTypeName","src":"3266:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"id":285,"initialValue":{"hexValue":"7b22726f6f745f6b6579223a205b7b2261223a20312c202262223a20327d5d7d","id":284,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3287:34:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_e95522e99766888d0261f55bd1eae5e3f3e26eaf009a16e2433eafaf0a4ecdf2","typeString":"literal_string \"{\"root_key\": [{\"a\": 1, \"b\": 2}]}\""},"value":"{\"root_key\": [{\"a\": 1, \"b\": 2}]}"},"nodeType":"VariableDeclarationStatement","src":"3266:55:0"},{"assignments":[290],"declarations":[{"constant":false,"id":290,"mutability":"mutable","name":"keys","nameLocation":"3347:4:0","nodeType":"VariableDeclaration","scope":377,"src":"3331:20:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string[]"},"typeName":{"baseType":{"id":288,"name":"string","nodeType":"ElementaryTypeName","src":"3331:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"id":289,"nodeType":"ArrayTypeName","src":"3331:8:0","typeDescriptions":{"typeIdentifier":"t_array$_t_string_storage_$dyn_storage_ptr","typeString":"string[]"}},"visibility":"internal"}],"id":296,"initialValue":{"arguments":[{"id":293,"name":"json","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":283,"src":"3371:4:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"hexValue":"2e726f6f745f6b65795b305d","id":294,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3377:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_d82f67100edb80050915e1ec4b565c9a8319a22efb1075e1298b7bb60101d266","typeString":"literal_string \".root_key[0]\""},"value":".root_key[0]"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_stringliteral_d82f67100edb80050915e1ec4b565c9a8319a22efb1075e1298b7bb60101d266","typeString":"literal_string \".root_key[0]\""}],"expression":{"id":291,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"3354:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":292,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"parseJsonKeys","nodeType":"MemberAccess","referencedDeclaration":27,"src":"3354:16:0","typeDescriptions":{"typeIdentifier":"t_function_external_pure$_t_string_memory_ptr_$_t_string_memory_ptr_$returns$_t_array$_t_string_memory_ptr_$dyn_memory_ptr_$","typeString":"function (string memory,string memory) pure external returns (string memory[] memory)"}},"id":295,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3354:38:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string memory[] memory"}},"nodeType":"VariableDeclarationStatement","src":"3331:61:0"},{"expression":{"arguments":[{"hexValue":"6b657973","id":300,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3414:6:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_f29790a80c4ce5f42f59892f424f9c92856c6b656c3378e2cf305b260c6f4195","typeString":"literal_string \"keys\""},"value":"keys"},{"baseExpression":{"id":301,"name":"keys","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":290,"src":"3422:4:0","typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string memory[] memory"}},"id":303,"indexExpression":{"hexValue":"30","id":302,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"3427:1:0","typeDescriptions":{"typeIdentifier":"t_rational_0_by_1","typeString":"int_const 0"},"value":"0"},"isConstant":false,"isLValue":true,"isPure":false,"lValueRequested":false,"nodeType":"IndexAccess","src":"3422:7:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"baseExpression":{"id":304,"name":"keys","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":290,"src":"3431:4:0","typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string memory[] memory"}},"id":306,"indexExpression":{"hexValue":"31","id":305,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"3436:1:0","typeDescriptions":{"typeIdentifier":"t_rational_1_by_1","typeString":"int_const 1"},"value":"1"},"isConstant":false,"isLValue":true,"isPure":false,"lValueRequested":false,"nodeType":"IndexAccess","src":"3431:7:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_f29790a80c4ce5f42f59892f424f9c92856c6b656c3378e2cf305b260c6f4195","typeString":"literal_string \"keys\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}],"expression":{"id":297,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3402:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":299,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":191,"src":"3402:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_string_memory_ptr_$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory,string memory,string memory) pure"}},"id":307,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3402:37:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":308,"nodeType":"ExpressionStatement","src":"3402:37:0"},{"expression":{"arguments":[{"hexValue":"66726f6d206f726967696e616c","id":312,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3461:15:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_77928970c8757d110f3c23e003246f49e0de890480ba9717ba659b2f56f316b2","typeString":"literal_string \"from original\""},"value":"from original"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_77928970c8757d110f3c23e003246f49e0de890480ba9717ba659b2f56f316b2","typeString":"literal_string \"from original\""}],"expression":{"id":309,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3450:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":311,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"hello","nodeType":"MemberAccess","referencedDeclaration":633,"src":"3450:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) view external"}},"id":313,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3450:27:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":314,"nodeType":"ExpressionStatement","src":"3450:27:0"},{"expression":{"arguments":[{"arguments":[{"arguments":[{"hexValue":"30783432","id":322,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"3517:4:0","typeDescriptions":{"typeIdentifier":"t_rational_66_by_1","typeString":"int_const 66"},"value":"0x42"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_66_by_1","typeString":"int_const 66"}],"id":321,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3509:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":320,"name":"uint160","nodeType":"ElementaryTypeName","src":"3509:7:0","typeDescriptions":{}}},"id":323,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3509:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":319,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3501:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":318,"name":"address","nodeType":"ElementaryTypeName","src":"3501:7:0","typeDescriptions":{}}},"id":324,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3501:22:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":315,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"3487:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":317,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"startPrank","nodeType":"MemberAccess","referencedDeclaration":32,"src":"3487:13:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_address_$returns$__$","typeString":"function (address) external"}},"id":325,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3487:37:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":326,"nodeType":"ExpressionStatement","src":"3487:37:0"},{"expression":{"arguments":[{"hexValue":"66726f6d207072616e6b2031","id":330,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3545:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_42b34abfe37a8b0add910cda7b4a379e6538fa7a1dcafce47a02bd38f6c88e2a","typeString":"literal_string \"from prank 1\""},"value":"from prank 1"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_42b34abfe37a8b0add910cda7b4a379e6538fa7a1dcafce47a02bd38f6c88e2a","typeString":"literal_string \"from prank 1\""}],"expression":{"id":327,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3534:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":329,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"hello","nodeType":"MemberAccess","referencedDeclaration":633,"src":"3534:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) view external"}},"id":331,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3534:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":332,"nodeType":"ExpressionStatement","src":"3534:26:0"},{"expression":{"arguments":[{"hexValue":"706172656e742073636f7065206d73672e73656e646572","id":336,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3582:25:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_83ec9246154d8845de47aafc5c2865c9985d2efe84472c27283879f2fbf5cc94","typeString":"literal_string \"parent scope msg.sender\""},"value":"parent scope msg.sender"},{"arguments":[{"expression":{"id":339,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"3617:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":340,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"sender","nodeType":"MemberAccess","src":"3617:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":338,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3609:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":337,"name":"address","nodeType":"ElementaryTypeName","src":"3609:7:0","typeDescriptions":{}}},"id":341,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3609:19:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_83ec9246154d8845de47aafc5c2865c9985d2efe84472c27283879f2fbf5cc94","typeString":"literal_string \"parent scope msg.sender\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":333,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3570:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":335,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":171,"src":"3570:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":342,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3570:59:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":343,"nodeType":"ExpressionStatement","src":"3570:59:0"},{"expression":{"arguments":[{"hexValue":"706172656e742073636f706520636f6e74726163742e61646472","id":347,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3651:28:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_97df66250e0b2b48f0ec8d0e01eb1b8ca012d95f1572895622aa1ea433e5570f","typeString":"literal_string \"parent scope contract.addr\""},"value":"parent scope contract.addr"},{"arguments":[{"id":350,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3689:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}],"id":349,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3681:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":348,"name":"address","nodeType":"ElementaryTypeName","src":"3681:7:0","typeDescriptions":{}}},"id":351,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3681:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_97df66250e0b2b48f0ec8d0e01eb1b8ca012d95f1572895622aa1ea433e5570f","typeString":"literal_string \"parent scope contract.addr\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":344,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3639:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":346,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":171,"src":"3639:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":352,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3639:56:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":353,"nodeType":"ExpressionStatement","src":"3639:56:0"},{"expression":{"arguments":[{"hexValue":"66726f6d207072616e6b2032","id":357,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3716:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_a38a34f8cad750a79aa097a92971f8f405b51ee9d53d25c5b14fc129ba3684bb","typeString":"literal_string \"from prank 2\""},"value":"from prank 2"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_a38a34f8cad750a79aa097a92971f8f405b51ee9d53d25c5b14fc129ba3684bb","typeString":"literal_string \"from prank 2\""}],"expression":{"id":354,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3705:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":356,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"hello","nodeType":"MemberAccess","referencedDeclaration":633,"src":"3705:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) view external"}},"id":358,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3705:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":359,"nodeType":"ExpressionStatement","src":"3705:26:0"},{"expression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":360,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"3741:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":362,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"stopPrank","nodeType":"MemberAccess","referencedDeclaration":35,"src":"3741:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$__$returns$__$","typeString":"function () external"}},"id":363,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3741:14:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":364,"nodeType":"ExpressionStatement","src":"3741:14:0"},{"expression":{"arguments":[{"hexValue":"66726f6d206f726967696e616c20616761696e","id":368,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3776:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_0c805c6579e20a9c4c8e11aeab23330910a9f2da629191dc119d1730e8ed6860","typeString":"literal_string \"from original again\""},"value":"from original again"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_0c805c6579e20a9c4c8e11aeab23330910a9f2da629191dc119d1730e8ed6860","typeString":"literal_string \"from original again\""}],"expression":{"id":365,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3765:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":367,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"hello","nodeType":"MemberAccess","referencedDeclaration":633,"src":"3765:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) view external"}},"id":369,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3765:33:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":370,"nodeType":"ExpressionStatement","src":"3765:33:0"},{"expression":{"arguments":[{"hexValue":"646f6e6521","id":374,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3821:7:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_080382d5c9e9e7c5e3d1d33f5e7422740375955180fadff167d8130e0c35f3fc","typeString":"literal_string \"done!\""},"value":"done!"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_080382d5c9e9e7c5e3d1d33f5e7422740375955180fadff167d8130e0c35f3fc","typeString":"literal_string \"done!\""}],"expression":{"id":371,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3809:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":373,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"3809:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":375,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3809:20:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":376,"nodeType":"ExpressionStatement","src":"3809:20:0"}]},"documentation":{"id":216,"nodeType":"StructuredDocumentation","src":"2804:78:0","text":"@notice example function, runs through basic cheat-codes and console logs."},"functionSelector":"c0406226","implemented":true,"kind":"function","modifiers":[],"name":"run","nameLocation":"2896:3:0","parameters":{"id":217,"nodeType":"ParameterList","parameters":[],"src":"2899:2:0"},"returnParameters":{"id":218,"nodeType":"ParameterList","parameters":[],"src":"2909:0:0"},"scope":706,"stateMutability":"nonpayable","virtual":false,"visibility":"public"},{"id":609,"nodeType":"FunctionDefinition","src":"3903:1258:0","nodes":[],"body":{"id":608,"nodeType":"Block","src":"3934:1227:0","nodes":[],"statements":[{"expression":{"arguments":[{"hexValue":"6e6f6e6365207374617274","id":385,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3956:13:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_71efc69b9a13b6bc1e9a14d766ff01c79022262c6daa6532fb5dfb14f8511a20","typeString":"literal_string \"nonce start\""},"value":"nonce start"},{"arguments":[{"arguments":[{"arguments":[{"id":392,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3999:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}],"id":391,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3991:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":390,"name":"address","nodeType":"ElementaryTypeName","src":"3991:7:0","typeDescriptions":{}}},"id":393,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3991:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":388,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"3979:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":389,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"getNonce","nodeType":"MemberAccess","referencedDeclaration":17,"src":"3979:11:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_address_$returns$_t_uint64_$","typeString":"function (address) view external returns (uint64)"}},"id":394,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3979:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint64","typeString":"uint64"}],"id":387,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3971:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint256_$","typeString":"type(uint256)"},"typeName":{"id":386,"name":"uint256","nodeType":"ElementaryTypeName","src":"3971:7:0","typeDescriptions":{}}},"id":395,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3971:35:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_71efc69b9a13b6bc1e9a14d766ff01c79022262c6daa6532fb5dfb14f8511a20","typeString":"literal_string \"nonce start\""},{"typeIdentifier":"t_uint256","typeString":"uint256"}],"expression":{"id":382,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3944:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":384,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":154,"src":"3944:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_uint256_$returns$__$","typeString":"function (string memory,uint256) pure"}},"id":396,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3944:63:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":397,"nodeType":"ExpressionStatement","src":"3944:63:0"},{"expression":{"arguments":[{"hexValue":"74657374696e672073696e676c65","id":401,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4030:16:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_b75103528423218e7569082dad569ed0d2ce7c0ac770c0812b220e2d369fe474","typeString":"literal_string \"testing single\""},"value":"testing single"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_b75103528423218e7569082dad569ed0d2ce7c0ac770c0812b220e2d369fe474","typeString":"literal_string \"testing single\""}],"expression":{"id":398,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"4018:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":400,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"4018:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":402,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4018:29:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":403,"nodeType":"ExpressionStatement","src":"4018:29:0"},{"expression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":404,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"4057:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":406,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"broadcast","nodeType":"MemberAccess","referencedDeclaration":38,"src":"4057:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$__$returns$__$","typeString":"function () external"}},"id":407,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4057:14:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":408,"nodeType":"ExpressionStatement","src":"4057:14:0"},{"expression":{"arguments":[{"hexValue":"73696e676c655f63616c6c31","id":412,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4092:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_5e1cad6d7a968cfacf2731373e1248ffb11f4886bced66a02a6de1a67ac8f777","typeString":"literal_string \"single_call1\""},"value":"single_call1"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_5e1cad6d7a968cfacf2731373e1248ffb11f4886bced66a02a6de1a67ac8f777","typeString":"literal_string \"single_call1\""}],"expression":{"id":409,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"4081:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":411,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"call1","nodeType":"MemberAccess","referencedDeclaration":648,"src":"4081:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) external"}},"id":413,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4081:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":414,"nodeType":"ExpressionStatement","src":"4081:26:0"},{"expression":{"arguments":[{"hexValue":"73696e676c655f63616c6c32","id":418,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4128:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_b37ddaf5d00ad9e6371de3fb71b91eef731fae1e86b768666380f7d44e1ada25","typeString":"literal_string \"single_call2\""},"value":"single_call2"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_b37ddaf5d00ad9e6371de3fb71b91eef731fae1e86b768666380f7d44e1ada25","typeString":"literal_string \"single_call2\""}],"expression":{"id":415,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"4117:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":417,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"call2","nodeType":"MemberAccess","referencedDeclaration":663,"src":"4117:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) external"}},"id":419,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4117:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":420,"nodeType":"ExpressionStatement","src":"4117:26:0"},{"expression":{"arguments":[{"hexValue":"74657374696e672073746172742f73746f70","id":424,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4166:20:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_778e886e3a1c3c5096aca76228832105f3f9269f362effd0e8ce3737787cb784","typeString":"literal_string \"testing start/stop\""},"value":"testing start/stop"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_778e886e3a1c3c5096aca76228832105f3f9269f362effd0e8ce3737787cb784","typeString":"literal_string \"testing start/stop\""}],"expression":{"id":421,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"4154:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":423,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"4154:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":425,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4154:33:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":426,"nodeType":"ExpressionStatement","src":"4154:33:0"},{"expression":{"arguments":[{"arguments":[{"arguments":[{"hexValue":"3078633066666565","id":434,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4231:8:0","typeDescriptions":{"typeIdentifier":"t_rational_12648430_by_1","typeString":"int_const 12648430"},"value":"0xc0ffee"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_12648430_by_1","typeString":"int_const 12648430"}],"id":433,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4223:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":432,"name":"uint160","nodeType":"ElementaryTypeName","src":"4223:7:0","typeDescriptions":{}}},"id":435,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4223:17:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":431,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4215:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":430,"name":"address","nodeType":"ElementaryTypeName","src":"4215:7:0","typeDescriptions":{}}},"id":436,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4215:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":427,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"4197:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":429,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"startBroadcast","nodeType":"MemberAccess","referencedDeclaration":48,"src":"4197:17:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_address_$returns$__$","typeString":"function (address) external"}},"id":437,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4197:45:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":438,"nodeType":"ExpressionStatement","src":"4197:45:0"},{"expression":{"arguments":[{"hexValue":"737461727473746f705f63616c6c31","id":442,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4263:17:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_2fc2682edf10ed478ee3b9a190f6b1c88bb492b300935ce44545a1613cf8f041","typeString":"literal_string \"startstop_call1\""},"value":"startstop_call1"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_2fc2682edf10ed478ee3b9a190f6b1c88bb492b300935ce44545a1613cf8f041","typeString":"literal_string \"startstop_call1\""}],"expression":{"id":439,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"4252:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":441,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"call1","nodeType":"MemberAccess","referencedDeclaration":648,"src":"4252:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) external"}},"id":443,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4252:29:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":444,"nodeType":"ExpressionStatement","src":"4252:29:0"},{"expression":{"arguments":[{"hexValue":"737461727473746f705f63616c6c32","id":448,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4302:17:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_1a6fd77f04b28bf45d6d0e2dd4c65c0bbfeba174f849e43bb67ebca1c019cda4","typeString":"literal_string \"startstop_call2\""},"value":"startstop_call2"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_1a6fd77f04b28bf45d6d0e2dd4c65c0bbfeba174f849e43bb67ebca1c019cda4","typeString":"literal_string \"startstop_call2\""}],"expression":{"id":445,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"4291:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":447,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"call2","nodeType":"MemberAccess","referencedDeclaration":663,"src":"4291:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) external"}},"id":449,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4291:29:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":450,"nodeType":"ExpressionStatement","src":"4291:29:0"},{"expression":{"arguments":[{"hexValue":"737461727473746f705f70757265","id":454,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4344:16:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_b6e9eb1efd186b1d92b54da45026aa97a178e6eaffdf9dbf9f666fc751fb0ff9","typeString":"literal_string \"startstop_pure\""},"value":"startstop_pure"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_b6e9eb1efd186b1d92b54da45026aa97a178e6eaffdf9dbf9f666fc751fb0ff9","typeString":"literal_string \"startstop_pure\""}],"expression":{"id":451,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"4330:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":453,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"callPure","nodeType":"MemberAccess","referencedDeclaration":705,"src":"4330:13:0","typeDescriptions":{"typeIdentifier":"t_function_external_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure external"}},"id":455,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4330:31:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":456,"nodeType":"ExpressionStatement","src":"4330:31:0"},{"expression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":457,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"4371:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":459,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"stopBroadcast","nodeType":"MemberAccess","referencedDeclaration":54,"src":"4371:16:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$__$returns$__$","typeString":"function () external"}},"id":460,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4371:18:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":461,"nodeType":"ExpressionStatement","src":"4371:18:0"},{"expression":{"arguments":[{"hexValue":"737461727473746f705f63616c6c33","id":465,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4410:17:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_8eb502bfdc4adda22bd960aa2ae13ce4c0ed8cc3b3791ed65e321a38cdd36f72","typeString":"literal_string \"startstop_call3\""},"value":"startstop_call3"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_8eb502bfdc4adda22bd960aa2ae13ce4c0ed8cc3b3791ed65e321a38cdd36f72","typeString":"literal_string \"startstop_call3\""}],"expression":{"id":462,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"4399:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":464,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"call1","nodeType":"MemberAccess","referencedDeclaration":648,"src":"4399:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) external"}},"id":466,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4399:29:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":467,"nodeType":"ExpressionStatement","src":"4399:29:0"},{"expression":{"arguments":[{"hexValue":"74657374696e67206e6573746564","id":471,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4451:16:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_f92f19f7a5b5b9ce341188bf4e15925f184cdb5ac135c4846ced718f259dbde5","typeString":"literal_string \"testing nested\""},"value":"testing nested"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_f92f19f7a5b5b9ce341188bf4e15925f184cdb5ac135c4846ced718f259dbde5","typeString":"literal_string \"testing nested\""}],"expression":{"id":468,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"4439:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":470,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"4439:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":472,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4439:29:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":473,"nodeType":"ExpressionStatement","src":"4439:29:0"},{"expression":{"arguments":[{"arguments":[{"arguments":[{"hexValue":"307831323334","id":481,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4512:6:0","typeDescriptions":{"typeIdentifier":"t_rational_4660_by_1","typeString":"int_const 4660"},"value":"0x1234"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_4660_by_1","typeString":"int_const 4660"}],"id":480,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4504:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":479,"name":"uint160","nodeType":"ElementaryTypeName","src":"4504:7:0","typeDescriptions":{}}},"id":482,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4504:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":478,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4496:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":477,"name":"address","nodeType":"ElementaryTypeName","src":"4496:7:0","typeDescriptions":{}}},"id":483,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4496:24:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":474,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"4478:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":476,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"startBroadcast","nodeType":"MemberAccess","referencedDeclaration":48,"src":"4478:17:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_address_$returns$__$","typeString":"function (address) external"}},"id":484,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4478:43:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":485,"nodeType":"ExpressionStatement","src":"4478:43:0"},{"expression":{"arguments":[{"hexValue":"6e6573746564","id":489,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4544:8:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_4d5b14044d78fbf0c9dd8b9c49e35f09ee5a6f5b1b3b8117b5d0e15c8dd2cb09","typeString":"literal_string \"nested\""},"value":"nested"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_4d5b14044d78fbf0c9dd8b9c49e35f09ee5a6f5b1b3b8117b5d0e15c8dd2cb09","typeString":"literal_string \"nested\""}],"expression":{"id":486,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"4531:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":488,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"nested1","nodeType":"MemberAccess","referencedDeclaration":678,"src":"4531:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) external"}},"id":490,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4531:22:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":491,"nodeType":"ExpressionStatement","src":"4531:22:0"},{"expression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":492,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"4563:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":494,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"stopBroadcast","nodeType":"MemberAccess","referencedDeclaration":54,"src":"4563:16:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$__$returns$__$","typeString":"function () external"}},"id":495,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4563:18:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":496,"nodeType":"ExpressionStatement","src":"4563:18:0"},{"expression":{"arguments":[{"hexValue":"636f6e7472616374206465706c6f796d656e74","id":500,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4604:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_aaf9be86adf9b6872d87eed3526f7c55f3c5d61f4e4dd6d55ef2fcbb8ad0bd57","typeString":"literal_string \"contract deployment\""},"value":"contract deployment"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_aaf9be86adf9b6872d87eed3526f7c55f3c5d61f4e4dd6d55ef2fcbb8ad0bd57","typeString":"literal_string \"contract deployment\""}],"expression":{"id":497,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"4592:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":499,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"4592:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":501,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4592:34:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":502,"nodeType":"ExpressionStatement","src":"4592:34:0"},{"expression":{"arguments":[{"arguments":[{"arguments":[{"hexValue":"3078313233343536","id":510,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4665:8:0","typeDescriptions":{"typeIdentifier":"t_rational_1193046_by_1","typeString":"int_const 1193046"},"value":"0x123456"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_1193046_by_1","typeString":"int_const 1193046"}],"id":509,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4657:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":508,"name":"uint160","nodeType":"ElementaryTypeName","src":"4657:7:0","typeDescriptions":{}}},"id":511,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4657:17:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":507,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4649:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":506,"name":"address","nodeType":"ElementaryTypeName","src":"4649:7:0","typeDescriptions":{}}},"id":512,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4649:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":503,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"4636:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":505,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"broadcast","nodeType":"MemberAccess","referencedDeclaration":43,"src":"4636:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_address_$returns$__$","typeString":"function (address) external"}},"id":513,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4636:40:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":514,"nodeType":"ExpressionStatement","src":"4636:40:0"},{"assignments":[517],"declarations":[{"constant":false,"id":517,"mutability":"mutable","name":"x","nameLocation":"4693:1:0","nodeType":"VariableDeclaration","scope":608,"src":"4686:8:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"},"typeName":{"id":516,"nodeType":"UserDefinedTypeName","pathNode":{"id":515,"name":"FooBar","nodeType":"IdentifierPath","referencedDeclaration":719,"src":"4686:6:0"},"referencedDeclaration":719,"src":"4686:6:0","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}},"visibility":"internal"}],"id":523,"initialValue":{"arguments":[{"hexValue":"31323334","id":521,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4708:4:0","typeDescriptions":{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"},"value":"1234"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"}],"id":520,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"NewExpression","src":"4697:10:0","typeDescriptions":{"typeIdentifier":"t_function_creation_nonpayable$_t_uint256_$returns$_t_contract$_FooBar_$719_$","typeString":"function (uint256) returns (contract FooBar)"},"typeName":{"id":519,"nodeType":"UserDefinedTypeName","pathNode":{"id":518,"name":"FooBar","nodeType":"IdentifierPath","referencedDeclaration":719,"src":"4701:6:0"},"referencedDeclaration":719,"src":"4701:6:0","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}}},"id":522,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4697:16:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}},"nodeType":"VariableDeclarationStatement","src":"4686:27:0"},{"expression":{"arguments":[{"commonType":{"typeIdentifier":"t_uint256","typeString":"uint256"},"id":529,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"leftExpression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":525,"name":"x","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":517,"src":"4731:1:0","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}},"id":526,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"foo","nodeType":"MemberAccess","referencedDeclaration":708,"src":"4731:5:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$__$returns$_t_uint256_$","typeString":"function () view external returns (uint256)"}},"id":527,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4731:7:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"nodeType":"BinaryOperation","operator":"==","rightExpression":{"hexValue":"31323334","id":528,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4742:4:0","typeDescriptions":{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"},"value":"1234"},"src":"4731:15:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bool","typeString":"bool"}],"id":524,"name":"require","nodeType":"Identifier","overloadedDeclarations":[-18,-18],"referencedDeclaration":-18,"src":"4723:7:0","typeDescriptions":{"typeIdentifier":"t_function_require_pure$_t_bool_$returns$__$","typeString":"function (bool) pure"}},"id":530,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4723:24:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":531,"nodeType":"ExpressionStatement","src":"4723:24:0"},{"expression":{"arguments":[{"hexValue":"6372656174652032","id":535,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4770:10:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_4411d6d4ffcd00382a95255a63761e69de9810e1236042a5c64948a7b6c04daa","typeString":"literal_string \"create 2\""},"value":"create 2"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_4411d6d4ffcd00382a95255a63761e69de9810e1236042a5c64948a7b6c04daa","typeString":"literal_string \"create 2\""}],"expression":{"id":532,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"4758:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":534,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"4758:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":536,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4758:23:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":537,"nodeType":"ExpressionStatement","src":"4758:23:0"},{"expression":{"arguments":[{"arguments":[{"arguments":[{"hexValue":"307863616665","id":545,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4820:6:0","typeDescriptions":{"typeIdentifier":"t_rational_51966_by_1","typeString":"int_const 51966"},"value":"0xcafe"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_51966_by_1","typeString":"int_const 51966"}],"id":544,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4812:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":543,"name":"uint160","nodeType":"ElementaryTypeName","src":"4812:7:0","typeDescriptions":{}}},"id":546,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4812:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":542,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4804:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":541,"name":"address","nodeType":"ElementaryTypeName","src":"4804:7:0","typeDescriptions":{}}},"id":547,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4804:24:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":538,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"4791:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":540,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"broadcast","nodeType":"MemberAccess","referencedDeclaration":43,"src":"4791:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_address_$returns$__$","typeString":"function (address) external"}},"id":548,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4791:38:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":549,"nodeType":"ExpressionStatement","src":"4791:38:0"},{"assignments":[552],"declarations":[{"constant":false,"id":552,"mutability":"mutable","name":"y","nameLocation":"4846:1:0","nodeType":"VariableDeclaration","scope":608,"src":"4839:8:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"},"typeName":{"id":551,"nodeType":"UserDefinedTypeName","pathNode":{"id":550,"name":"FooBar","nodeType":"IdentifierPath","referencedDeclaration":719,"src":"4839:6:0"},"referencedDeclaration":719,"src":"4839:6:0","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}},"visibility":"internal"}],"id":566,"initialValue":{"arguments":[{"hexValue":"31323334","id":564,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4889:4:0","typeDescriptions":{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"},"value":"1234"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"}],"id":555,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"NewExpression","src":"4850:10:0","typeDescriptions":{"typeIdentifier":"t_function_creation_nonpayable$_t_uint256_$returns$_t_contract$_FooBar_$719_$","typeString":"function (uint256) returns (contract FooBar)"},"typeName":{"id":554,"nodeType":"UserDefinedTypeName","pathNode":{"id":553,"name":"FooBar","nodeType":"IdentifierPath","referencedDeclaration":719,"src":"4854:6:0"},"referencedDeclaration":719,"src":"4854:6:0","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}}},"id":563,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"names":["salt"],"nodeType":"FunctionCallOptions","options":[{"arguments":[{"arguments":[{"hexValue":"3432","id":560,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4883:2:0","typeDescriptions":{"typeIdentifier":"t_rational_42_by_1","typeString":"int_const 42"},"value":"42"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_42_by_1","typeString":"int_const 42"}],"id":559,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4875:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint256_$","typeString":"type(uint256)"},"typeName":{"id":558,"name":"uint256","nodeType":"ElementaryTypeName","src":"4875:7:0","typeDescriptions":{}}},"id":561,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4875:11:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint256","typeString":"uint256"}],"id":557,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4867:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_bytes32_$","typeString":"type(bytes32)"},"typeName":{"id":556,"name":"bytes32","nodeType":"ElementaryTypeName","src":"4867:7:0","typeDescriptions":{}}},"id":562,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4867:20:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes32","typeString":"bytes32"}}],"src":"4850:38:0","typeDescriptions":{"typeIdentifier":"t_function_creation_nonpayable$_t_uint256_$returns$_t_contract$_FooBar_$719_$salt","typeString":"function (uint256) returns (contract FooBar)"}},"id":565,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4850:44:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}},"nodeType":"VariableDeclarationStatement","src":"4839:55:0"},{"expression":{"arguments":[{"commonType":{"typeIdentifier":"t_uint256","typeString":"uint256"},"id":572,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"leftExpression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":568,"name":"y","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":552,"src":"4912:1:0","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}},"id":569,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"foo","nodeType":"MemberAccess","referencedDeclaration":708,"src":"4912:5:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$__$returns$_t_uint256_$","typeString":"function () view external returns (uint256)"}},"id":570,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4912:7:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"nodeType":"BinaryOperation","operator":"==","rightExpression":{"hexValue":"31323334","id":571,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4923:4:0","typeDescriptions":{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"},"value":"1234"},"src":"4912:15:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bool","typeString":"bool"}],"id":567,"name":"require","nodeType":"Identifier","overloadedDeclarations":[-18,-18],"referencedDeclaration":-18,"src":"4904:7:0","typeDescriptions":{"typeIdentifier":"t_function_require_pure$_t_bool_$returns$__$","typeString":"function (bool) pure"}},"id":573,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4904:24:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":574,"nodeType":"ExpressionStatement","src":"4904:24:0"},{"expression":{"arguments":[{"hexValue":"646f6e6521","id":578,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4950:7:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_080382d5c9e9e7c5e3d1d33f5e7422740375955180fadff167d8130e0c35f3fc","typeString":"literal_string \"done!\""},"value":"done!"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_080382d5c9e9e7c5e3d1d33f5e7422740375955180fadff167d8130e0c35f3fc","typeString":"literal_string \"done!\""}],"expression":{"id":575,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"4938:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":577,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"4938:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":579,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4938:20:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":580,"nodeType":"ExpressionStatement","src":"4938:20:0"},{"expression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":581,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"5042:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":583,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"broadcast","nodeType":"MemberAccess","referencedDeclaration":38,"src":"5042:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$__$returns$__$","typeString":"function () external"}},"id":584,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5042:14:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":585,"nodeType":"ExpressionStatement","src":"5042:14:0"},{"expression":{"arguments":[{"hexValue":"31323334","id":589,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"5077:4:0","typeDescriptions":{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"},"value":"1234"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"}],"id":588,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"NewExpression","src":"5066:10:0","typeDescriptions":{"typeIdentifier":"t_function_creation_nonpayable$_t_uint256_$returns$_t_contract$_FooBar_$719_$","typeString":"function (uint256) returns (contract FooBar)"},"typeName":{"id":587,"nodeType":"UserDefinedTypeName","pathNode":{"id":586,"name":"FooBar","nodeType":"IdentifierPath","referencedDeclaration":719,"src":"5070:6:0"},"referencedDeclaration":719,"src":"5070:6:0","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}}},"id":590,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5066:16:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}},"id":591,"nodeType":"ExpressionStatement","src":"5066:16:0"},{"expression":{"arguments":[{"hexValue":"6e6f6e636520656e64","id":595,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"5105:11:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_fa629e6661ad2a2bdb09cf9a3a276ce0d722482ae5c2887650751be0938847e8","typeString":"literal_string \"nonce end\""},"value":"nonce end"},{"arguments":[{"arguments":[{"arguments":[{"id":602,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"5146:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}],"id":601,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"5138:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":600,"name":"address","nodeType":"ElementaryTypeName","src":"5138:7:0","typeDescriptions":{}}},"id":603,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5138:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":598,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"5126:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":599,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"getNonce","nodeType":"MemberAccess","referencedDeclaration":17,"src":"5126:11:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_address_$returns$_t_uint64_$","typeString":"function (address) view external returns (uint64)"}},"id":604,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5126:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint64","typeString":"uint64"}],"id":597,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"5118:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint256_$","typeString":"type(uint256)"},"typeName":{"id":596,"name":"uint256","nodeType":"ElementaryTypeName","src":"5118:7:0","typeDescriptions":{}}},"id":605,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5118:35:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_fa629e6661ad2a2bdb09cf9a3a276ce0d722482ae5c2887650751be0938847e8","typeString":"literal_string \"nonce end\""},{"typeIdentifier":"t_uint256","typeString":"uint256"}],"expression":{"id":592,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"5093:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":594,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":154,"src":"5093:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_uint256_$returns$__$","typeString":"function (string memory,uint256) pure"}},"id":606,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5093:61:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":607,"nodeType":"ExpressionStatement","src":"5093:61:0"}]},"documentation":{"id":379,"nodeType":"StructuredDocumentation","src":"3842:56:0","text":"@notice example function, to test vm.broadcast with."},"functionSelector":"bef03abc","implemented":true,"kind":"function","modifiers":[],"name":"runBroadcast","nameLocation":"3912:12:0","parameters":{"id":380,"nodeType":"ParameterList","parameters":[],"src":"3924:2:0"},"returnParameters":{"id":381,"nodeType":"ParameterList","parameters":[],"src":"3934:0:0"},"scope":706,"stateMutability":"nonpayable","virtual":false,"visibility":"public"},{"id":633,"nodeType":"FunctionDefinition","src":"5256:143:0","nodes":[],"body":{"id":632,"nodeType":"Block","src":"5305:94:0","nodes":[],"statements":[{"expression":{"arguments":[{"id":618,"name":"_v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":612,"src":"5327:2:0","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}],"expression":{"id":615,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"5315:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":617,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"5315:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":619,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5315:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":620,"nodeType":"ExpressionStatement","src":"5315:15:0"},{"expression":{"arguments":[{"hexValue":"68656c6c6f206d73672e73656e646572","id":624,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"5352:18:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_b3cc13bc51228b2c4c4334d82a4772908254dc0e1c512893dd16208ef13efb8e","typeString":"literal_string \"hello msg.sender\""},"value":"hello msg.sender"},{"arguments":[{"expression":{"id":627,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"5380:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":628,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"sender","nodeType":"MemberAccess","src":"5380:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":626,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"5372:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":625,"name":"address","nodeType":"ElementaryTypeName","src":"5372:7:0","typeDescriptions":{}}},"id":629,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5372:19:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_b3cc13bc51228b2c4c4334d82a4772908254dc0e1c512893dd16208ef13efb8e","typeString":"literal_string \"hello msg.sender\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":621,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"5340:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":623,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":171,"src":"5340:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":630,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5340:52:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":631,"nodeType":"ExpressionStatement","src":"5340:52:0"}]},"documentation":{"id":610,"nodeType":"StructuredDocumentation","src":"5167:84:0","text":"@notice example external function, to force a CALL, and test vm.startPrank with."},"functionSelector":"a777d0dc","implemented":true,"kind":"function","modifiers":[],"name":"hello","nameLocation":"5265:5:0","parameters":{"id":613,"nodeType":"ParameterList","parameters":[{"constant":false,"id":612,"mutability":"mutable","name":"_v","nameLocation":"5287:2:0","nodeType":"VariableDeclaration","scope":633,"src":"5271:18:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":611,"name":"string","nodeType":"ElementaryTypeName","src":"5271:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"5270:20:0"},"returnParameters":{"id":614,"nodeType":"ParameterList","parameters":[],"src":"5305:0:0"},"scope":706,"stateMutability":"view","virtual":false,"visibility":"external"},{"id":648,"nodeType":"FunctionDefinition","src":"5405:95:0","nodes":[],"body":{"id":647,"nodeType":"Block","src":"5449:51:0","nodes":[],"statements":[{"expression":{"id":639,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"UnaryOperation","operator":"++","prefix":false,"src":"5459:9:0","subExpression":{"id":638,"name":"counter","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":215,"src":"5459:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"id":640,"nodeType":"ExpressionStatement","src":"5459:9:0"},{"expression":{"arguments":[{"id":644,"name":"_v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":635,"src":"5490:2:0","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}],"expression":{"id":641,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"5478:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":643,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"5478:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":645,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5478:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":646,"nodeType":"ExpressionStatement","src":"5478:15:0"}]},"functionSelector":"7e79255d","implemented":true,"kind":"function","modifiers":[],"name":"call1","nameLocation":"5414:5:0","parameters":{"id":636,"nodeType":"ParameterList","parameters":[{"constant":false,"id":635,"mutability":"mutable","name":"_v","nameLocation":"5436:2:0","nodeType":"VariableDeclaration","scope":648,"src":"5420:18:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":634,"name":"string","nodeType":"ElementaryTypeName","src":"5420:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"5419:20:0"},"returnParameters":{"id":637,"nodeType":"ParameterList","parameters":[],"src":"5449:0:0"},"scope":706,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":663,"nodeType":"FunctionDefinition","src":"5506:95:0","nodes":[],"body":{"id":662,"nodeType":"Block","src":"5550:51:0","nodes":[],"statements":[{"expression":{"id":654,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"UnaryOperation","operator":"++","prefix":false,"src":"5560:9:0","subExpression":{"id":653,"name":"counter","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":215,"src":"5560:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"id":655,"nodeType":"ExpressionStatement","src":"5560:9:0"},{"expression":{"arguments":[{"id":659,"name":"_v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":650,"src":"5591:2:0","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}],"expression":{"id":656,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"5579:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":658,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"5579:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":660,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5579:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":661,"nodeType":"ExpressionStatement","src":"5579:15:0"}]},"functionSelector":"8d3ef7ca","implemented":true,"kind":"function","modifiers":[],"name":"call2","nameLocation":"5515:5:0","parameters":{"id":651,"nodeType":"ParameterList","parameters":[{"constant":false,"id":650,"mutability":"mutable","name":"_v","nameLocation":"5537:2:0","nodeType":"VariableDeclaration","scope":663,"src":"5521:18:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":649,"name":"string","nodeType":"ElementaryTypeName","src":"5521:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"5520:20:0"},"returnParameters":{"id":652,"nodeType":"ParameterList","parameters":[],"src":"5550:0:0"},"scope":706,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":678,"nodeType":"FunctionDefinition","src":"5607:98:0","nodes":[],"body":{"id":677,"nodeType":"Block","src":"5653:52:0","nodes":[],"statements":[{"expression":{"id":669,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"UnaryOperation","operator":"++","prefix":false,"src":"5663:9:0","subExpression":{"id":668,"name":"counter","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":215,"src":"5663:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"id":670,"nodeType":"ExpressionStatement","src":"5663:9:0"},{"expression":{"arguments":[{"id":674,"name":"_v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":665,"src":"5695:2:0","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}],"expression":{"id":671,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"5682:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":673,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"nested2","nodeType":"MemberAccess","referencedDeclaration":693,"src":"5682:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) external"}},"id":675,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5682:16:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":676,"nodeType":"ExpressionStatement","src":"5682:16:0"}]},"functionSelector":"a76ccdfa","implemented":true,"kind":"function","modifiers":[],"name":"nested1","nameLocation":"5616:7:0","parameters":{"id":666,"nodeType":"ParameterList","parameters":[{"constant":false,"id":665,"mutability":"mutable","name":"_v","nameLocation":"5640:2:0","nodeType":"VariableDeclaration","scope":678,"src":"5624:18:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":664,"name":"string","nodeType":"ElementaryTypeName","src":"5624:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"5623:20:0"},"returnParameters":{"id":667,"nodeType":"ParameterList","parameters":[],"src":"5653:0:0"},"scope":706,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":693,"nodeType":"FunctionDefinition","src":"5711:97:0","nodes":[],"body":{"id":692,"nodeType":"Block","src":"5757:51:0","nodes":[],"statements":[{"expression":{"id":684,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"UnaryOperation","operator":"++","prefix":false,"src":"5767:9:0","subExpression":{"id":683,"name":"counter","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":215,"src":"5767:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"id":685,"nodeType":"ExpressionStatement","src":"5767:9:0"},{"expression":{"arguments":[{"id":689,"name":"_v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":680,"src":"5798:2:0","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}],"expression":{"id":686,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"5786:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":688,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"5786:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":690,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5786:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":691,"nodeType":"ExpressionStatement","src":"5786:15:0"}]},"functionSelector":"dbf1282f","implemented":true,"kind":"function","modifiers":[],"name":"nested2","nameLocation":"5720:7:0","parameters":{"id":681,"nodeType":"ParameterList","parameters":[{"constant":false,"id":680,"mutability":"mutable","name":"_v","nameLocation":"5744:2:0","nodeType":"VariableDeclaration","scope":693,"src":"5728:18:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":679,"name":"string","nodeType":"ElementaryTypeName","src":"5728:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"5727:20:0"},"returnParameters":{"id":682,"nodeType":"ParameterList","parameters":[],"src":"5757:0:0"},"scope":706,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":705,"nodeType":"FunctionDefinition","src":"5814:84:0","nodes":[],"body":{"id":704,"nodeType":"Block","src":"5866:32:0","nodes":[],"statements":[{"expression":{"arguments":[{"id":701,"name":"_v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":695,"src":"5888:2:0","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}],"expression":{"id":698,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"5876:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":700,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"5876:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":702,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5876:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":703,"nodeType":"ExpressionStatement","src":"5876:15:0"}]},"functionSelector":"7f8b915c","implemented":true,"kind":"function","modifiers":[],"name":"callPure","nameLocation":"5823:8:0","parameters":{"id":696,"nodeType":"ParameterList","parameters":[{"constant":false,"id":695,"mutability":"mutable","name":"_v","nameLocation":"5848:2:0","nodeType":"VariableDeclaration","scope":705,"src":"5832:18:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":694,"name":"string","nodeType":"ElementaryTypeName","src":"5832:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"5831:20:0"},"returnParameters":{"id":697,"nodeType":"ParameterList","parameters":[],"src":"5866:0:0"},"scope":706,"stateMutability":"pure","virtual":false,"visibility":"external"}],"abstract":false,"baseContracts":[],"canonicalName":"ScriptExample","contractDependencies":[719],"contractKind":"contract","documentation":{"id":193,"nodeType":"StructuredDocumentation","src":"2415:126:0","text":"@title ScriptExample\n @notice ScriptExample is an example script. The Go forge script code tests that it can run this."},"fullyImplemented":true,"linearizedBaseContracts":[706],"name":"ScriptExample","nameLocation":"2550:13:0","scope":720,"usedErrors":[]},{"id":719,"nodeType":"ContractDefinition","src":"5902:96:0","nodes":[{"id":708,"nodeType":"VariableDeclaration","src":"5924:18:0","nodes":[],"constant":false,"functionSelector":"c2985578","mutability":"mutable","name":"foo","nameLocation":"5939:3:0","scope":719,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":707,"name":"uint256","nodeType":"ElementaryTypeName","src":"5924:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"public"},{"id":718,"nodeType":"FunctionDefinition","src":"5949:47:0","nodes":[],"body":{"id":717,"nodeType":"Block","src":"5972:24:0","nodes":[],"statements":[{"expression":{"id":715,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"leftHandSide":{"id":713,"name":"foo","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":708,"src":"5982:3:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"nodeType":"Assignment","operator":"=","rightHandSide":{"id":714,"name":"v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":710,"src":"5988:1:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"src":"5982:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"id":716,"nodeType":"ExpressionStatement","src":"5982:7:0"}]},"implemented":true,"kind":"constructor","modifiers":[],"name":"","nameLocation":"-1:-1:-1","parameters":{"id":711,"nodeType":"ParameterList","parameters":[{"constant":false,"id":710,"mutability":"mutable","name":"v","nameLocation":"5969:1:0","nodeType":"VariableDeclaration","scope":718,"src":"5961:9:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":709,"name":"uint256","nodeType":"ElementaryTypeName","src":"5961:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"}],"src":"5960:11:0"},"returnParameters":{"id":712,"nodeType":"ParameterList","parameters":[],"src":"5972:0:0"},"scope":719,"stateMutability":"nonpayable","virtual":false,"visibility":"public"}],"abstract":false,"baseContracts":[],"canonicalName":"FooBar","contractDependencies":[],"contractKind":"contract","fullyImplemented":true,"linearizedBaseContracts":[719],"name":"FooBar","nameLocation":"5911:6:0","scope":720,"usedErrors":[]}],"license":"MIT"},"id":0} +\ No newline at end of file
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+0
+
-0
+ +
+ +
+
+
diff --git OP/op-chain-ops/script/testdata/test-artifacts/ScriptExample.s.sol/console.json CELO/op-chain-ops/script/testdata/test-artifacts/ScriptExample.s.sol/console.json +index 23641034487bdd2ad3fcdb35064cb2cdf72b8c77..390e798a470117aedcb815fad90e38e45dad6e26 100644 +--- OP/op-chain-ops/script/testdata/test-artifacts/ScriptExample.s.sol/console.json ++++ CELO/op-chain-ops/script/testdata/test-artifacts/ScriptExample.s.sol/console.json +@@ -1 +1 @@ +-{"abi":[],"bytecode":{"object":"0x602d6037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea164736f6c634300080f000a","sourceMap":"568:1622:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;568:1622:0;;;;;;;;;;;;;;;;;","linkReferences":{}},"deployedBytecode":{"object":"0x73000000000000000000000000000000000000000030146080604052600080fdfea164736f6c634300080f000a","sourceMap":"568:1622:0:-:0;;;;;;;;","linkReferences":{}},"methodIdentifiers":{},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"scripts/ScriptExample.s.sol\":\"console\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[]},\"sources\":{\"scripts/ScriptExample.s.sol\":{\"keccak256\":\"0x531a2ad96c1a2c0bbfa9ab0e1195cd32551b0c10e16e7d256ce5e4c0289a8089\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://24dc6c71502c01f43fb5e113786e377c3b4cafabd5c506067d229fcdd7b037fa\",\"dweb:/ipfs/QmZ9AuxNx9Ygescfg5M4p6Abc2CCwCMZpX5xU32Fz1r4kY\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.15+commit.e14f2714"},"language":"Solidity","output":{"abi":[],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"remappings":[],"optimizer":{"enabled":true,"runs":999999},"metadata":{"bytecodeHash":"none"},"compilationTarget":{"scripts/ScriptExample.s.sol":"console"},"evmVersion":"london","libraries":{}},"sources":{"scripts/ScriptExample.s.sol":{"keccak256":"0x531a2ad96c1a2c0bbfa9ab0e1195cd32551b0c10e16e7d256ce5e4c0289a8089","urls":["bzz-raw://24dc6c71502c01f43fb5e113786e377c3b4cafabd5c506067d229fcdd7b037fa","dweb:/ipfs/QmZ9AuxNx9Ygescfg5M4p6Abc2CCwCMZpX5xU32Fz1r4kY"],"license":"MIT"}},"version":1},"storageLayout":{"storage":[],"types":{}},"userdoc":{"version":1,"kind":"user"},"devdoc":{"version":1,"kind":"dev"},"ast":{"absolutePath":"scripts/ScriptExample.s.sol","id":383,"exportedSymbols":{"ScriptExample":[382],"Vm":[36],"console":[173]},"nodeType":"SourceUnit","src":"32:3736:0","nodes":[{"id":1,"nodeType":"PragmaDirective","src":"32:23:0","nodes":[],"literals":["solidity","0.8",".15"]},{"id":36,"nodeType":"ContractDefinition","src":"120:393:0","nodes":[{"id":10,"nodeType":"FunctionDefinition","src":"139:91:0","nodes":[],"functionSelector":"4777f3cf","implemented":false,"kind":"function","modifiers":[],"name":"envOr","nameLocation":"148:5:0","parameters":{"id":6,"nodeType":"ParameterList","parameters":[{"constant":false,"id":3,"mutability":"mutable","name":"name","nameLocation":"170:4:0","nodeType":"VariableDeclaration","scope":10,"src":"154:20:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":2,"name":"string","nodeType":"ElementaryTypeName","src":"154:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":5,"mutability":"mutable","name":"defaultValue","nameLocation":"181:12:0","nodeType":"VariableDeclaration","scope":10,"src":"176:17:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":4,"name":"bool","nodeType":"ElementaryTypeName","src":"176:4:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"src":"153:41:0"},"returnParameters":{"id":9,"nodeType":"ParameterList","parameters":[{"constant":false,"id":8,"mutability":"mutable","name":"value","nameLocation":"223:5:0","nodeType":"VariableDeclaration","scope":10,"src":"218:10:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":7,"name":"bool","nodeType":"ElementaryTypeName","src":"218:4:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"src":"217:12:0"},"scope":36,"stateMutability":"view","virtual":false,"visibility":"external"},{"id":17,"nodeType":"FunctionDefinition","src":"235:72:0","nodes":[],"functionSelector":"2d0335ab","implemented":false,"kind":"function","modifiers":[],"name":"getNonce","nameLocation":"244:8:0","parameters":{"id":13,"nodeType":"ParameterList","parameters":[{"constant":false,"id":12,"mutability":"mutable","name":"account","nameLocation":"261:7:0","nodeType":"VariableDeclaration","scope":17,"src":"253:15:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":11,"name":"address","nodeType":"ElementaryTypeName","src":"253:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"252:17:0"},"returnParameters":{"id":16,"nodeType":"ParameterList","parameters":[{"constant":false,"id":15,"mutability":"mutable","name":"nonce","nameLocation":"300:5:0","nodeType":"VariableDeclaration","scope":17,"src":"293:12:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"},"typeName":{"id":14,"name":"uint64","nodeType":"ElementaryTypeName","src":"293:6:0","typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}},"visibility":"internal"}],"src":"292:14:0"},"scope":36,"stateMutability":"view","virtual":false,"visibility":"external"},{"id":27,"nodeType":"FunctionDefinition","src":"312:111:0","nodes":[],"functionSelector":"213e4198","implemented":false,"kind":"function","modifiers":[],"name":"parseJsonKeys","nameLocation":"321:13:0","parameters":{"id":22,"nodeType":"ParameterList","parameters":[{"constant":false,"id":19,"mutability":"mutable","name":"json","nameLocation":"351:4:0","nodeType":"VariableDeclaration","scope":27,"src":"335:20:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":18,"name":"string","nodeType":"ElementaryTypeName","src":"335:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":21,"mutability":"mutable","name":"key","nameLocation":"373:3:0","nodeType":"VariableDeclaration","scope":27,"src":"357:19:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":20,"name":"string","nodeType":"ElementaryTypeName","src":"357:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"334:43:0"},"returnParameters":{"id":26,"nodeType":"ParameterList","parameters":[{"constant":false,"id":25,"mutability":"mutable","name":"keys","nameLocation":"417:4:0","nodeType":"VariableDeclaration","scope":27,"src":"401:20:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string[]"},"typeName":{"baseType":{"id":23,"name":"string","nodeType":"ElementaryTypeName","src":"401:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"id":24,"nodeType":"ArrayTypeName","src":"401:8:0","typeDescriptions":{"typeIdentifier":"t_array$_t_string_storage_$dyn_storage_ptr","typeString":"string[]"}},"visibility":"internal"}],"src":"400:22:0"},"scope":36,"stateMutability":"pure","virtual":false,"visibility":"external"},{"id":32,"nodeType":"FunctionDefinition","src":"428:48:0","nodes":[],"functionSelector":"06447d56","implemented":false,"kind":"function","modifiers":[],"name":"startPrank","nameLocation":"437:10:0","parameters":{"id":30,"nodeType":"ParameterList","parameters":[{"constant":false,"id":29,"mutability":"mutable","name":"msgSender","nameLocation":"456:9:0","nodeType":"VariableDeclaration","scope":32,"src":"448:17:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":28,"name":"address","nodeType":"ElementaryTypeName","src":"448:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"447:19:0"},"returnParameters":{"id":31,"nodeType":"ParameterList","parameters":[],"src":"475:0:0"},"scope":36,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":35,"nodeType":"FunctionDefinition","src":"481:30:0","nodes":[],"functionSelector":"90c5013b","implemented":false,"kind":"function","modifiers":[],"name":"stopPrank","nameLocation":"490:9:0","parameters":{"id":33,"nodeType":"ParameterList","parameters":[],"src":"499:2:0"},"returnParameters":{"id":34,"nodeType":"ParameterList","parameters":[],"src":"510:0:0"},"scope":36,"stateMutability":"nonpayable","virtual":false,"visibility":"external"}],"abstract":false,"baseContracts":[],"canonicalName":"Vm","contractDependencies":[],"contractKind":"interface","fullyImplemented":false,"linearizedBaseContracts":[36],"name":"Vm","nameLocation":"130:2:0","scope":383,"usedErrors":[]},{"id":173,"nodeType":"ContractDefinition","src":"568:1622:0","nodes":[{"id":42,"nodeType":"VariableDeclaration","src":"590:86:0","nodes":[],"constant":true,"mutability":"constant","name":"CONSOLE_ADDRESS","nameLocation":"607:15:0","scope":173,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":37,"name":"address","nodeType":"ElementaryTypeName","src":"590:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"value":{"arguments":[{"hexValue":"307830303030303030303030303030303030303036333646366537333646366336353265366336663637","id":40,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"633:42:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"value":"0x000000000000000000636F6e736F6c652e6c6f67"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":39,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"625:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":38,"name":"address","nodeType":"ElementaryTypeName","src":"625:7:0","typeDescriptions":{}}},"id":41,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"625:51:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"},{"id":59,"nodeType":"FunctionDefinition","src":"683:221:0","nodes":[],"body":{"id":58,"nodeType":"Block","src":"842:62:0","nodes":[],"statements":[{"AST":{"nodeType":"YulBlock","src":"861:37:0","statements":[{"nodeType":"YulAssignment","src":"875:13:0","value":{"name":"fnIn","nodeType":"YulIdentifier","src":"884:4:0"},"variableNames":[{"name":"fnOut","nodeType":"YulIdentifier","src":"875:5:0"}]}]},"evmVersion":"london","externalReferences":[{"declaration":48,"isOffset":false,"isSlot":false,"src":"884:4:0","valueSize":1},{"declaration":55,"isOffset":false,"isSlot":false,"src":"875:5:0","valueSize":1}],"id":57,"nodeType":"InlineAssembly","src":"852:46:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"_castLogPayloadViewToPure","nameLocation":"692:25:0","parameters":{"id":49,"nodeType":"ParameterList","parameters":[{"constant":false,"id":48,"mutability":"mutable","name":"fnIn","nameLocation":"764:4:0","nodeType":"VariableDeclaration","scope":59,"src":"727:41:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_function_internal_view$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes) view"},"typeName":{"id":47,"nodeType":"FunctionTypeName","parameterTypes":{"id":45,"nodeType":"ParameterList","parameters":[{"constant":false,"id":44,"mutability":"mutable","name":"","nameLocation":"-1:-1:-1","nodeType":"VariableDeclaration","scope":47,"src":"736:12:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":43,"name":"bytes","nodeType":"ElementaryTypeName","src":"736:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"735:14:0"},"returnParameterTypes":{"id":46,"nodeType":"ParameterList","parameters":[],"src":"764:0:0"},"src":"727:41:0","stateMutability":"view","typeDescriptions":{"typeIdentifier":"t_function_internal_view$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes) view"},"visibility":"internal"},"visibility":"internal"}],"src":"717:57:0"},"returnParameters":{"id":56,"nodeType":"ParameterList","parameters":[{"constant":false,"id":55,"mutability":"mutable","name":"fnOut","nameLocation":"835:5:0","nodeType":"VariableDeclaration","scope":59,"src":"798:42:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes) pure"},"typeName":{"id":54,"nodeType":"FunctionTypeName","parameterTypes":{"id":52,"nodeType":"ParameterList","parameters":[{"constant":false,"id":51,"mutability":"mutable","name":"","nameLocation":"-1:-1:-1","nodeType":"VariableDeclaration","scope":54,"src":"807:12:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":50,"name":"bytes","nodeType":"ElementaryTypeName","src":"807:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"806:14:0"},"returnParameterTypes":{"id":53,"nodeType":"ParameterList","parameters":[],"src":"835:0:0"},"src":"798:42:0","stateMutability":"pure","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes) pure"},"visibility":"internal"},"visibility":"internal"}],"src":"797:44:0"},"scope":173,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":71,"nodeType":"FunctionDefinition","src":"910:133:0","nodes":[],"body":{"id":70,"nodeType":"Block","src":"971:72:0","nodes":[],"statements":[{"expression":{"arguments":[{"id":67,"name":"payload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":61,"src":"1028:7:0","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"arguments":[{"id":65,"name":"_sendLogPayloadView","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":87,"src":"1007:19:0","typeDescriptions":{"typeIdentifier":"t_function_internal_view$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) view"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_function_internal_view$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) view"}],"id":64,"name":"_castLogPayloadViewToPure","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":59,"src":"981:25:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_function_internal_view$_t_bytes_memory_ptr_$returns$__$_$returns$_t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$_$","typeString":"function (function (bytes memory) view) pure returns (function (bytes memory) pure)"}},"id":66,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"981:46:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":68,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"981:55:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":69,"nodeType":"ExpressionStatement","src":"981:55:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"_sendLogPayload","nameLocation":"919:15:0","parameters":{"id":62,"nodeType":"ParameterList","parameters":[{"constant":false,"id":61,"mutability":"mutable","name":"payload","nameLocation":"948:7:0","nodeType":"VariableDeclaration","scope":71,"src":"935:20:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":60,"name":"bytes","nodeType":"ElementaryTypeName","src":"935:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"934:22:0"},"returnParameters":{"id":63,"nodeType":"ParameterList","parameters":[],"src":"971:0:0"},"scope":173,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":87,"nodeType":"FunctionDefinition","src":"1049:380:0","nodes":[],"body":{"id":86,"nodeType":"Block","src":"1113:316:0","nodes":[],"statements":[{"assignments":[77],"declarations":[{"constant":false,"id":77,"mutability":"mutable","name":"payloadLength","nameLocation":"1131:13:0","nodeType":"VariableDeclaration","scope":86,"src":"1123:21:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":76,"name":"uint256","nodeType":"ElementaryTypeName","src":"1123:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"}],"id":80,"initialValue":{"expression":{"id":78,"name":"payload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":73,"src":"1147:7:0","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}},"id":79,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"length","nodeType":"MemberAccess","src":"1147:14:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"nodeType":"VariableDeclarationStatement","src":"1123:38:0"},{"assignments":[82],"declarations":[{"constant":false,"id":82,"mutability":"mutable","name":"consoleAddress","nameLocation":"1179:14:0","nodeType":"VariableDeclaration","scope":86,"src":"1171:22:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":81,"name":"address","nodeType":"ElementaryTypeName","src":"1171:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"id":84,"initialValue":{"id":83,"name":"CONSOLE_ADDRESS","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":42,"src":"1196:15:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"nodeType":"VariableDeclarationStatement","src":"1171:40:0"},{"AST":{"nodeType":"YulBlock","src":"1273:150:0","statements":[{"nodeType":"YulVariableDeclaration","src":"1287:36:0","value":{"arguments":[{"name":"payload","nodeType":"YulIdentifier","src":"1311:7:0"},{"kind":"number","nodeType":"YulLiteral","src":"1320:2:0","type":"","value":"32"}],"functionName":{"name":"add","nodeType":"YulIdentifier","src":"1307:3:0"},"nodeType":"YulFunctionCall","src":"1307:16:0"},"variables":[{"name":"payloadStart","nodeType":"YulTypedName","src":"1291:12:0","type":""}]},{"nodeType":"YulVariableDeclaration","src":"1336:77:0","value":{"arguments":[{"arguments":[],"functionName":{"name":"gas","nodeType":"YulIdentifier","src":"1356:3:0"},"nodeType":"YulFunctionCall","src":"1356:5:0"},{"name":"consoleAddress","nodeType":"YulIdentifier","src":"1363:14:0"},{"name":"payloadStart","nodeType":"YulIdentifier","src":"1379:12:0"},{"name":"payloadLength","nodeType":"YulIdentifier","src":"1393:13:0"},{"kind":"number","nodeType":"YulLiteral","src":"1408:1:0","type":"","value":"0"},{"kind":"number","nodeType":"YulLiteral","src":"1411:1:0","type":"","value":"0"}],"functionName":{"name":"staticcall","nodeType":"YulIdentifier","src":"1345:10:0"},"nodeType":"YulFunctionCall","src":"1345:68:0"},"variables":[{"name":"r","nodeType":"YulTypedName","src":"1340:1:0","type":""}]}]},"documentation":"@solidity memory-safe-assembly","evmVersion":"london","externalReferences":[{"declaration":82,"isOffset":false,"isSlot":false,"src":"1363:14:0","valueSize":1},{"declaration":73,"isOffset":false,"isSlot":false,"src":"1311:7:0","valueSize":1},{"declaration":77,"isOffset":false,"isSlot":false,"src":"1393:13:0","valueSize":1}],"id":85,"nodeType":"InlineAssembly","src":"1264:159:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"_sendLogPayloadView","nameLocation":"1058:19:0","parameters":{"id":74,"nodeType":"ParameterList","parameters":[{"constant":false,"id":73,"mutability":"mutable","name":"payload","nameLocation":"1091:7:0","nodeType":"VariableDeclaration","scope":87,"src":"1078:20:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":72,"name":"bytes","nodeType":"ElementaryTypeName","src":"1078:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"1077:22:0"},"returnParameters":{"id":75,"nodeType":"ParameterList","parameters":[],"src":"1113:0:0"},"scope":173,"stateMutability":"view","virtual":false,"visibility":"private"},{"id":101,"nodeType":"FunctionDefinition","src":"1435:121:0","nodes":[],"body":{"id":100,"nodeType":"Block","src":"1480:76:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e6729","id":95,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"1530:13:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_41304facd9323d75b11bcdd609cb38effffdb05710f7caf0e9b16c6d9d709f50","typeString":"literal_string \"log(string)\""},"value":"log(string)"},{"id":96,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":89,"src":"1545:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_41304facd9323d75b11bcdd609cb38effffdb05710f7caf0e9b16c6d9d709f50","typeString":"literal_string \"log(string)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}],"expression":{"id":93,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"1506:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":94,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"1506:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":97,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1506:42:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":92,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":71,"src":"1490:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":98,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1490:59:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":99,"nodeType":"ExpressionStatement","src":"1490:59:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"1444:3:0","parameters":{"id":90,"nodeType":"ParameterList","parameters":[{"constant":false,"id":89,"mutability":"mutable","name":"p0","nameLocation":"1462:2:0","nodeType":"VariableDeclaration","scope":101,"src":"1448:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":88,"name":"string","nodeType":"ElementaryTypeName","src":"1448:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"1447:18:0"},"returnParameters":{"id":91,"nodeType":"ParameterList","parameters":[],"src":"1480:0:0"},"scope":173,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":118,"nodeType":"FunctionDefinition","src":"1562:139:0","nodes":[],"body":{"id":117,"nodeType":"Block","src":"1616:85:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e672c626f6f6c29","id":111,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"1666:18:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_c3b556354c088fbb43886eb83c2a04bc7089663f964d22be308197a236f5b870","typeString":"literal_string \"log(string,bool)\""},"value":"log(string,bool)"},{"id":112,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":103,"src":"1686:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":113,"name":"p1","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":105,"src":"1690:2:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_c3b556354c088fbb43886eb83c2a04bc7089663f964d22be308197a236f5b870","typeString":"literal_string \"log(string,bool)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_bool","typeString":"bool"}],"expression":{"id":109,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"1642:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":110,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"1642:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":114,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1642:51:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":108,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":71,"src":"1626:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":115,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1626:68:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":116,"nodeType":"ExpressionStatement","src":"1626:68:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"1571:3:0","parameters":{"id":106,"nodeType":"ParameterList","parameters":[{"constant":false,"id":103,"mutability":"mutable","name":"p0","nameLocation":"1589:2:0","nodeType":"VariableDeclaration","scope":118,"src":"1575:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":102,"name":"string","nodeType":"ElementaryTypeName","src":"1575:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":105,"mutability":"mutable","name":"p1","nameLocation":"1598:2:0","nodeType":"VariableDeclaration","scope":118,"src":"1593:7:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":104,"name":"bool","nodeType":"ElementaryTypeName","src":"1593:4:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"src":"1574:27:0"},"returnParameters":{"id":107,"nodeType":"ParameterList","parameters":[],"src":"1616:0:0"},"scope":173,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":135,"nodeType":"FunctionDefinition","src":"1707:145:0","nodes":[],"body":{"id":134,"nodeType":"Block","src":"1764:88:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e672c75696e7432353629","id":128,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"1814:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_b60e72ccf6d57ab53eb84d7e94a9545806ed7f93c4d5673f11a64f03471e584e","typeString":"literal_string \"log(string,uint256)\""},"value":"log(string,uint256)"},{"id":129,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":120,"src":"1837:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":130,"name":"p1","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":122,"src":"1841:2:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_b60e72ccf6d57ab53eb84d7e94a9545806ed7f93c4d5673f11a64f03471e584e","typeString":"literal_string \"log(string,uint256)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_uint256","typeString":"uint256"}],"expression":{"id":126,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"1790:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":127,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"1790:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":131,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1790:54:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":125,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":71,"src":"1774:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":132,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1774:71:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":133,"nodeType":"ExpressionStatement","src":"1774:71:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"1716:3:0","parameters":{"id":123,"nodeType":"ParameterList","parameters":[{"constant":false,"id":120,"mutability":"mutable","name":"p0","nameLocation":"1734:2:0","nodeType":"VariableDeclaration","scope":135,"src":"1720:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":119,"name":"string","nodeType":"ElementaryTypeName","src":"1720:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":122,"mutability":"mutable","name":"p1","nameLocation":"1746:2:0","nodeType":"VariableDeclaration","scope":135,"src":"1738:10:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":121,"name":"uint256","nodeType":"ElementaryTypeName","src":"1738:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"}],"src":"1719:30:0"},"returnParameters":{"id":124,"nodeType":"ParameterList","parameters":[],"src":"1764:0:0"},"scope":173,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":152,"nodeType":"FunctionDefinition","src":"1858:145:0","nodes":[],"body":{"id":151,"nodeType":"Block","src":"1915:88:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e672c6164647265737329","id":145,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"1965:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_319af333460570a1937bf195dd33445c0d0951c59127da6f1f038b9fdce3fd72","typeString":"literal_string \"log(string,address)\""},"value":"log(string,address)"},{"id":146,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":137,"src":"1988:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":147,"name":"p1","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":139,"src":"1992:2:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_319af333460570a1937bf195dd33445c0d0951c59127da6f1f038b9fdce3fd72","typeString":"literal_string \"log(string,address)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":143,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"1941:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":144,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"1941:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":148,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1941:54:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":142,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":71,"src":"1925:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":149,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1925:71:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":150,"nodeType":"ExpressionStatement","src":"1925:71:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"1867:3:0","parameters":{"id":140,"nodeType":"ParameterList","parameters":[{"constant":false,"id":137,"mutability":"mutable","name":"p0","nameLocation":"1885:2:0","nodeType":"VariableDeclaration","scope":152,"src":"1871:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":136,"name":"string","nodeType":"ElementaryTypeName","src":"1871:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":139,"mutability":"mutable","name":"p1","nameLocation":"1897:2:0","nodeType":"VariableDeclaration","scope":152,"src":"1889:10:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":138,"name":"address","nodeType":"ElementaryTypeName","src":"1889:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"1870:30:0"},"returnParameters":{"id":141,"nodeType":"ParameterList","parameters":[],"src":"1915:0:0"},"scope":173,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":172,"nodeType":"FunctionDefinition","src":"2009:179:0","nodes":[],"body":{"id":171,"nodeType":"Block","src":"2090:98:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e672c737472696e672c737472696e6729","id":164,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2140:27:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_2ced7cef693312206c21f0e92e3b54e2e16bf33db5eec350c78866822c665e1f","typeString":"literal_string \"log(string,string,string)\""},"value":"log(string,string,string)"},{"id":165,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":154,"src":"2169:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":166,"name":"p1","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":156,"src":"2173:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":167,"name":"p2","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":158,"src":"2177:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_2ced7cef693312206c21f0e92e3b54e2e16bf33db5eec350c78866822c665e1f","typeString":"literal_string \"log(string,string,string)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}],"expression":{"id":162,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"2116:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":163,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"2116:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":168,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2116:64:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":161,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":71,"src":"2100:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":169,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2100:81:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":170,"nodeType":"ExpressionStatement","src":"2100:81:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"2018:3:0","parameters":{"id":159,"nodeType":"ParameterList","parameters":[{"constant":false,"id":154,"mutability":"mutable","name":"p0","nameLocation":"2036:2:0","nodeType":"VariableDeclaration","scope":172,"src":"2022:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":153,"name":"string","nodeType":"ElementaryTypeName","src":"2022:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":156,"mutability":"mutable","name":"p1","nameLocation":"2054:2:0","nodeType":"VariableDeclaration","scope":172,"src":"2040:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":155,"name":"string","nodeType":"ElementaryTypeName","src":"2040:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":158,"mutability":"mutable","name":"p2","nameLocation":"2072:2:0","nodeType":"VariableDeclaration","scope":172,"src":"2058:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":157,"name":"string","nodeType":"ElementaryTypeName","src":"2058:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"2021:54:0"},"returnParameters":{"id":160,"nodeType":"ParameterList","parameters":[],"src":"2090:0:0"},"scope":173,"stateMutability":"pure","virtual":false,"visibility":"internal"}],"abstract":false,"baseContracts":[],"canonicalName":"console","contractDependencies":[],"contractKind":"library","fullyImplemented":true,"linearizedBaseContracts":[173],"name":"console","nameLocation":"576:7:0","scope":383,"usedErrors":[]},{"id":382,"nodeType":"ContractDefinition","src":"2318:1449:0","nodes":[{"id":188,"nodeType":"VariableDeclaration","src":"2348:94:0","nodes":[],"constant":true,"mutability":"constant","name":"VM_ADDRESS","nameLocation":"2374:10:0","scope":382,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":175,"name":"address","nodeType":"ElementaryTypeName","src":"2348:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"value":{"arguments":[{"arguments":[{"arguments":[{"arguments":[{"hexValue":"6865766d20636865617420636f6465","id":183,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2421:17:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d","typeString":"literal_string \"hevm cheat code\""},"value":"hevm cheat code"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d","typeString":"literal_string \"hevm cheat code\""}],"id":182,"name":"keccak256","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-8,"src":"2411:9:0","typeDescriptions":{"typeIdentifier":"t_function_keccak256_pure$_t_bytes_memory_ptr_$returns$_t_bytes32_$","typeString":"function (bytes memory) pure returns (bytes32)"}},"id":184,"isConstant":false,"isLValue":false,"isPure":true,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2411:28:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes32","typeString":"bytes32"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes32","typeString":"bytes32"}],"id":181,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2403:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint256_$","typeString":"type(uint256)"},"typeName":{"id":180,"name":"uint256","nodeType":"ElementaryTypeName","src":"2403:7:0","typeDescriptions":{}}},"id":185,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2403:37:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint256","typeString":"uint256"}],"id":179,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2395:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":178,"name":"uint160","nodeType":"ElementaryTypeName","src":"2395:7:0","typeDescriptions":{}}},"id":186,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2395:46:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":177,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2387:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":176,"name":"address","nodeType":"ElementaryTypeName","src":"2387:7:0","typeDescriptions":{}}},"id":187,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2387:55:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"},{"id":194,"nodeType":"VariableDeclaration","src":"2448:40:0","nodes":[],"constant":true,"mutability":"constant","name":"vm","nameLocation":"2469:2:0","scope":382,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$36","typeString":"contract Vm"},"typeName":{"id":190,"nodeType":"UserDefinedTypeName","pathNode":{"id":189,"name":"Vm","nodeType":"IdentifierPath","referencedDeclaration":36,"src":"2448:2:0"},"referencedDeclaration":36,"src":"2448:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$36","typeString":"contract Vm"}},"value":{"arguments":[{"id":192,"name":"VM_ADDRESS","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":188,"src":"2477:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":191,"name":"Vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":36,"src":"2474:2:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_Vm_$36_$","typeString":"type(contract Vm)"}},"id":193,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2474:14:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$36","typeString":"contract Vm"}},"visibility":"internal"},{"id":357,"nodeType":"FunctionDefinition","src":"2578:949:0","nodes":[],"body":{"id":356,"nodeType":"Block","src":"2600:927:0","nodes":[],"statements":[{"assignments":[199],"declarations":[{"constant":false,"id":199,"mutability":"mutable","name":"x","nameLocation":"2615:1:0","nodeType":"VariableDeclaration","scope":356,"src":"2610:6:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":198,"name":"bool","nodeType":"ElementaryTypeName","src":"2610:4:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"id":205,"initialValue":{"arguments":[{"hexValue":"4558414d504c455f424f4f4c","id":202,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2628:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_a634dae177a0e138ae7aaa2afae347412e148992e88c7aabd33ee71be146cb7f","typeString":"literal_string \"EXAMPLE_BOOL\""},"value":"EXAMPLE_BOOL"},{"hexValue":"66616c7365","id":203,"isConstant":false,"isLValue":false,"isPure":true,"kind":"bool","lValueRequested":false,"nodeType":"Literal","src":"2644:5:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"value":"false"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_a634dae177a0e138ae7aaa2afae347412e148992e88c7aabd33ee71be146cb7f","typeString":"literal_string \"EXAMPLE_BOOL\""},{"typeIdentifier":"t_bool","typeString":"bool"}],"expression":{"id":200,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":194,"src":"2619:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$36","typeString":"contract Vm"}},"id":201,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"envOr","nodeType":"MemberAccess","referencedDeclaration":10,"src":"2619:8:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$_t_bool_$returns$_t_bool_$","typeString":"function (string memory,bool) view external returns (bool)"}},"id":204,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2619:31:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"nodeType":"VariableDeclarationStatement","src":"2610:40:0"},{"expression":{"arguments":[{"hexValue":"626f6f6c2076616c75652066726f6d20656e76","id":209,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2672:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_5a607d0b5a1295325aa8901721d78ba402601bba6f62cebdd5235dd0204a590b","typeString":"literal_string \"bool value from env\""},"value":"bool value from env"},{"id":210,"name":"x","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":199,"src":"2695:1:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_5a607d0b5a1295325aa8901721d78ba402601bba6f62cebdd5235dd0204a590b","typeString":"literal_string \"bool value from env\""},{"typeIdentifier":"t_bool","typeString":"bool"}],"expression":{"id":206,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"2660:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":208,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":118,"src":"2660:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_bool_$returns$__$","typeString":"function (string memory,bool) pure"}},"id":211,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2660:37:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":212,"nodeType":"ExpressionStatement","src":"2660:37:0"},{"expression":{"arguments":[{"hexValue":"636f6e74726163742061646472","id":216,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2720:15:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_fa50728770d00fe8f6a0592f3565bbfaf063ee4077f1f5bbc003d091d33cd0c4","typeString":"literal_string \"contract addr\""},"value":"contract addr"},{"arguments":[{"id":219,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"2745:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}],"id":218,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2737:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":217,"name":"address","nodeType":"ElementaryTypeName","src":"2737:7:0","typeDescriptions":{}}},"id":220,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2737:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_fa50728770d00fe8f6a0592f3565bbfaf063ee4077f1f5bbc003d091d33cd0c4","typeString":"literal_string \"contract addr\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":213,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"2708:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":215,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":152,"src":"2708:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":221,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2708:43:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":222,"nodeType":"ExpressionStatement","src":"2708:43:0"},{"expression":{"arguments":[{"hexValue":"636f6e7472616374206e6f6e6365","id":226,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2773:16:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_3a23091615a5de8c0a35ffd8857a37e2c4e0b72f3ef8a34d6caf65efcd562e2f","typeString":"literal_string \"contract nonce\""},"value":"contract nonce"},{"arguments":[{"arguments":[{"id":231,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"2811:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}],"id":230,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2803:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":229,"name":"address","nodeType":"ElementaryTypeName","src":"2803:7:0","typeDescriptions":{}}},"id":232,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2803:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":227,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":194,"src":"2791:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$36","typeString":"contract Vm"}},"id":228,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"getNonce","nodeType":"MemberAccess","referencedDeclaration":17,"src":"2791:11:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_address_$returns$_t_uint64_$","typeString":"function (address) view external returns (uint64)"}},"id":233,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2791:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_3a23091615a5de8c0a35ffd8857a37e2c4e0b72f3ef8a34d6caf65efcd562e2f","typeString":"literal_string \"contract nonce\""},{"typeIdentifier":"t_uint64","typeString":"uint64"}],"expression":{"id":223,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"2761:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":225,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":135,"src":"2761:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_uint256_$returns$__$","typeString":"function (string memory,uint256) pure"}},"id":234,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2761:57:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":235,"nodeType":"ExpressionStatement","src":"2761:57:0"},{"expression":{"arguments":[{"hexValue":"73656e6465722061646472","id":239,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2840:13:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_8125ca2decf812b25b65606ff16dad37cb198ff0433485a7926e50feafacfc35","typeString":"literal_string \"sender addr\""},"value":"sender addr"},{"arguments":[{"expression":{"id":242,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"2863:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":243,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"sender","nodeType":"MemberAccess","src":"2863:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":241,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2855:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":240,"name":"address","nodeType":"ElementaryTypeName","src":"2855:7:0","typeDescriptions":{}}},"id":244,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2855:19:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_8125ca2decf812b25b65606ff16dad37cb198ff0433485a7926e50feafacfc35","typeString":"literal_string \"sender addr\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":236,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"2828:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":238,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":152,"src":"2828:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":245,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2828:47:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":246,"nodeType":"ExpressionStatement","src":"2828:47:0"},{"expression":{"arguments":[{"hexValue":"73656e646572206e6f6e6365","id":250,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2897:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_db7deb43f2f9e0404016de53b7e64c4976b54149581f7534daae2551e8cf4e40","typeString":"literal_string \"sender nonce\""},"value":"sender nonce"},{"arguments":[{"arguments":[{"expression":{"id":255,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"2933:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":256,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"sender","nodeType":"MemberAccess","src":"2933:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":254,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2925:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":253,"name":"address","nodeType":"ElementaryTypeName","src":"2925:7:0","typeDescriptions":{}}},"id":257,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2925:19:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":251,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":194,"src":"2913:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$36","typeString":"contract Vm"}},"id":252,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"getNonce","nodeType":"MemberAccess","referencedDeclaration":17,"src":"2913:11:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_address_$returns$_t_uint64_$","typeString":"function (address) view external returns (uint64)"}},"id":258,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2913:32:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_db7deb43f2f9e0404016de53b7e64c4976b54149581f7534daae2551e8cf4e40","typeString":"literal_string \"sender nonce\""},{"typeIdentifier":"t_uint64","typeString":"uint64"}],"expression":{"id":247,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"2885:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":249,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":135,"src":"2885:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_uint256_$returns$__$","typeString":"function (string memory,uint256) pure"}},"id":259,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2885:61:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":260,"nodeType":"ExpressionStatement","src":"2885:61:0"},{"assignments":[262],"declarations":[{"constant":false,"id":262,"mutability":"mutable","name":"json","nameLocation":"2971:4:0","nodeType":"VariableDeclaration","scope":356,"src":"2957:18:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":261,"name":"string","nodeType":"ElementaryTypeName","src":"2957:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"id":264,"initialValue":{"hexValue":"7b22726f6f745f6b6579223a205b7b2261223a20312c202262223a20327d5d7d","id":263,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2978:34:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_e95522e99766888d0261f55bd1eae5e3f3e26eaf009a16e2433eafaf0a4ecdf2","typeString":"literal_string \"{\"root_key\": [{\"a\": 1, \"b\": 2}]}\""},"value":"{\"root_key\": [{\"a\": 1, \"b\": 2}]}"},"nodeType":"VariableDeclarationStatement","src":"2957:55:0"},{"assignments":[269],"declarations":[{"constant":false,"id":269,"mutability":"mutable","name":"keys","nameLocation":"3038:4:0","nodeType":"VariableDeclaration","scope":356,"src":"3022:20:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string[]"},"typeName":{"baseType":{"id":267,"name":"string","nodeType":"ElementaryTypeName","src":"3022:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"id":268,"nodeType":"ArrayTypeName","src":"3022:8:0","typeDescriptions":{"typeIdentifier":"t_array$_t_string_storage_$dyn_storage_ptr","typeString":"string[]"}},"visibility":"internal"}],"id":275,"initialValue":{"arguments":[{"id":272,"name":"json","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":262,"src":"3062:4:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"hexValue":"2e726f6f745f6b65795b305d","id":273,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3068:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_d82f67100edb80050915e1ec4b565c9a8319a22efb1075e1298b7bb60101d266","typeString":"literal_string \".root_key[0]\""},"value":".root_key[0]"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_stringliteral_d82f67100edb80050915e1ec4b565c9a8319a22efb1075e1298b7bb60101d266","typeString":"literal_string \".root_key[0]\""}],"expression":{"id":270,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":194,"src":"3045:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$36","typeString":"contract Vm"}},"id":271,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"parseJsonKeys","nodeType":"MemberAccess","referencedDeclaration":27,"src":"3045:16:0","typeDescriptions":{"typeIdentifier":"t_function_external_pure$_t_string_memory_ptr_$_t_string_memory_ptr_$returns$_t_array$_t_string_memory_ptr_$dyn_memory_ptr_$","typeString":"function (string memory,string memory) pure external returns (string memory[] memory)"}},"id":274,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3045:38:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string memory[] memory"}},"nodeType":"VariableDeclarationStatement","src":"3022:61:0"},{"expression":{"arguments":[{"hexValue":"6b657973","id":279,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3105:6:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_f29790a80c4ce5f42f59892f424f9c92856c6b656c3378e2cf305b260c6f4195","typeString":"literal_string \"keys\""},"value":"keys"},{"baseExpression":{"id":280,"name":"keys","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":269,"src":"3113:4:0","typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string memory[] memory"}},"id":282,"indexExpression":{"hexValue":"30","id":281,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"3118:1:0","typeDescriptions":{"typeIdentifier":"t_rational_0_by_1","typeString":"int_const 0"},"value":"0"},"isConstant":false,"isLValue":true,"isPure":false,"lValueRequested":false,"nodeType":"IndexAccess","src":"3113:7:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"baseExpression":{"id":283,"name":"keys","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":269,"src":"3122:4:0","typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string memory[] memory"}},"id":285,"indexExpression":{"hexValue":"31","id":284,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"3127:1:0","typeDescriptions":{"typeIdentifier":"t_rational_1_by_1","typeString":"int_const 1"},"value":"1"},"isConstant":false,"isLValue":true,"isPure":false,"lValueRequested":false,"nodeType":"IndexAccess","src":"3122:7:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_f29790a80c4ce5f42f59892f424f9c92856c6b656c3378e2cf305b260c6f4195","typeString":"literal_string \"keys\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}],"expression":{"id":276,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"3093:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":278,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":172,"src":"3093:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_string_memory_ptr_$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory,string memory,string memory) pure"}},"id":286,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3093:37:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":287,"nodeType":"ExpressionStatement","src":"3093:37:0"},{"expression":{"arguments":[{"hexValue":"66726f6d206f726967696e616c","id":291,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3152:15:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_77928970c8757d110f3c23e003246f49e0de890480ba9717ba659b2f56f316b2","typeString":"literal_string \"from original\""},"value":"from original"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_77928970c8757d110f3c23e003246f49e0de890480ba9717ba659b2f56f316b2","typeString":"literal_string \"from original\""}],"expression":{"id":288,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3141:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}},"id":290,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"hello","nodeType":"MemberAccess","referencedDeclaration":381,"src":"3141:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) view external"}},"id":292,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3141:27:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":293,"nodeType":"ExpressionStatement","src":"3141:27:0"},{"expression":{"arguments":[{"arguments":[{"arguments":[{"hexValue":"30783432","id":301,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"3208:4:0","typeDescriptions":{"typeIdentifier":"t_rational_66_by_1","typeString":"int_const 66"},"value":"0x42"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_66_by_1","typeString":"int_const 66"}],"id":300,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3200:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":299,"name":"uint160","nodeType":"ElementaryTypeName","src":"3200:7:0","typeDescriptions":{}}},"id":302,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3200:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":298,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3192:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":297,"name":"address","nodeType":"ElementaryTypeName","src":"3192:7:0","typeDescriptions":{}}},"id":303,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3192:22:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":294,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":194,"src":"3178:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$36","typeString":"contract Vm"}},"id":296,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"startPrank","nodeType":"MemberAccess","referencedDeclaration":32,"src":"3178:13:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_address_$returns$__$","typeString":"function (address) external"}},"id":304,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3178:37:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":305,"nodeType":"ExpressionStatement","src":"3178:37:0"},{"expression":{"arguments":[{"hexValue":"66726f6d207072616e6b2031","id":309,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3236:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_42b34abfe37a8b0add910cda7b4a379e6538fa7a1dcafce47a02bd38f6c88e2a","typeString":"literal_string \"from prank 1\""},"value":"from prank 1"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_42b34abfe37a8b0add910cda7b4a379e6538fa7a1dcafce47a02bd38f6c88e2a","typeString":"literal_string \"from prank 1\""}],"expression":{"id":306,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3225:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}},"id":308,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"hello","nodeType":"MemberAccess","referencedDeclaration":381,"src":"3225:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) view external"}},"id":310,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3225:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":311,"nodeType":"ExpressionStatement","src":"3225:26:0"},{"expression":{"arguments":[{"hexValue":"706172656e742073636f7065206d73672e73656e646572","id":315,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3273:25:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_83ec9246154d8845de47aafc5c2865c9985d2efe84472c27283879f2fbf5cc94","typeString":"literal_string \"parent scope msg.sender\""},"value":"parent scope msg.sender"},{"arguments":[{"expression":{"id":318,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"3308:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":319,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"sender","nodeType":"MemberAccess","src":"3308:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":317,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3300:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":316,"name":"address","nodeType":"ElementaryTypeName","src":"3300:7:0","typeDescriptions":{}}},"id":320,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3300:19:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_83ec9246154d8845de47aafc5c2865c9985d2efe84472c27283879f2fbf5cc94","typeString":"literal_string \"parent scope msg.sender\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":312,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"3261:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":314,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":152,"src":"3261:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":321,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3261:59:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":322,"nodeType":"ExpressionStatement","src":"3261:59:0"},{"expression":{"arguments":[{"hexValue":"706172656e742073636f706520636f6e74726163742e61646472","id":326,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3342:28:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_97df66250e0b2b48f0ec8d0e01eb1b8ca012d95f1572895622aa1ea433e5570f","typeString":"literal_string \"parent scope contract.addr\""},"value":"parent scope contract.addr"},{"arguments":[{"id":329,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3380:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}],"id":328,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3372:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":327,"name":"address","nodeType":"ElementaryTypeName","src":"3372:7:0","typeDescriptions":{}}},"id":330,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3372:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_97df66250e0b2b48f0ec8d0e01eb1b8ca012d95f1572895622aa1ea433e5570f","typeString":"literal_string \"parent scope contract.addr\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":323,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"3330:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":325,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":152,"src":"3330:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":331,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3330:56:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":332,"nodeType":"ExpressionStatement","src":"3330:56:0"},{"expression":{"arguments":[{"hexValue":"66726f6d207072616e6b2032","id":336,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3407:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_a38a34f8cad750a79aa097a92971f8f405b51ee9d53d25c5b14fc129ba3684bb","typeString":"literal_string \"from prank 2\""},"value":"from prank 2"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_a38a34f8cad750a79aa097a92971f8f405b51ee9d53d25c5b14fc129ba3684bb","typeString":"literal_string \"from prank 2\""}],"expression":{"id":333,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3396:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}},"id":335,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"hello","nodeType":"MemberAccess","referencedDeclaration":381,"src":"3396:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) view external"}},"id":337,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3396:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":338,"nodeType":"ExpressionStatement","src":"3396:26:0"},{"expression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":339,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":194,"src":"3432:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$36","typeString":"contract Vm"}},"id":341,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"stopPrank","nodeType":"MemberAccess","referencedDeclaration":35,"src":"3432:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$__$returns$__$","typeString":"function () external"}},"id":342,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3432:14:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":343,"nodeType":"ExpressionStatement","src":"3432:14:0"},{"expression":{"arguments":[{"hexValue":"66726f6d206f726967696e616c20616761696e","id":347,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3467:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_0c805c6579e20a9c4c8e11aeab23330910a9f2da629191dc119d1730e8ed6860","typeString":"literal_string \"from original again\""},"value":"from original again"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_0c805c6579e20a9c4c8e11aeab23330910a9f2da629191dc119d1730e8ed6860","typeString":"literal_string \"from original again\""}],"expression":{"id":344,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3456:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$382","typeString":"contract ScriptExample"}},"id":346,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"hello","nodeType":"MemberAccess","referencedDeclaration":381,"src":"3456:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) view external"}},"id":348,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3456:33:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":349,"nodeType":"ExpressionStatement","src":"3456:33:0"},{"expression":{"arguments":[{"hexValue":"646f6e6521","id":353,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3512:7:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_080382d5c9e9e7c5e3d1d33f5e7422740375955180fadff167d8130e0c35f3fc","typeString":"literal_string \"done!\""},"value":"done!"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_080382d5c9e9e7c5e3d1d33f5e7422740375955180fadff167d8130e0c35f3fc","typeString":"literal_string \"done!\""}],"expression":{"id":350,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"3500:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":352,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":101,"src":"3500:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":354,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3500:20:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":355,"nodeType":"ExpressionStatement","src":"3500:20:0"}]},"documentation":{"id":195,"nodeType":"StructuredDocumentation","src":"2495:78:0","text":"@notice example function, runs through basic cheat-codes and console logs."},"functionSelector":"c0406226","implemented":true,"kind":"function","modifiers":[],"name":"run","nameLocation":"2587:3:0","parameters":{"id":196,"nodeType":"ParameterList","parameters":[],"src":"2590:2:0"},"returnParameters":{"id":197,"nodeType":"ParameterList","parameters":[],"src":"2600:0:0"},"scope":382,"stateMutability":"nonpayable","virtual":false,"visibility":"public"},{"id":381,"nodeType":"FunctionDefinition","src":"3622:143:0","nodes":[],"body":{"id":380,"nodeType":"Block","src":"3671:94:0","nodes":[],"statements":[{"expression":{"arguments":[{"id":366,"name":"_v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":360,"src":"3693:2:0","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}],"expression":{"id":363,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"3681:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":365,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":101,"src":"3681:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":367,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3681:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":368,"nodeType":"ExpressionStatement","src":"3681:15:0"},{"expression":{"arguments":[{"hexValue":"68656c6c6f206d73672e73656e646572","id":372,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3718:18:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_b3cc13bc51228b2c4c4334d82a4772908254dc0e1c512893dd16208ef13efb8e","typeString":"literal_string \"hello msg.sender\""},"value":"hello msg.sender"},{"arguments":[{"expression":{"id":375,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"3746:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":376,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"sender","nodeType":"MemberAccess","src":"3746:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":374,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3738:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":373,"name":"address","nodeType":"ElementaryTypeName","src":"3738:7:0","typeDescriptions":{}}},"id":377,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3738:19:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_b3cc13bc51228b2c4c4334d82a4772908254dc0e1c512893dd16208ef13efb8e","typeString":"literal_string \"hello msg.sender\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":369,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"3706:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$173_$","typeString":"type(library console)"}},"id":371,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":152,"src":"3706:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":378,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3706:52:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":379,"nodeType":"ExpressionStatement","src":"3706:52:0"}]},"documentation":{"id":358,"nodeType":"StructuredDocumentation","src":"3533:84:0","text":"@notice example external function, to force a CALL, and test vm.startPrank with."},"functionSelector":"a777d0dc","implemented":true,"kind":"function","modifiers":[],"name":"hello","nameLocation":"3631:5:0","parameters":{"id":361,"nodeType":"ParameterList","parameters":[{"constant":false,"id":360,"mutability":"mutable","name":"_v","nameLocation":"3653:2:0","nodeType":"VariableDeclaration","scope":381,"src":"3637:18:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":359,"name":"string","nodeType":"ElementaryTypeName","src":"3637:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"3636:20:0"},"returnParameters":{"id":362,"nodeType":"ParameterList","parameters":[],"src":"3671:0:0"},"scope":382,"stateMutability":"view","virtual":false,"visibility":"external"}],"abstract":false,"baseContracts":[],"canonicalName":"ScriptExample","contractDependencies":[],"contractKind":"contract","documentation":{"id":174,"nodeType":"StructuredDocumentation","src":"2192:126:0","text":"@title ScriptExample\n @notice ScriptExample is an example script. The Go forge script code tests that it can run this."},"fullyImplemented":true,"linearizedBaseContracts":[382],"name":"ScriptExample","nameLocation":"2327:13:0","scope":383,"usedErrors":[]}],"license":"MIT"},"id":0} +\ No newline at end of file ++{"abi":[],"bytecode":{"object":"0x602d6037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea164736f6c634300080f000a","sourceMap":"791:1622:0:-:0;;;;;;;;;;;;;;;-1:-1:-1;;;791:1622:0;;;;;;;;;;;;;;;;;","linkReferences":{}},"deployedBytecode":{"object":"0x73000000000000000000000000000000000000000030146080604052600080fdfea164736f6c634300080f000a","sourceMap":"791:1622:0:-:0;;;;;;;;","linkReferences":{}},"methodIdentifiers":{},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.15+commit.e14f2714\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"scripts/ScriptExample.s.sol\":\"console\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[]},\"sources\":{\"scripts/ScriptExample.s.sol\":{\"keccak256\":\"0x8d1dfa41908e7ccc3a498a2a2aa51c5275bedbb904ce32d08f8598e36f896d8d\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://5117bb7158363cae8b9dc0508d2852692fd36172f1c699ff680afbb5acebe1f3\",\"dweb:/ipfs/QmQdahJ8SPKfJ4yea5Ge9qaj5qh1TxVffhHvaWytBaL95h\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.15+commit.e14f2714"},"language":"Solidity","output":{"abi":[],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"remappings":[],"optimizer":{"enabled":true,"runs":999999},"metadata":{"bytecodeHash":"none"},"compilationTarget":{"scripts/ScriptExample.s.sol":"console"},"evmVersion":"london","libraries":{}},"sources":{"scripts/ScriptExample.s.sol":{"keccak256":"0x8d1dfa41908e7ccc3a498a2a2aa51c5275bedbb904ce32d08f8598e36f896d8d","urls":["bzz-raw://5117bb7158363cae8b9dc0508d2852692fd36172f1c699ff680afbb5acebe1f3","dweb:/ipfs/QmQdahJ8SPKfJ4yea5Ge9qaj5qh1TxVffhHvaWytBaL95h"],"license":"MIT"}},"version":1},"storageLayout":{"storage":[],"types":{}},"userdoc":{"version":1,"kind":"user"},"devdoc":{"version":1,"kind":"dev"},"ast":{"absolutePath":"scripts/ScriptExample.s.sol","id":720,"exportedSymbols":{"FooBar":[719],"ScriptExample":[706],"Vm":[55],"console":[192]},"nodeType":"SourceUnit","src":"32:5967:0","nodes":[{"id":1,"nodeType":"PragmaDirective","src":"32:23:0","nodes":[],"literals":["solidity","0.8",".15"]},{"id":55,"nodeType":"ContractDefinition","src":"120:616:0","nodes":[{"id":10,"nodeType":"FunctionDefinition","src":"139:91:0","nodes":[],"functionSelector":"4777f3cf","implemented":false,"kind":"function","modifiers":[],"name":"envOr","nameLocation":"148:5:0","parameters":{"id":6,"nodeType":"ParameterList","parameters":[{"constant":false,"id":3,"mutability":"mutable","name":"name","nameLocation":"170:4:0","nodeType":"VariableDeclaration","scope":10,"src":"154:20:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":2,"name":"string","nodeType":"ElementaryTypeName","src":"154:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":5,"mutability":"mutable","name":"defaultValue","nameLocation":"181:12:0","nodeType":"VariableDeclaration","scope":10,"src":"176:17:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":4,"name":"bool","nodeType":"ElementaryTypeName","src":"176:4:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"src":"153:41:0"},"returnParameters":{"id":9,"nodeType":"ParameterList","parameters":[{"constant":false,"id":8,"mutability":"mutable","name":"value","nameLocation":"223:5:0","nodeType":"VariableDeclaration","scope":10,"src":"218:10:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":7,"name":"bool","nodeType":"ElementaryTypeName","src":"218:4:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"src":"217:12:0"},"scope":55,"stateMutability":"view","virtual":false,"visibility":"external"},{"id":17,"nodeType":"FunctionDefinition","src":"235:72:0","nodes":[],"functionSelector":"2d0335ab","implemented":false,"kind":"function","modifiers":[],"name":"getNonce","nameLocation":"244:8:0","parameters":{"id":13,"nodeType":"ParameterList","parameters":[{"constant":false,"id":12,"mutability":"mutable","name":"account","nameLocation":"261:7:0","nodeType":"VariableDeclaration","scope":17,"src":"253:15:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":11,"name":"address","nodeType":"ElementaryTypeName","src":"253:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"252:17:0"},"returnParameters":{"id":16,"nodeType":"ParameterList","parameters":[{"constant":false,"id":15,"mutability":"mutable","name":"nonce","nameLocation":"300:5:0","nodeType":"VariableDeclaration","scope":17,"src":"293:12:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"},"typeName":{"id":14,"name":"uint64","nodeType":"ElementaryTypeName","src":"293:6:0","typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}},"visibility":"internal"}],"src":"292:14:0"},"scope":55,"stateMutability":"view","virtual":false,"visibility":"external"},{"id":27,"nodeType":"FunctionDefinition","src":"312:111:0","nodes":[],"functionSelector":"213e4198","implemented":false,"kind":"function","modifiers":[],"name":"parseJsonKeys","nameLocation":"321:13:0","parameters":{"id":22,"nodeType":"ParameterList","parameters":[{"constant":false,"id":19,"mutability":"mutable","name":"json","nameLocation":"351:4:0","nodeType":"VariableDeclaration","scope":27,"src":"335:20:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":18,"name":"string","nodeType":"ElementaryTypeName","src":"335:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":21,"mutability":"mutable","name":"key","nameLocation":"373:3:0","nodeType":"VariableDeclaration","scope":27,"src":"357:19:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":20,"name":"string","nodeType":"ElementaryTypeName","src":"357:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"334:43:0"},"returnParameters":{"id":26,"nodeType":"ParameterList","parameters":[{"constant":false,"id":25,"mutability":"mutable","name":"keys","nameLocation":"417:4:0","nodeType":"VariableDeclaration","scope":27,"src":"401:20:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string[]"},"typeName":{"baseType":{"id":23,"name":"string","nodeType":"ElementaryTypeName","src":"401:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"id":24,"nodeType":"ArrayTypeName","src":"401:8:0","typeDescriptions":{"typeIdentifier":"t_array$_t_string_storage_$dyn_storage_ptr","typeString":"string[]"}},"visibility":"internal"}],"src":"400:22:0"},"scope":55,"stateMutability":"pure","virtual":false,"visibility":"external"},{"id":32,"nodeType":"FunctionDefinition","src":"428:48:0","nodes":[],"functionSelector":"06447d56","implemented":false,"kind":"function","modifiers":[],"name":"startPrank","nameLocation":"437:10:0","parameters":{"id":30,"nodeType":"ParameterList","parameters":[{"constant":false,"id":29,"mutability":"mutable","name":"msgSender","nameLocation":"456:9:0","nodeType":"VariableDeclaration","scope":32,"src":"448:17:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":28,"name":"address","nodeType":"ElementaryTypeName","src":"448:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"447:19:0"},"returnParameters":{"id":31,"nodeType":"ParameterList","parameters":[],"src":"475:0:0"},"scope":55,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":35,"nodeType":"FunctionDefinition","src":"481:30:0","nodes":[],"functionSelector":"90c5013b","implemented":false,"kind":"function","modifiers":[],"name":"stopPrank","nameLocation":"490:9:0","parameters":{"id":33,"nodeType":"ParameterList","parameters":[],"src":"499:2:0"},"returnParameters":{"id":34,"nodeType":"ParameterList","parameters":[],"src":"510:0:0"},"scope":55,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":38,"nodeType":"FunctionDefinition","src":"516:30:0","nodes":[],"functionSelector":"afc98040","implemented":false,"kind":"function","modifiers":[],"name":"broadcast","nameLocation":"525:9:0","parameters":{"id":36,"nodeType":"ParameterList","parameters":[],"src":"534:2:0"},"returnParameters":{"id":37,"nodeType":"ParameterList","parameters":[],"src":"545:0:0"},"scope":55,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":43,"nodeType":"FunctionDefinition","src":"551:47:0","nodes":[],"functionSelector":"e6962cdb","implemented":false,"kind":"function","modifiers":[],"name":"broadcast","nameLocation":"560:9:0","parameters":{"id":41,"nodeType":"ParameterList","parameters":[{"constant":false,"id":40,"mutability":"mutable","name":"msgSender","nameLocation":"578:9:0","nodeType":"VariableDeclaration","scope":43,"src":"570:17:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":39,"name":"address","nodeType":"ElementaryTypeName","src":"570:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"569:19:0"},"returnParameters":{"id":42,"nodeType":"ParameterList","parameters":[],"src":"597:0:0"},"scope":55,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":48,"nodeType":"FunctionDefinition","src":"603:52:0","nodes":[],"functionSelector":"7fec2a8d","implemented":false,"kind":"function","modifiers":[],"name":"startBroadcast","nameLocation":"612:14:0","parameters":{"id":46,"nodeType":"ParameterList","parameters":[{"constant":false,"id":45,"mutability":"mutable","name":"msgSender","nameLocation":"635:9:0","nodeType":"VariableDeclaration","scope":48,"src":"627:17:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":44,"name":"address","nodeType":"ElementaryTypeName","src":"627:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"626:19:0"},"returnParameters":{"id":47,"nodeType":"ParameterList","parameters":[],"src":"654:0:0"},"scope":55,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":51,"nodeType":"FunctionDefinition","src":"660:35:0","nodes":[],"functionSelector":"7fb5297f","implemented":false,"kind":"function","modifiers":[],"name":"startBroadcast","nameLocation":"669:14:0","parameters":{"id":49,"nodeType":"ParameterList","parameters":[],"src":"683:2:0"},"returnParameters":{"id":50,"nodeType":"ParameterList","parameters":[],"src":"694:0:0"},"scope":55,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":54,"nodeType":"FunctionDefinition","src":"700:34:0","nodes":[],"functionSelector":"76eadd36","implemented":false,"kind":"function","modifiers":[],"name":"stopBroadcast","nameLocation":"709:13:0","parameters":{"id":52,"nodeType":"ParameterList","parameters":[],"src":"722:2:0"},"returnParameters":{"id":53,"nodeType":"ParameterList","parameters":[],"src":"733:0:0"},"scope":55,"stateMutability":"nonpayable","virtual":false,"visibility":"external"}],"abstract":false,"baseContracts":[],"canonicalName":"Vm","contractDependencies":[],"contractKind":"interface","fullyImplemented":false,"linearizedBaseContracts":[55],"name":"Vm","nameLocation":"130:2:0","scope":720,"usedErrors":[]},{"id":192,"nodeType":"ContractDefinition","src":"791:1622:0","nodes":[{"id":61,"nodeType":"VariableDeclaration","src":"813:86:0","nodes":[],"constant":true,"mutability":"constant","name":"CONSOLE_ADDRESS","nameLocation":"830:15:0","scope":192,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":56,"name":"address","nodeType":"ElementaryTypeName","src":"813:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"value":{"arguments":[{"hexValue":"307830303030303030303030303030303030303036333646366537333646366336353265366336663637","id":59,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"856:42:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"value":"0x000000000000000000636F6e736F6c652e6c6f67"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":58,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"848:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":57,"name":"address","nodeType":"ElementaryTypeName","src":"848:7:0","typeDescriptions":{}}},"id":60,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"848:51:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"},{"id":78,"nodeType":"FunctionDefinition","src":"906:221:0","nodes":[],"body":{"id":77,"nodeType":"Block","src":"1065:62:0","nodes":[],"statements":[{"AST":{"nodeType":"YulBlock","src":"1084:37:0","statements":[{"nodeType":"YulAssignment","src":"1098:13:0","value":{"name":"fnIn","nodeType":"YulIdentifier","src":"1107:4:0"},"variableNames":[{"name":"fnOut","nodeType":"YulIdentifier","src":"1098:5:0"}]}]},"evmVersion":"london","externalReferences":[{"declaration":67,"isOffset":false,"isSlot":false,"src":"1107:4:0","valueSize":1},{"declaration":74,"isOffset":false,"isSlot":false,"src":"1098:5:0","valueSize":1}],"id":76,"nodeType":"InlineAssembly","src":"1075:46:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"_castLogPayloadViewToPure","nameLocation":"915:25:0","parameters":{"id":68,"nodeType":"ParameterList","parameters":[{"constant":false,"id":67,"mutability":"mutable","name":"fnIn","nameLocation":"987:4:0","nodeType":"VariableDeclaration","scope":78,"src":"950:41:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_function_internal_view$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes) view"},"typeName":{"id":66,"nodeType":"FunctionTypeName","parameterTypes":{"id":64,"nodeType":"ParameterList","parameters":[{"constant":false,"id":63,"mutability":"mutable","name":"","nameLocation":"-1:-1:-1","nodeType":"VariableDeclaration","scope":66,"src":"959:12:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":62,"name":"bytes","nodeType":"ElementaryTypeName","src":"959:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"958:14:0"},"returnParameterTypes":{"id":65,"nodeType":"ParameterList","parameters":[],"src":"987:0:0"},"src":"950:41:0","stateMutability":"view","typeDescriptions":{"typeIdentifier":"t_function_internal_view$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes) view"},"visibility":"internal"},"visibility":"internal"}],"src":"940:57:0"},"returnParameters":{"id":75,"nodeType":"ParameterList","parameters":[{"constant":false,"id":74,"mutability":"mutable","name":"fnOut","nameLocation":"1058:5:0","nodeType":"VariableDeclaration","scope":78,"src":"1021:42:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes) pure"},"typeName":{"id":73,"nodeType":"FunctionTypeName","parameterTypes":{"id":71,"nodeType":"ParameterList","parameters":[{"constant":false,"id":70,"mutability":"mutable","name":"","nameLocation":"-1:-1:-1","nodeType":"VariableDeclaration","scope":73,"src":"1030:12:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":69,"name":"bytes","nodeType":"ElementaryTypeName","src":"1030:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"1029:14:0"},"returnParameterTypes":{"id":72,"nodeType":"ParameterList","parameters":[],"src":"1058:0:0"},"src":"1021:42:0","stateMutability":"pure","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes) pure"},"visibility":"internal"},"visibility":"internal"}],"src":"1020:44:0"},"scope":192,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":90,"nodeType":"FunctionDefinition","src":"1133:133:0","nodes":[],"body":{"id":89,"nodeType":"Block","src":"1194:72:0","nodes":[],"statements":[{"expression":{"arguments":[{"id":86,"name":"payload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":80,"src":"1251:7:0","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"arguments":[{"id":84,"name":"_sendLogPayloadView","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":106,"src":"1230:19:0","typeDescriptions":{"typeIdentifier":"t_function_internal_view$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) view"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_function_internal_view$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) view"}],"id":83,"name":"_castLogPayloadViewToPure","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":78,"src":"1204:25:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_function_internal_view$_t_bytes_memory_ptr_$returns$__$_$returns$_t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$_$","typeString":"function (function (bytes memory) view) pure returns (function (bytes memory) pure)"}},"id":85,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1204:46:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":87,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1204:55:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":88,"nodeType":"ExpressionStatement","src":"1204:55:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"_sendLogPayload","nameLocation":"1142:15:0","parameters":{"id":81,"nodeType":"ParameterList","parameters":[{"constant":false,"id":80,"mutability":"mutable","name":"payload","nameLocation":"1171:7:0","nodeType":"VariableDeclaration","scope":90,"src":"1158:20:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":79,"name":"bytes","nodeType":"ElementaryTypeName","src":"1158:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"1157:22:0"},"returnParameters":{"id":82,"nodeType":"ParameterList","parameters":[],"src":"1194:0:0"},"scope":192,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":106,"nodeType":"FunctionDefinition","src":"1272:380:0","nodes":[],"body":{"id":105,"nodeType":"Block","src":"1336:316:0","nodes":[],"statements":[{"assignments":[96],"declarations":[{"constant":false,"id":96,"mutability":"mutable","name":"payloadLength","nameLocation":"1354:13:0","nodeType":"VariableDeclaration","scope":105,"src":"1346:21:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":95,"name":"uint256","nodeType":"ElementaryTypeName","src":"1346:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"}],"id":99,"initialValue":{"expression":{"id":97,"name":"payload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":92,"src":"1370:7:0","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}},"id":98,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"length","nodeType":"MemberAccess","src":"1370:14:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"nodeType":"VariableDeclarationStatement","src":"1346:38:0"},{"assignments":[101],"declarations":[{"constant":false,"id":101,"mutability":"mutable","name":"consoleAddress","nameLocation":"1402:14:0","nodeType":"VariableDeclaration","scope":105,"src":"1394:22:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":100,"name":"address","nodeType":"ElementaryTypeName","src":"1394:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"id":103,"initialValue":{"id":102,"name":"CONSOLE_ADDRESS","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":61,"src":"1419:15:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"nodeType":"VariableDeclarationStatement","src":"1394:40:0"},{"AST":{"nodeType":"YulBlock","src":"1496:150:0","statements":[{"nodeType":"YulVariableDeclaration","src":"1510:36:0","value":{"arguments":[{"name":"payload","nodeType":"YulIdentifier","src":"1534:7:0"},{"kind":"number","nodeType":"YulLiteral","src":"1543:2:0","type":"","value":"32"}],"functionName":{"name":"add","nodeType":"YulIdentifier","src":"1530:3:0"},"nodeType":"YulFunctionCall","src":"1530:16:0"},"variables":[{"name":"payloadStart","nodeType":"YulTypedName","src":"1514:12:0","type":""}]},{"nodeType":"YulVariableDeclaration","src":"1559:77:0","value":{"arguments":[{"arguments":[],"functionName":{"name":"gas","nodeType":"YulIdentifier","src":"1579:3:0"},"nodeType":"YulFunctionCall","src":"1579:5:0"},{"name":"consoleAddress","nodeType":"YulIdentifier","src":"1586:14:0"},{"name":"payloadStart","nodeType":"YulIdentifier","src":"1602:12:0"},{"name":"payloadLength","nodeType":"YulIdentifier","src":"1616:13:0"},{"kind":"number","nodeType":"YulLiteral","src":"1631:1:0","type":"","value":"0"},{"kind":"number","nodeType":"YulLiteral","src":"1634:1:0","type":"","value":"0"}],"functionName":{"name":"staticcall","nodeType":"YulIdentifier","src":"1568:10:0"},"nodeType":"YulFunctionCall","src":"1568:68:0"},"variables":[{"name":"r","nodeType":"YulTypedName","src":"1563:1:0","type":""}]}]},"documentation":"@solidity memory-safe-assembly","evmVersion":"london","externalReferences":[{"declaration":101,"isOffset":false,"isSlot":false,"src":"1586:14:0","valueSize":1},{"declaration":92,"isOffset":false,"isSlot":false,"src":"1534:7:0","valueSize":1},{"declaration":96,"isOffset":false,"isSlot":false,"src":"1616:13:0","valueSize":1}],"id":104,"nodeType":"InlineAssembly","src":"1487:159:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"_sendLogPayloadView","nameLocation":"1281:19:0","parameters":{"id":93,"nodeType":"ParameterList","parameters":[{"constant":false,"id":92,"mutability":"mutable","name":"payload","nameLocation":"1314:7:0","nodeType":"VariableDeclaration","scope":106,"src":"1301:20:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":91,"name":"bytes","nodeType":"ElementaryTypeName","src":"1301:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"1300:22:0"},"returnParameters":{"id":94,"nodeType":"ParameterList","parameters":[],"src":"1336:0:0"},"scope":192,"stateMutability":"view","virtual":false,"visibility":"private"},{"id":120,"nodeType":"FunctionDefinition","src":"1658:121:0","nodes":[],"body":{"id":119,"nodeType":"Block","src":"1703:76:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e6729","id":114,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"1753:13:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_41304facd9323d75b11bcdd609cb38effffdb05710f7caf0e9b16c6d9d709f50","typeString":"literal_string \"log(string)\""},"value":"log(string)"},{"id":115,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":108,"src":"1768:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_41304facd9323d75b11bcdd609cb38effffdb05710f7caf0e9b16c6d9d709f50","typeString":"literal_string \"log(string)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}],"expression":{"id":112,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"1729:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":113,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"1729:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":116,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1729:42:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":111,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":90,"src":"1713:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":117,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1713:59:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":118,"nodeType":"ExpressionStatement","src":"1713:59:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"1667:3:0","parameters":{"id":109,"nodeType":"ParameterList","parameters":[{"constant":false,"id":108,"mutability":"mutable","name":"p0","nameLocation":"1685:2:0","nodeType":"VariableDeclaration","scope":120,"src":"1671:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":107,"name":"string","nodeType":"ElementaryTypeName","src":"1671:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"1670:18:0"},"returnParameters":{"id":110,"nodeType":"ParameterList","parameters":[],"src":"1703:0:0"},"scope":192,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":137,"nodeType":"FunctionDefinition","src":"1785:139:0","nodes":[],"body":{"id":136,"nodeType":"Block","src":"1839:85:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e672c626f6f6c29","id":130,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"1889:18:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_c3b556354c088fbb43886eb83c2a04bc7089663f964d22be308197a236f5b870","typeString":"literal_string \"log(string,bool)\""},"value":"log(string,bool)"},{"id":131,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":122,"src":"1909:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":132,"name":"p1","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":124,"src":"1913:2:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_c3b556354c088fbb43886eb83c2a04bc7089663f964d22be308197a236f5b870","typeString":"literal_string \"log(string,bool)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_bool","typeString":"bool"}],"expression":{"id":128,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"1865:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":129,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"1865:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":133,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1865:51:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":127,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":90,"src":"1849:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":134,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1849:68:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":135,"nodeType":"ExpressionStatement","src":"1849:68:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"1794:3:0","parameters":{"id":125,"nodeType":"ParameterList","parameters":[{"constant":false,"id":122,"mutability":"mutable","name":"p0","nameLocation":"1812:2:0","nodeType":"VariableDeclaration","scope":137,"src":"1798:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":121,"name":"string","nodeType":"ElementaryTypeName","src":"1798:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":124,"mutability":"mutable","name":"p1","nameLocation":"1821:2:0","nodeType":"VariableDeclaration","scope":137,"src":"1816:7:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":123,"name":"bool","nodeType":"ElementaryTypeName","src":"1816:4:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"src":"1797:27:0"},"returnParameters":{"id":126,"nodeType":"ParameterList","parameters":[],"src":"1839:0:0"},"scope":192,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":154,"nodeType":"FunctionDefinition","src":"1930:145:0","nodes":[],"body":{"id":153,"nodeType":"Block","src":"1987:88:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e672c75696e7432353629","id":147,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2037:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_b60e72ccf6d57ab53eb84d7e94a9545806ed7f93c4d5673f11a64f03471e584e","typeString":"literal_string \"log(string,uint256)\""},"value":"log(string,uint256)"},{"id":148,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":139,"src":"2060:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":149,"name":"p1","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":141,"src":"2064:2:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_b60e72ccf6d57ab53eb84d7e94a9545806ed7f93c4d5673f11a64f03471e584e","typeString":"literal_string \"log(string,uint256)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_uint256","typeString":"uint256"}],"expression":{"id":145,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"2013:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":146,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"2013:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":150,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2013:54:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":144,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":90,"src":"1997:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":151,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"1997:71:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":152,"nodeType":"ExpressionStatement","src":"1997:71:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"1939:3:0","parameters":{"id":142,"nodeType":"ParameterList","parameters":[{"constant":false,"id":139,"mutability":"mutable","name":"p0","nameLocation":"1957:2:0","nodeType":"VariableDeclaration","scope":154,"src":"1943:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":138,"name":"string","nodeType":"ElementaryTypeName","src":"1943:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":141,"mutability":"mutable","name":"p1","nameLocation":"1969:2:0","nodeType":"VariableDeclaration","scope":154,"src":"1961:10:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":140,"name":"uint256","nodeType":"ElementaryTypeName","src":"1961:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"}],"src":"1942:30:0"},"returnParameters":{"id":143,"nodeType":"ParameterList","parameters":[],"src":"1987:0:0"},"scope":192,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":171,"nodeType":"FunctionDefinition","src":"2081:145:0","nodes":[],"body":{"id":170,"nodeType":"Block","src":"2138:88:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e672c6164647265737329","id":164,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2188:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_319af333460570a1937bf195dd33445c0d0951c59127da6f1f038b9fdce3fd72","typeString":"literal_string \"log(string,address)\""},"value":"log(string,address)"},{"id":165,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":156,"src":"2211:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":166,"name":"p1","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":158,"src":"2215:2:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_319af333460570a1937bf195dd33445c0d0951c59127da6f1f038b9fdce3fd72","typeString":"literal_string \"log(string,address)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":162,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"2164:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":163,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"2164:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":167,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2164:54:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":161,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":90,"src":"2148:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":168,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2148:71:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":169,"nodeType":"ExpressionStatement","src":"2148:71:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"2090:3:0","parameters":{"id":159,"nodeType":"ParameterList","parameters":[{"constant":false,"id":156,"mutability":"mutable","name":"p0","nameLocation":"2108:2:0","nodeType":"VariableDeclaration","scope":171,"src":"2094:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":155,"name":"string","nodeType":"ElementaryTypeName","src":"2094:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":158,"mutability":"mutable","name":"p1","nameLocation":"2120:2:0","nodeType":"VariableDeclaration","scope":171,"src":"2112:10:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":157,"name":"address","nodeType":"ElementaryTypeName","src":"2112:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"2093:30:0"},"returnParameters":{"id":160,"nodeType":"ParameterList","parameters":[],"src":"2138:0:0"},"scope":192,"stateMutability":"pure","virtual":false,"visibility":"internal"},{"id":191,"nodeType":"FunctionDefinition","src":"2232:179:0","nodes":[],"body":{"id":190,"nodeType":"Block","src":"2313:98:0","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[{"hexValue":"6c6f6728737472696e672c737472696e672c737472696e6729","id":183,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2363:27:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_2ced7cef693312206c21f0e92e3b54e2e16bf33db5eec350c78866822c665e1f","typeString":"literal_string \"log(string,string,string)\""},"value":"log(string,string,string)"},{"id":184,"name":"p0","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":173,"src":"2392:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":185,"name":"p1","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":175,"src":"2396:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"id":186,"name":"p2","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":177,"src":"2400:2:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_2ced7cef693312206c21f0e92e3b54e2e16bf33db5eec350c78866822c665e1f","typeString":"literal_string \"log(string,string,string)\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}],"expression":{"id":181,"name":"abi","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-1,"src":"2339:3:0","typeDescriptions":{"typeIdentifier":"t_magic_abi","typeString":"abi"}},"id":182,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberName":"encodeWithSignature","nodeType":"MemberAccess","src":"2339:23:0","typeDescriptions":{"typeIdentifier":"t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$","typeString":"function (string memory) pure returns (bytes memory)"}},"id":187,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2339:64:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes memory"}],"id":180,"name":"_sendLogPayload","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":90,"src":"2323:15:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory) pure"}},"id":188,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2323:81:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":189,"nodeType":"ExpressionStatement","src":"2323:81:0"}]},"implemented":true,"kind":"function","modifiers":[],"name":"log","nameLocation":"2241:3:0","parameters":{"id":178,"nodeType":"ParameterList","parameters":[{"constant":false,"id":173,"mutability":"mutable","name":"p0","nameLocation":"2259:2:0","nodeType":"VariableDeclaration","scope":191,"src":"2245:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":172,"name":"string","nodeType":"ElementaryTypeName","src":"2245:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":175,"mutability":"mutable","name":"p1","nameLocation":"2277:2:0","nodeType":"VariableDeclaration","scope":191,"src":"2263:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":174,"name":"string","nodeType":"ElementaryTypeName","src":"2263:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"},{"constant":false,"id":177,"mutability":"mutable","name":"p2","nameLocation":"2295:2:0","nodeType":"VariableDeclaration","scope":191,"src":"2281:16:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":176,"name":"string","nodeType":"ElementaryTypeName","src":"2281:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"2244:54:0"},"returnParameters":{"id":179,"nodeType":"ParameterList","parameters":[],"src":"2313:0:0"},"scope":192,"stateMutability":"pure","virtual":false,"visibility":"internal"}],"abstract":false,"baseContracts":[],"canonicalName":"console","contractDependencies":[],"contractKind":"library","fullyImplemented":true,"linearizedBaseContracts":[192],"name":"console","nameLocation":"799:7:0","scope":720,"usedErrors":[]},{"id":706,"nodeType":"ContractDefinition","src":"2541:3359:0","nodes":[{"id":207,"nodeType":"VariableDeclaration","src":"2571:94:0","nodes":[],"constant":true,"mutability":"constant","name":"VM_ADDRESS","nameLocation":"2597:10:0","scope":706,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":194,"name":"address","nodeType":"ElementaryTypeName","src":"2571:7:0","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"value":{"arguments":[{"arguments":[{"arguments":[{"arguments":[{"hexValue":"6865766d20636865617420636f6465","id":202,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2644:17:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d","typeString":"literal_string \"hevm cheat code\""},"value":"hevm cheat code"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d","typeString":"literal_string \"hevm cheat code\""}],"id":201,"name":"keccak256","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-8,"src":"2634:9:0","typeDescriptions":{"typeIdentifier":"t_function_keccak256_pure$_t_bytes_memory_ptr_$returns$_t_bytes32_$","typeString":"function (bytes memory) pure returns (bytes32)"}},"id":203,"isConstant":false,"isLValue":false,"isPure":true,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2634:28:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes32","typeString":"bytes32"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes32","typeString":"bytes32"}],"id":200,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2626:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint256_$","typeString":"type(uint256)"},"typeName":{"id":199,"name":"uint256","nodeType":"ElementaryTypeName","src":"2626:7:0","typeDescriptions":{}}},"id":204,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2626:37:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint256","typeString":"uint256"}],"id":198,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2618:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":197,"name":"uint160","nodeType":"ElementaryTypeName","src":"2618:7:0","typeDescriptions":{}}},"id":205,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2618:46:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":196,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"2610:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":195,"name":"address","nodeType":"ElementaryTypeName","src":"2610:7:0","typeDescriptions":{}}},"id":206,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2610:55:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"},{"id":213,"nodeType":"VariableDeclaration","src":"2671:40:0","nodes":[],"constant":true,"mutability":"constant","name":"vm","nameLocation":"2692:2:0","scope":706,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"},"typeName":{"id":209,"nodeType":"UserDefinedTypeName","pathNode":{"id":208,"name":"Vm","nodeType":"IdentifierPath","referencedDeclaration":55,"src":"2671:2:0"},"referencedDeclaration":55,"src":"2671:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"value":{"arguments":[{"id":211,"name":"VM_ADDRESS","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":207,"src":"2700:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":210,"name":"Vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":55,"src":"2697:2:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_Vm_$55_$","typeString":"type(contract Vm)"}},"id":212,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2697:14:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"visibility":"internal"},{"id":215,"nodeType":"VariableDeclaration","src":"2775:22:0","nodes":[],"constant":false,"functionSelector":"61bc221a","mutability":"mutable","name":"counter","nameLocation":"2790:7:0","scope":706,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":214,"name":"uint256","nodeType":"ElementaryTypeName","src":"2775:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"public"},{"id":378,"nodeType":"FunctionDefinition","src":"2887:949:0","nodes":[],"body":{"id":377,"nodeType":"Block","src":"2909:927:0","nodes":[],"statements":[{"assignments":[220],"declarations":[{"constant":false,"id":220,"mutability":"mutable","name":"x","nameLocation":"2924:1:0","nodeType":"VariableDeclaration","scope":377,"src":"2919:6:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":219,"name":"bool","nodeType":"ElementaryTypeName","src":"2919:4:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"id":226,"initialValue":{"arguments":[{"hexValue":"4558414d504c455f424f4f4c","id":223,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2937:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_a634dae177a0e138ae7aaa2afae347412e148992e88c7aabd33ee71be146cb7f","typeString":"literal_string \"EXAMPLE_BOOL\""},"value":"EXAMPLE_BOOL"},{"hexValue":"66616c7365","id":224,"isConstant":false,"isLValue":false,"isPure":true,"kind":"bool","lValueRequested":false,"nodeType":"Literal","src":"2953:5:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"value":"false"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_a634dae177a0e138ae7aaa2afae347412e148992e88c7aabd33ee71be146cb7f","typeString":"literal_string \"EXAMPLE_BOOL\""},{"typeIdentifier":"t_bool","typeString":"bool"}],"expression":{"id":221,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"2928:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":222,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"envOr","nodeType":"MemberAccess","referencedDeclaration":10,"src":"2928:8:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$_t_bool_$returns$_t_bool_$","typeString":"function (string memory,bool) view external returns (bool)"}},"id":225,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2928:31:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"nodeType":"VariableDeclarationStatement","src":"2919:40:0"},{"expression":{"arguments":[{"hexValue":"626f6f6c2076616c75652066726f6d20656e76","id":230,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"2981:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_5a607d0b5a1295325aa8901721d78ba402601bba6f62cebdd5235dd0204a590b","typeString":"literal_string \"bool value from env\""},"value":"bool value from env"},{"id":231,"name":"x","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":220,"src":"3004:1:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_5a607d0b5a1295325aa8901721d78ba402601bba6f62cebdd5235dd0204a590b","typeString":"literal_string \"bool value from env\""},{"typeIdentifier":"t_bool","typeString":"bool"}],"expression":{"id":227,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"2969:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":229,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":137,"src":"2969:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_bool_$returns$__$","typeString":"function (string memory,bool) pure"}},"id":232,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"2969:37:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":233,"nodeType":"ExpressionStatement","src":"2969:37:0"},{"expression":{"arguments":[{"hexValue":"636f6e74726163742061646472","id":237,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3029:15:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_fa50728770d00fe8f6a0592f3565bbfaf063ee4077f1f5bbc003d091d33cd0c4","typeString":"literal_string \"contract addr\""},"value":"contract addr"},{"arguments":[{"id":240,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3054:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}],"id":239,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3046:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":238,"name":"address","nodeType":"ElementaryTypeName","src":"3046:7:0","typeDescriptions":{}}},"id":241,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3046:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_fa50728770d00fe8f6a0592f3565bbfaf063ee4077f1f5bbc003d091d33cd0c4","typeString":"literal_string \"contract addr\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":234,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3017:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":236,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":171,"src":"3017:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":242,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3017:43:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":243,"nodeType":"ExpressionStatement","src":"3017:43:0"},{"expression":{"arguments":[{"hexValue":"636f6e7472616374206e6f6e6365","id":247,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3082:16:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_3a23091615a5de8c0a35ffd8857a37e2c4e0b72f3ef8a34d6caf65efcd562e2f","typeString":"literal_string \"contract nonce\""},"value":"contract nonce"},{"arguments":[{"arguments":[{"id":252,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3120:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}],"id":251,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3112:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":250,"name":"address","nodeType":"ElementaryTypeName","src":"3112:7:0","typeDescriptions":{}}},"id":253,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3112:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":248,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"3100:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":249,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"getNonce","nodeType":"MemberAccess","referencedDeclaration":17,"src":"3100:11:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_address_$returns$_t_uint64_$","typeString":"function (address) view external returns (uint64)"}},"id":254,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3100:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_3a23091615a5de8c0a35ffd8857a37e2c4e0b72f3ef8a34d6caf65efcd562e2f","typeString":"literal_string \"contract nonce\""},{"typeIdentifier":"t_uint64","typeString":"uint64"}],"expression":{"id":244,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3070:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":246,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":154,"src":"3070:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_uint256_$returns$__$","typeString":"function (string memory,uint256) pure"}},"id":255,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3070:57:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":256,"nodeType":"ExpressionStatement","src":"3070:57:0"},{"expression":{"arguments":[{"hexValue":"73656e6465722061646472","id":260,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3149:13:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_8125ca2decf812b25b65606ff16dad37cb198ff0433485a7926e50feafacfc35","typeString":"literal_string \"sender addr\""},"value":"sender addr"},{"arguments":[{"expression":{"id":263,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"3172:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":264,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"sender","nodeType":"MemberAccess","src":"3172:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":262,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3164:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":261,"name":"address","nodeType":"ElementaryTypeName","src":"3164:7:0","typeDescriptions":{}}},"id":265,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3164:19:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_8125ca2decf812b25b65606ff16dad37cb198ff0433485a7926e50feafacfc35","typeString":"literal_string \"sender addr\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":257,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3137:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":259,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":171,"src":"3137:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":266,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3137:47:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":267,"nodeType":"ExpressionStatement","src":"3137:47:0"},{"expression":{"arguments":[{"hexValue":"73656e646572206e6f6e6365","id":271,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3206:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_db7deb43f2f9e0404016de53b7e64c4976b54149581f7534daae2551e8cf4e40","typeString":"literal_string \"sender nonce\""},"value":"sender nonce"},{"arguments":[{"arguments":[{"expression":{"id":276,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"3242:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":277,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"sender","nodeType":"MemberAccess","src":"3242:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":275,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3234:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":274,"name":"address","nodeType":"ElementaryTypeName","src":"3234:7:0","typeDescriptions":{}}},"id":278,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3234:19:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":272,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"3222:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":273,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"getNonce","nodeType":"MemberAccess","referencedDeclaration":17,"src":"3222:11:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_address_$returns$_t_uint64_$","typeString":"function (address) view external returns (uint64)"}},"id":279,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3222:32:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_db7deb43f2f9e0404016de53b7e64c4976b54149581f7534daae2551e8cf4e40","typeString":"literal_string \"sender nonce\""},{"typeIdentifier":"t_uint64","typeString":"uint64"}],"expression":{"id":268,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3194:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":270,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":154,"src":"3194:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_uint256_$returns$__$","typeString":"function (string memory,uint256) pure"}},"id":280,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3194:61:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":281,"nodeType":"ExpressionStatement","src":"3194:61:0"},{"assignments":[283],"declarations":[{"constant":false,"id":283,"mutability":"mutable","name":"json","nameLocation":"3280:4:0","nodeType":"VariableDeclaration","scope":377,"src":"3266:18:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string"},"typeName":{"id":282,"name":"string","nodeType":"ElementaryTypeName","src":"3266:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"id":285,"initialValue":{"hexValue":"7b22726f6f745f6b6579223a205b7b2261223a20312c202262223a20327d5d7d","id":284,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3287:34:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_e95522e99766888d0261f55bd1eae5e3f3e26eaf009a16e2433eafaf0a4ecdf2","typeString":"literal_string \"{\"root_key\": [{\"a\": 1, \"b\": 2}]}\""},"value":"{\"root_key\": [{\"a\": 1, \"b\": 2}]}"},"nodeType":"VariableDeclarationStatement","src":"3266:55:0"},{"assignments":[290],"declarations":[{"constant":false,"id":290,"mutability":"mutable","name":"keys","nameLocation":"3347:4:0","nodeType":"VariableDeclaration","scope":377,"src":"3331:20:0","stateVariable":false,"storageLocation":"memory","typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string[]"},"typeName":{"baseType":{"id":288,"name":"string","nodeType":"ElementaryTypeName","src":"3331:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"id":289,"nodeType":"ArrayTypeName","src":"3331:8:0","typeDescriptions":{"typeIdentifier":"t_array$_t_string_storage_$dyn_storage_ptr","typeString":"string[]"}},"visibility":"internal"}],"id":296,"initialValue":{"arguments":[{"id":293,"name":"json","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":283,"src":"3371:4:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"hexValue":"2e726f6f745f6b65795b305d","id":294,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3377:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_d82f67100edb80050915e1ec4b565c9a8319a22efb1075e1298b7bb60101d266","typeString":"literal_string \".root_key[0]\""},"value":".root_key[0]"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_stringliteral_d82f67100edb80050915e1ec4b565c9a8319a22efb1075e1298b7bb60101d266","typeString":"literal_string \".root_key[0]\""}],"expression":{"id":291,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"3354:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":292,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"parseJsonKeys","nodeType":"MemberAccess","referencedDeclaration":27,"src":"3354:16:0","typeDescriptions":{"typeIdentifier":"t_function_external_pure$_t_string_memory_ptr_$_t_string_memory_ptr_$returns$_t_array$_t_string_memory_ptr_$dyn_memory_ptr_$","typeString":"function (string memory,string memory) pure external returns (string memory[] memory)"}},"id":295,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3354:38:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string memory[] memory"}},"nodeType":"VariableDeclarationStatement","src":"3331:61:0"},{"expression":{"arguments":[{"hexValue":"6b657973","id":300,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3414:6:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_f29790a80c4ce5f42f59892f424f9c92856c6b656c3378e2cf305b260c6f4195","typeString":"literal_string \"keys\""},"value":"keys"},{"baseExpression":{"id":301,"name":"keys","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":290,"src":"3422:4:0","typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string memory[] memory"}},"id":303,"indexExpression":{"hexValue":"30","id":302,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"3427:1:0","typeDescriptions":{"typeIdentifier":"t_rational_0_by_1","typeString":"int_const 0"},"value":"0"},"isConstant":false,"isLValue":true,"isPure":false,"lValueRequested":false,"nodeType":"IndexAccess","src":"3422:7:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}},{"baseExpression":{"id":304,"name":"keys","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":290,"src":"3431:4:0","typeDescriptions":{"typeIdentifier":"t_array$_t_string_memory_ptr_$dyn_memory_ptr","typeString":"string memory[] memory"}},"id":306,"indexExpression":{"hexValue":"31","id":305,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"3436:1:0","typeDescriptions":{"typeIdentifier":"t_rational_1_by_1","typeString":"int_const 1"},"value":"1"},"isConstant":false,"isLValue":true,"isPure":false,"lValueRequested":false,"nodeType":"IndexAccess","src":"3431:7:0","typeDescriptions":{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_f29790a80c4ce5f42f59892f424f9c92856c6b656c3378e2cf305b260c6f4195","typeString":"literal_string \"keys\""},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"},{"typeIdentifier":"t_string_memory_ptr","typeString":"string memory"}],"expression":{"id":297,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3402:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":299,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":191,"src":"3402:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_string_memory_ptr_$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory,string memory,string memory) pure"}},"id":307,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3402:37:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":308,"nodeType":"ExpressionStatement","src":"3402:37:0"},{"expression":{"arguments":[{"hexValue":"66726f6d206f726967696e616c","id":312,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3461:15:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_77928970c8757d110f3c23e003246f49e0de890480ba9717ba659b2f56f316b2","typeString":"literal_string \"from original\""},"value":"from original"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_77928970c8757d110f3c23e003246f49e0de890480ba9717ba659b2f56f316b2","typeString":"literal_string \"from original\""}],"expression":{"id":309,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3450:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":311,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"hello","nodeType":"MemberAccess","referencedDeclaration":633,"src":"3450:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) view external"}},"id":313,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3450:27:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":314,"nodeType":"ExpressionStatement","src":"3450:27:0"},{"expression":{"arguments":[{"arguments":[{"arguments":[{"hexValue":"30783432","id":322,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"3517:4:0","typeDescriptions":{"typeIdentifier":"t_rational_66_by_1","typeString":"int_const 66"},"value":"0x42"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_66_by_1","typeString":"int_const 66"}],"id":321,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3509:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":320,"name":"uint160","nodeType":"ElementaryTypeName","src":"3509:7:0","typeDescriptions":{}}},"id":323,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3509:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":319,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3501:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":318,"name":"address","nodeType":"ElementaryTypeName","src":"3501:7:0","typeDescriptions":{}}},"id":324,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3501:22:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":315,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"3487:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":317,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"startPrank","nodeType":"MemberAccess","referencedDeclaration":32,"src":"3487:13:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_address_$returns$__$","typeString":"function (address) external"}},"id":325,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3487:37:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":326,"nodeType":"ExpressionStatement","src":"3487:37:0"},{"expression":{"arguments":[{"hexValue":"66726f6d207072616e6b2031","id":330,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3545:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_42b34abfe37a8b0add910cda7b4a379e6538fa7a1dcafce47a02bd38f6c88e2a","typeString":"literal_string \"from prank 1\""},"value":"from prank 1"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_42b34abfe37a8b0add910cda7b4a379e6538fa7a1dcafce47a02bd38f6c88e2a","typeString":"literal_string \"from prank 1\""}],"expression":{"id":327,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3534:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":329,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"hello","nodeType":"MemberAccess","referencedDeclaration":633,"src":"3534:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) view external"}},"id":331,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3534:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":332,"nodeType":"ExpressionStatement","src":"3534:26:0"},{"expression":{"arguments":[{"hexValue":"706172656e742073636f7065206d73672e73656e646572","id":336,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3582:25:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_83ec9246154d8845de47aafc5c2865c9985d2efe84472c27283879f2fbf5cc94","typeString":"literal_string \"parent scope msg.sender\""},"value":"parent scope msg.sender"},{"arguments":[{"expression":{"id":339,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"3617:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":340,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"sender","nodeType":"MemberAccess","src":"3617:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":338,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3609:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":337,"name":"address","nodeType":"ElementaryTypeName","src":"3609:7:0","typeDescriptions":{}}},"id":341,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3609:19:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_83ec9246154d8845de47aafc5c2865c9985d2efe84472c27283879f2fbf5cc94","typeString":"literal_string \"parent scope msg.sender\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":333,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3570:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":335,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":171,"src":"3570:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":342,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3570:59:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":343,"nodeType":"ExpressionStatement","src":"3570:59:0"},{"expression":{"arguments":[{"hexValue":"706172656e742073636f706520636f6e74726163742e61646472","id":347,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3651:28:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_97df66250e0b2b48f0ec8d0e01eb1b8ca012d95f1572895622aa1ea433e5570f","typeString":"literal_string \"parent scope contract.addr\""},"value":"parent scope contract.addr"},{"arguments":[{"id":350,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3689:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}],"id":349,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3681:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":348,"name":"address","nodeType":"ElementaryTypeName","src":"3681:7:0","typeDescriptions":{}}},"id":351,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3681:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_97df66250e0b2b48f0ec8d0e01eb1b8ca012d95f1572895622aa1ea433e5570f","typeString":"literal_string \"parent scope contract.addr\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":344,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3639:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":346,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":171,"src":"3639:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":352,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3639:56:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":353,"nodeType":"ExpressionStatement","src":"3639:56:0"},{"expression":{"arguments":[{"hexValue":"66726f6d207072616e6b2032","id":357,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3716:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_a38a34f8cad750a79aa097a92971f8f405b51ee9d53d25c5b14fc129ba3684bb","typeString":"literal_string \"from prank 2\""},"value":"from prank 2"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_a38a34f8cad750a79aa097a92971f8f405b51ee9d53d25c5b14fc129ba3684bb","typeString":"literal_string \"from prank 2\""}],"expression":{"id":354,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3705:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":356,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"hello","nodeType":"MemberAccess","referencedDeclaration":633,"src":"3705:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) view external"}},"id":358,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3705:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":359,"nodeType":"ExpressionStatement","src":"3705:26:0"},{"expression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":360,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"3741:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":362,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"stopPrank","nodeType":"MemberAccess","referencedDeclaration":35,"src":"3741:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$__$returns$__$","typeString":"function () external"}},"id":363,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3741:14:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":364,"nodeType":"ExpressionStatement","src":"3741:14:0"},{"expression":{"arguments":[{"hexValue":"66726f6d206f726967696e616c20616761696e","id":368,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3776:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_0c805c6579e20a9c4c8e11aeab23330910a9f2da629191dc119d1730e8ed6860","typeString":"literal_string \"from original again\""},"value":"from original again"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_0c805c6579e20a9c4c8e11aeab23330910a9f2da629191dc119d1730e8ed6860","typeString":"literal_string \"from original again\""}],"expression":{"id":365,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3765:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":367,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"hello","nodeType":"MemberAccess","referencedDeclaration":633,"src":"3765:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) view external"}},"id":369,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3765:33:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":370,"nodeType":"ExpressionStatement","src":"3765:33:0"},{"expression":{"arguments":[{"hexValue":"646f6e6521","id":374,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3821:7:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_080382d5c9e9e7c5e3d1d33f5e7422740375955180fadff167d8130e0c35f3fc","typeString":"literal_string \"done!\""},"value":"done!"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_080382d5c9e9e7c5e3d1d33f5e7422740375955180fadff167d8130e0c35f3fc","typeString":"literal_string \"done!\""}],"expression":{"id":371,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3809:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":373,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"3809:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":375,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3809:20:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":376,"nodeType":"ExpressionStatement","src":"3809:20:0"}]},"documentation":{"id":216,"nodeType":"StructuredDocumentation","src":"2804:78:0","text":"@notice example function, runs through basic cheat-codes and console logs."},"functionSelector":"c0406226","implemented":true,"kind":"function","modifiers":[],"name":"run","nameLocation":"2896:3:0","parameters":{"id":217,"nodeType":"ParameterList","parameters":[],"src":"2899:2:0"},"returnParameters":{"id":218,"nodeType":"ParameterList","parameters":[],"src":"2909:0:0"},"scope":706,"stateMutability":"nonpayable","virtual":false,"visibility":"public"},{"id":609,"nodeType":"FunctionDefinition","src":"3903:1258:0","nodes":[],"body":{"id":608,"nodeType":"Block","src":"3934:1227:0","nodes":[],"statements":[{"expression":{"arguments":[{"hexValue":"6e6f6e6365207374617274","id":385,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"3956:13:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_71efc69b9a13b6bc1e9a14d766ff01c79022262c6daa6532fb5dfb14f8511a20","typeString":"literal_string \"nonce start\""},"value":"nonce start"},{"arguments":[{"arguments":[{"arguments":[{"id":392,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"3999:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}],"id":391,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3991:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":390,"name":"address","nodeType":"ElementaryTypeName","src":"3991:7:0","typeDescriptions":{}}},"id":393,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3991:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":388,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"3979:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":389,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"getNonce","nodeType":"MemberAccess","referencedDeclaration":17,"src":"3979:11:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_address_$returns$_t_uint64_$","typeString":"function (address) view external returns (uint64)"}},"id":394,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3979:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint64","typeString":"uint64"}],"id":387,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"3971:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint256_$","typeString":"type(uint256)"},"typeName":{"id":386,"name":"uint256","nodeType":"ElementaryTypeName","src":"3971:7:0","typeDescriptions":{}}},"id":395,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3971:35:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_71efc69b9a13b6bc1e9a14d766ff01c79022262c6daa6532fb5dfb14f8511a20","typeString":"literal_string \"nonce start\""},{"typeIdentifier":"t_uint256","typeString":"uint256"}],"expression":{"id":382,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"3944:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":384,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":154,"src":"3944:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_uint256_$returns$__$","typeString":"function (string memory,uint256) pure"}},"id":396,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"3944:63:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":397,"nodeType":"ExpressionStatement","src":"3944:63:0"},{"expression":{"arguments":[{"hexValue":"74657374696e672073696e676c65","id":401,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4030:16:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_b75103528423218e7569082dad569ed0d2ce7c0ac770c0812b220e2d369fe474","typeString":"literal_string \"testing single\""},"value":"testing single"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_b75103528423218e7569082dad569ed0d2ce7c0ac770c0812b220e2d369fe474","typeString":"literal_string \"testing single\""}],"expression":{"id":398,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"4018:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":400,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"4018:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":402,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4018:29:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":403,"nodeType":"ExpressionStatement","src":"4018:29:0"},{"expression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":404,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"4057:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":406,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"broadcast","nodeType":"MemberAccess","referencedDeclaration":38,"src":"4057:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$__$returns$__$","typeString":"function () external"}},"id":407,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4057:14:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":408,"nodeType":"ExpressionStatement","src":"4057:14:0"},{"expression":{"arguments":[{"hexValue":"73696e676c655f63616c6c31","id":412,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4092:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_5e1cad6d7a968cfacf2731373e1248ffb11f4886bced66a02a6de1a67ac8f777","typeString":"literal_string \"single_call1\""},"value":"single_call1"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_5e1cad6d7a968cfacf2731373e1248ffb11f4886bced66a02a6de1a67ac8f777","typeString":"literal_string \"single_call1\""}],"expression":{"id":409,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"4081:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":411,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"call1","nodeType":"MemberAccess","referencedDeclaration":648,"src":"4081:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) external"}},"id":413,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4081:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":414,"nodeType":"ExpressionStatement","src":"4081:26:0"},{"expression":{"arguments":[{"hexValue":"73696e676c655f63616c6c32","id":418,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4128:14:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_b37ddaf5d00ad9e6371de3fb71b91eef731fae1e86b768666380f7d44e1ada25","typeString":"literal_string \"single_call2\""},"value":"single_call2"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_b37ddaf5d00ad9e6371de3fb71b91eef731fae1e86b768666380f7d44e1ada25","typeString":"literal_string \"single_call2\""}],"expression":{"id":415,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"4117:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":417,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"call2","nodeType":"MemberAccess","referencedDeclaration":663,"src":"4117:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) external"}},"id":419,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4117:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":420,"nodeType":"ExpressionStatement","src":"4117:26:0"},{"expression":{"arguments":[{"hexValue":"74657374696e672073746172742f73746f70","id":424,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4166:20:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_778e886e3a1c3c5096aca76228832105f3f9269f362effd0e8ce3737787cb784","typeString":"literal_string \"testing start/stop\""},"value":"testing start/stop"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_778e886e3a1c3c5096aca76228832105f3f9269f362effd0e8ce3737787cb784","typeString":"literal_string \"testing start/stop\""}],"expression":{"id":421,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"4154:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":423,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"4154:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":425,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4154:33:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":426,"nodeType":"ExpressionStatement","src":"4154:33:0"},{"expression":{"arguments":[{"arguments":[{"arguments":[{"hexValue":"3078633066666565","id":434,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4231:8:0","typeDescriptions":{"typeIdentifier":"t_rational_12648430_by_1","typeString":"int_const 12648430"},"value":"0xc0ffee"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_12648430_by_1","typeString":"int_const 12648430"}],"id":433,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4223:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":432,"name":"uint160","nodeType":"ElementaryTypeName","src":"4223:7:0","typeDescriptions":{}}},"id":435,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4223:17:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":431,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4215:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":430,"name":"address","nodeType":"ElementaryTypeName","src":"4215:7:0","typeDescriptions":{}}},"id":436,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4215:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":427,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"4197:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":429,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"startBroadcast","nodeType":"MemberAccess","referencedDeclaration":48,"src":"4197:17:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_address_$returns$__$","typeString":"function (address) external"}},"id":437,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4197:45:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":438,"nodeType":"ExpressionStatement","src":"4197:45:0"},{"expression":{"arguments":[{"hexValue":"737461727473746f705f63616c6c31","id":442,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4263:17:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_2fc2682edf10ed478ee3b9a190f6b1c88bb492b300935ce44545a1613cf8f041","typeString":"literal_string \"startstop_call1\""},"value":"startstop_call1"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_2fc2682edf10ed478ee3b9a190f6b1c88bb492b300935ce44545a1613cf8f041","typeString":"literal_string \"startstop_call1\""}],"expression":{"id":439,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"4252:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":441,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"call1","nodeType":"MemberAccess","referencedDeclaration":648,"src":"4252:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) external"}},"id":443,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4252:29:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":444,"nodeType":"ExpressionStatement","src":"4252:29:0"},{"expression":{"arguments":[{"hexValue":"737461727473746f705f63616c6c32","id":448,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4302:17:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_1a6fd77f04b28bf45d6d0e2dd4c65c0bbfeba174f849e43bb67ebca1c019cda4","typeString":"literal_string \"startstop_call2\""},"value":"startstop_call2"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_1a6fd77f04b28bf45d6d0e2dd4c65c0bbfeba174f849e43bb67ebca1c019cda4","typeString":"literal_string \"startstop_call2\""}],"expression":{"id":445,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"4291:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":447,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"call2","nodeType":"MemberAccess","referencedDeclaration":663,"src":"4291:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) external"}},"id":449,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4291:29:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":450,"nodeType":"ExpressionStatement","src":"4291:29:0"},{"expression":{"arguments":[{"hexValue":"737461727473746f705f70757265","id":454,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4344:16:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_b6e9eb1efd186b1d92b54da45026aa97a178e6eaffdf9dbf9f666fc751fb0ff9","typeString":"literal_string \"startstop_pure\""},"value":"startstop_pure"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_b6e9eb1efd186b1d92b54da45026aa97a178e6eaffdf9dbf9f666fc751fb0ff9","typeString":"literal_string \"startstop_pure\""}],"expression":{"id":451,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"4330:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":453,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"callPure","nodeType":"MemberAccess","referencedDeclaration":705,"src":"4330:13:0","typeDescriptions":{"typeIdentifier":"t_function_external_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure external"}},"id":455,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4330:31:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":456,"nodeType":"ExpressionStatement","src":"4330:31:0"},{"expression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":457,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"4371:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":459,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"stopBroadcast","nodeType":"MemberAccess","referencedDeclaration":54,"src":"4371:16:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$__$returns$__$","typeString":"function () external"}},"id":460,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4371:18:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":461,"nodeType":"ExpressionStatement","src":"4371:18:0"},{"expression":{"arguments":[{"hexValue":"737461727473746f705f63616c6c33","id":465,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4410:17:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_8eb502bfdc4adda22bd960aa2ae13ce4c0ed8cc3b3791ed65e321a38cdd36f72","typeString":"literal_string \"startstop_call3\""},"value":"startstop_call3"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_8eb502bfdc4adda22bd960aa2ae13ce4c0ed8cc3b3791ed65e321a38cdd36f72","typeString":"literal_string \"startstop_call3\""}],"expression":{"id":462,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"4399:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":464,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"call1","nodeType":"MemberAccess","referencedDeclaration":648,"src":"4399:10:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) external"}},"id":466,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4399:29:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":467,"nodeType":"ExpressionStatement","src":"4399:29:0"},{"expression":{"arguments":[{"hexValue":"74657374696e67206e6573746564","id":471,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4451:16:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_f92f19f7a5b5b9ce341188bf4e15925f184cdb5ac135c4846ced718f259dbde5","typeString":"literal_string \"testing nested\""},"value":"testing nested"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_f92f19f7a5b5b9ce341188bf4e15925f184cdb5ac135c4846ced718f259dbde5","typeString":"literal_string \"testing nested\""}],"expression":{"id":468,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"4439:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":470,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"4439:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":472,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4439:29:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":473,"nodeType":"ExpressionStatement","src":"4439:29:0"},{"expression":{"arguments":[{"arguments":[{"arguments":[{"hexValue":"307831323334","id":481,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4512:6:0","typeDescriptions":{"typeIdentifier":"t_rational_4660_by_1","typeString":"int_const 4660"},"value":"0x1234"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_4660_by_1","typeString":"int_const 4660"}],"id":480,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4504:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":479,"name":"uint160","nodeType":"ElementaryTypeName","src":"4504:7:0","typeDescriptions":{}}},"id":482,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4504:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":478,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4496:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":477,"name":"address","nodeType":"ElementaryTypeName","src":"4496:7:0","typeDescriptions":{}}},"id":483,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4496:24:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":474,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"4478:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":476,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"startBroadcast","nodeType":"MemberAccess","referencedDeclaration":48,"src":"4478:17:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_address_$returns$__$","typeString":"function (address) external"}},"id":484,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4478:43:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":485,"nodeType":"ExpressionStatement","src":"4478:43:0"},{"expression":{"arguments":[{"hexValue":"6e6573746564","id":489,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4544:8:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_4d5b14044d78fbf0c9dd8b9c49e35f09ee5a6f5b1b3b8117b5d0e15c8dd2cb09","typeString":"literal_string \"nested\""},"value":"nested"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_4d5b14044d78fbf0c9dd8b9c49e35f09ee5a6f5b1b3b8117b5d0e15c8dd2cb09","typeString":"literal_string \"nested\""}],"expression":{"id":486,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"4531:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":488,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"nested1","nodeType":"MemberAccess","referencedDeclaration":678,"src":"4531:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) external"}},"id":490,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4531:22:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":491,"nodeType":"ExpressionStatement","src":"4531:22:0"},{"expression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":492,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"4563:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":494,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"stopBroadcast","nodeType":"MemberAccess","referencedDeclaration":54,"src":"4563:16:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$__$returns$__$","typeString":"function () external"}},"id":495,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4563:18:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":496,"nodeType":"ExpressionStatement","src":"4563:18:0"},{"expression":{"arguments":[{"hexValue":"636f6e7472616374206465706c6f796d656e74","id":500,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4604:21:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_aaf9be86adf9b6872d87eed3526f7c55f3c5d61f4e4dd6d55ef2fcbb8ad0bd57","typeString":"literal_string \"contract deployment\""},"value":"contract deployment"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_aaf9be86adf9b6872d87eed3526f7c55f3c5d61f4e4dd6d55ef2fcbb8ad0bd57","typeString":"literal_string \"contract deployment\""}],"expression":{"id":497,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"4592:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":499,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"4592:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":501,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4592:34:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":502,"nodeType":"ExpressionStatement","src":"4592:34:0"},{"expression":{"arguments":[{"arguments":[{"arguments":[{"hexValue":"3078313233343536","id":510,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4665:8:0","typeDescriptions":{"typeIdentifier":"t_rational_1193046_by_1","typeString":"int_const 1193046"},"value":"0x123456"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_1193046_by_1","typeString":"int_const 1193046"}],"id":509,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4657:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":508,"name":"uint160","nodeType":"ElementaryTypeName","src":"4657:7:0","typeDescriptions":{}}},"id":511,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4657:17:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":507,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4649:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":506,"name":"address","nodeType":"ElementaryTypeName","src":"4649:7:0","typeDescriptions":{}}},"id":512,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4649:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":503,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"4636:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":505,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"broadcast","nodeType":"MemberAccess","referencedDeclaration":43,"src":"4636:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_address_$returns$__$","typeString":"function (address) external"}},"id":513,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4636:40:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":514,"nodeType":"ExpressionStatement","src":"4636:40:0"},{"assignments":[517],"declarations":[{"constant":false,"id":517,"mutability":"mutable","name":"x","nameLocation":"4693:1:0","nodeType":"VariableDeclaration","scope":608,"src":"4686:8:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"},"typeName":{"id":516,"nodeType":"UserDefinedTypeName","pathNode":{"id":515,"name":"FooBar","nodeType":"IdentifierPath","referencedDeclaration":719,"src":"4686:6:0"},"referencedDeclaration":719,"src":"4686:6:0","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}},"visibility":"internal"}],"id":523,"initialValue":{"arguments":[{"hexValue":"31323334","id":521,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4708:4:0","typeDescriptions":{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"},"value":"1234"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"}],"id":520,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"NewExpression","src":"4697:10:0","typeDescriptions":{"typeIdentifier":"t_function_creation_nonpayable$_t_uint256_$returns$_t_contract$_FooBar_$719_$","typeString":"function (uint256) returns (contract FooBar)"},"typeName":{"id":519,"nodeType":"UserDefinedTypeName","pathNode":{"id":518,"name":"FooBar","nodeType":"IdentifierPath","referencedDeclaration":719,"src":"4701:6:0"},"referencedDeclaration":719,"src":"4701:6:0","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}}},"id":522,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4697:16:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}},"nodeType":"VariableDeclarationStatement","src":"4686:27:0"},{"expression":{"arguments":[{"commonType":{"typeIdentifier":"t_uint256","typeString":"uint256"},"id":529,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"leftExpression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":525,"name":"x","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":517,"src":"4731:1:0","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}},"id":526,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"foo","nodeType":"MemberAccess","referencedDeclaration":708,"src":"4731:5:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$__$returns$_t_uint256_$","typeString":"function () view external returns (uint256)"}},"id":527,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4731:7:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"nodeType":"BinaryOperation","operator":"==","rightExpression":{"hexValue":"31323334","id":528,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4742:4:0","typeDescriptions":{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"},"value":"1234"},"src":"4731:15:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bool","typeString":"bool"}],"id":524,"name":"require","nodeType":"Identifier","overloadedDeclarations":[-18,-18],"referencedDeclaration":-18,"src":"4723:7:0","typeDescriptions":{"typeIdentifier":"t_function_require_pure$_t_bool_$returns$__$","typeString":"function (bool) pure"}},"id":530,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4723:24:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":531,"nodeType":"ExpressionStatement","src":"4723:24:0"},{"expression":{"arguments":[{"hexValue":"6372656174652032","id":535,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4770:10:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_4411d6d4ffcd00382a95255a63761e69de9810e1236042a5c64948a7b6c04daa","typeString":"literal_string \"create 2\""},"value":"create 2"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_4411d6d4ffcd00382a95255a63761e69de9810e1236042a5c64948a7b6c04daa","typeString":"literal_string \"create 2\""}],"expression":{"id":532,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"4758:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":534,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"4758:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":536,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4758:23:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":537,"nodeType":"ExpressionStatement","src":"4758:23:0"},{"expression":{"arguments":[{"arguments":[{"arguments":[{"hexValue":"307863616665","id":545,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4820:6:0","typeDescriptions":{"typeIdentifier":"t_rational_51966_by_1","typeString":"int_const 51966"},"value":"0xcafe"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_51966_by_1","typeString":"int_const 51966"}],"id":544,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4812:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint160_$","typeString":"type(uint160)"},"typeName":{"id":543,"name":"uint160","nodeType":"ElementaryTypeName","src":"4812:7:0","typeDescriptions":{}}},"id":546,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4812:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint160","typeString":"uint160"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint160","typeString":"uint160"}],"id":542,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4804:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":541,"name":"address","nodeType":"ElementaryTypeName","src":"4804:7:0","typeDescriptions":{}}},"id":547,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4804:24:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":538,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"4791:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":540,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"broadcast","nodeType":"MemberAccess","referencedDeclaration":43,"src":"4791:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_address_$returns$__$","typeString":"function (address) external"}},"id":548,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4791:38:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":549,"nodeType":"ExpressionStatement","src":"4791:38:0"},{"assignments":[552],"declarations":[{"constant":false,"id":552,"mutability":"mutable","name":"y","nameLocation":"4846:1:0","nodeType":"VariableDeclaration","scope":608,"src":"4839:8:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"},"typeName":{"id":551,"nodeType":"UserDefinedTypeName","pathNode":{"id":550,"name":"FooBar","nodeType":"IdentifierPath","referencedDeclaration":719,"src":"4839:6:0"},"referencedDeclaration":719,"src":"4839:6:0","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}},"visibility":"internal"}],"id":566,"initialValue":{"arguments":[{"hexValue":"31323334","id":564,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4889:4:0","typeDescriptions":{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"},"value":"1234"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"}],"id":555,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"NewExpression","src":"4850:10:0","typeDescriptions":{"typeIdentifier":"t_function_creation_nonpayable$_t_uint256_$returns$_t_contract$_FooBar_$719_$","typeString":"function (uint256) returns (contract FooBar)"},"typeName":{"id":554,"nodeType":"UserDefinedTypeName","pathNode":{"id":553,"name":"FooBar","nodeType":"IdentifierPath","referencedDeclaration":719,"src":"4854:6:0"},"referencedDeclaration":719,"src":"4854:6:0","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}}},"id":563,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"names":["salt"],"nodeType":"FunctionCallOptions","options":[{"arguments":[{"arguments":[{"hexValue":"3432","id":560,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4883:2:0","typeDescriptions":{"typeIdentifier":"t_rational_42_by_1","typeString":"int_const 42"},"value":"42"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_42_by_1","typeString":"int_const 42"}],"id":559,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4875:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint256_$","typeString":"type(uint256)"},"typeName":{"id":558,"name":"uint256","nodeType":"ElementaryTypeName","src":"4875:7:0","typeDescriptions":{}}},"id":561,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4875:11:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint256","typeString":"uint256"}],"id":557,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"4867:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_bytes32_$","typeString":"type(bytes32)"},"typeName":{"id":556,"name":"bytes32","nodeType":"ElementaryTypeName","src":"4867:7:0","typeDescriptions":{}}},"id":562,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4867:20:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes32","typeString":"bytes32"}}],"src":"4850:38:0","typeDescriptions":{"typeIdentifier":"t_function_creation_nonpayable$_t_uint256_$returns$_t_contract$_FooBar_$719_$salt","typeString":"function (uint256) returns (contract FooBar)"}},"id":565,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4850:44:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}},"nodeType":"VariableDeclarationStatement","src":"4839:55:0"},{"expression":{"arguments":[{"commonType":{"typeIdentifier":"t_uint256","typeString":"uint256"},"id":572,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"leftExpression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":568,"name":"y","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":552,"src":"4912:1:0","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}},"id":569,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"foo","nodeType":"MemberAccess","referencedDeclaration":708,"src":"4912:5:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$__$returns$_t_uint256_$","typeString":"function () view external returns (uint256)"}},"id":570,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4912:7:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"nodeType":"BinaryOperation","operator":"==","rightExpression":{"hexValue":"31323334","id":571,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"4923:4:0","typeDescriptions":{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"},"value":"1234"},"src":"4912:15:0","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bool","typeString":"bool"}],"id":567,"name":"require","nodeType":"Identifier","overloadedDeclarations":[-18,-18],"referencedDeclaration":-18,"src":"4904:7:0","typeDescriptions":{"typeIdentifier":"t_function_require_pure$_t_bool_$returns$__$","typeString":"function (bool) pure"}},"id":573,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4904:24:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":574,"nodeType":"ExpressionStatement","src":"4904:24:0"},{"expression":{"arguments":[{"hexValue":"646f6e6521","id":578,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"4950:7:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_080382d5c9e9e7c5e3d1d33f5e7422740375955180fadff167d8130e0c35f3fc","typeString":"literal_string \"done!\""},"value":"done!"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_080382d5c9e9e7c5e3d1d33f5e7422740375955180fadff167d8130e0c35f3fc","typeString":"literal_string \"done!\""}],"expression":{"id":575,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"4938:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":577,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"4938:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":579,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"4938:20:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":580,"nodeType":"ExpressionStatement","src":"4938:20:0"},{"expression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":581,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"5042:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":583,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"broadcast","nodeType":"MemberAccess","referencedDeclaration":38,"src":"5042:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$__$returns$__$","typeString":"function () external"}},"id":584,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5042:14:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":585,"nodeType":"ExpressionStatement","src":"5042:14:0"},{"expression":{"arguments":[{"hexValue":"31323334","id":589,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"5077:4:0","typeDescriptions":{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"},"value":"1234"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_1234_by_1","typeString":"int_const 1234"}],"id":588,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"NewExpression","src":"5066:10:0","typeDescriptions":{"typeIdentifier":"t_function_creation_nonpayable$_t_uint256_$returns$_t_contract$_FooBar_$719_$","typeString":"function (uint256) returns (contract FooBar)"},"typeName":{"id":587,"nodeType":"UserDefinedTypeName","pathNode":{"id":586,"name":"FooBar","nodeType":"IdentifierPath","referencedDeclaration":719,"src":"5070:6:0"},"referencedDeclaration":719,"src":"5070:6:0","typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}}},"id":590,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5066:16:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_contract$_FooBar_$719","typeString":"contract FooBar"}},"id":591,"nodeType":"ExpressionStatement","src":"5066:16:0"},{"expression":{"arguments":[{"hexValue":"6e6f6e636520656e64","id":595,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"5105:11:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_fa629e6661ad2a2bdb09cf9a3a276ce0d722482ae5c2887650751be0938847e8","typeString":"literal_string \"nonce end\""},"value":"nonce end"},{"arguments":[{"arguments":[{"arguments":[{"id":602,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"5146:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}],"id":601,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"5138:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":600,"name":"address","nodeType":"ElementaryTypeName","src":"5138:7:0","typeDescriptions":{}}},"id":603,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5138:13:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":598,"name":"vm","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":213,"src":"5126:2:0","typeDescriptions":{"typeIdentifier":"t_contract$_Vm_$55","typeString":"contract Vm"}},"id":599,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"getNonce","nodeType":"MemberAccess","referencedDeclaration":17,"src":"5126:11:0","typeDescriptions":{"typeIdentifier":"t_function_external_view$_t_address_$returns$_t_uint64_$","typeString":"function (address) view external returns (uint64)"}},"id":604,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5126:26:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint64","typeString":"uint64"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint64","typeString":"uint64"}],"id":597,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"5118:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_uint256_$","typeString":"type(uint256)"},"typeName":{"id":596,"name":"uint256","nodeType":"ElementaryTypeName","src":"5118:7:0","typeDescriptions":{}}},"id":605,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5118:35:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_fa629e6661ad2a2bdb09cf9a3a276ce0d722482ae5c2887650751be0938847e8","typeString":"literal_string \"nonce end\""},{"typeIdentifier":"t_uint256","typeString":"uint256"}],"expression":{"id":592,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"5093:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":594,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":154,"src":"5093:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_uint256_$returns$__$","typeString":"function (string memory,uint256) pure"}},"id":606,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5093:61:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":607,"nodeType":"ExpressionStatement","src":"5093:61:0"}]},"documentation":{"id":379,"nodeType":"StructuredDocumentation","src":"3842:56:0","text":"@notice example function, to test vm.broadcast with."},"functionSelector":"bef03abc","implemented":true,"kind":"function","modifiers":[],"name":"runBroadcast","nameLocation":"3912:12:0","parameters":{"id":380,"nodeType":"ParameterList","parameters":[],"src":"3924:2:0"},"returnParameters":{"id":381,"nodeType":"ParameterList","parameters":[],"src":"3934:0:0"},"scope":706,"stateMutability":"nonpayable","virtual":false,"visibility":"public"},{"id":633,"nodeType":"FunctionDefinition","src":"5256:143:0","nodes":[],"body":{"id":632,"nodeType":"Block","src":"5305:94:0","nodes":[],"statements":[{"expression":{"arguments":[{"id":618,"name":"_v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":612,"src":"5327:2:0","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}],"expression":{"id":615,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"5315:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":617,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"5315:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":619,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5315:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":620,"nodeType":"ExpressionStatement","src":"5315:15:0"},{"expression":{"arguments":[{"hexValue":"68656c6c6f206d73672e73656e646572","id":624,"isConstant":false,"isLValue":false,"isPure":true,"kind":"string","lValueRequested":false,"nodeType":"Literal","src":"5352:18:0","typeDescriptions":{"typeIdentifier":"t_stringliteral_b3cc13bc51228b2c4c4334d82a4772908254dc0e1c512893dd16208ef13efb8e","typeString":"literal_string \"hello msg.sender\""},"value":"hello msg.sender"},{"arguments":[{"expression":{"id":627,"name":"msg","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-15,"src":"5380:3:0","typeDescriptions":{"typeIdentifier":"t_magic_message","typeString":"msg"}},"id":628,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"sender","nodeType":"MemberAccess","src":"5380:10:0","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":626,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"5372:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":625,"name":"address","nodeType":"ElementaryTypeName","src":"5372:7:0","typeDescriptions":{}}},"id":629,"isConstant":false,"isLValue":false,"isPure":false,"kind":"typeConversion","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5372:19:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_stringliteral_b3cc13bc51228b2c4c4334d82a4772908254dc0e1c512893dd16208ef13efb8e","typeString":"literal_string \"hello msg.sender\""},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":621,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"5340:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":623,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":171,"src":"5340:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$_t_address_$returns$__$","typeString":"function (string memory,address) pure"}},"id":630,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5340:52:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":631,"nodeType":"ExpressionStatement","src":"5340:52:0"}]},"documentation":{"id":610,"nodeType":"StructuredDocumentation","src":"5167:84:0","text":"@notice example external function, to force a CALL, and test vm.startPrank with."},"functionSelector":"a777d0dc","implemented":true,"kind":"function","modifiers":[],"name":"hello","nameLocation":"5265:5:0","parameters":{"id":613,"nodeType":"ParameterList","parameters":[{"constant":false,"id":612,"mutability":"mutable","name":"_v","nameLocation":"5287:2:0","nodeType":"VariableDeclaration","scope":633,"src":"5271:18:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":611,"name":"string","nodeType":"ElementaryTypeName","src":"5271:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"5270:20:0"},"returnParameters":{"id":614,"nodeType":"ParameterList","parameters":[],"src":"5305:0:0"},"scope":706,"stateMutability":"view","virtual":false,"visibility":"external"},{"id":648,"nodeType":"FunctionDefinition","src":"5405:95:0","nodes":[],"body":{"id":647,"nodeType":"Block","src":"5449:51:0","nodes":[],"statements":[{"expression":{"id":639,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"UnaryOperation","operator":"++","prefix":false,"src":"5459:9:0","subExpression":{"id":638,"name":"counter","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":215,"src":"5459:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"id":640,"nodeType":"ExpressionStatement","src":"5459:9:0"},{"expression":{"arguments":[{"id":644,"name":"_v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":635,"src":"5490:2:0","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}],"expression":{"id":641,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"5478:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":643,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"5478:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":645,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5478:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":646,"nodeType":"ExpressionStatement","src":"5478:15:0"}]},"functionSelector":"7e79255d","implemented":true,"kind":"function","modifiers":[],"name":"call1","nameLocation":"5414:5:0","parameters":{"id":636,"nodeType":"ParameterList","parameters":[{"constant":false,"id":635,"mutability":"mutable","name":"_v","nameLocation":"5436:2:0","nodeType":"VariableDeclaration","scope":648,"src":"5420:18:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":634,"name":"string","nodeType":"ElementaryTypeName","src":"5420:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"5419:20:0"},"returnParameters":{"id":637,"nodeType":"ParameterList","parameters":[],"src":"5449:0:0"},"scope":706,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":663,"nodeType":"FunctionDefinition","src":"5506:95:0","nodes":[],"body":{"id":662,"nodeType":"Block","src":"5550:51:0","nodes":[],"statements":[{"expression":{"id":654,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"UnaryOperation","operator":"++","prefix":false,"src":"5560:9:0","subExpression":{"id":653,"name":"counter","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":215,"src":"5560:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"id":655,"nodeType":"ExpressionStatement","src":"5560:9:0"},{"expression":{"arguments":[{"id":659,"name":"_v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":650,"src":"5591:2:0","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}],"expression":{"id":656,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"5579:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":658,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"5579:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":660,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5579:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":661,"nodeType":"ExpressionStatement","src":"5579:15:0"}]},"functionSelector":"8d3ef7ca","implemented":true,"kind":"function","modifiers":[],"name":"call2","nameLocation":"5515:5:0","parameters":{"id":651,"nodeType":"ParameterList","parameters":[{"constant":false,"id":650,"mutability":"mutable","name":"_v","nameLocation":"5537:2:0","nodeType":"VariableDeclaration","scope":663,"src":"5521:18:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":649,"name":"string","nodeType":"ElementaryTypeName","src":"5521:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"5520:20:0"},"returnParameters":{"id":652,"nodeType":"ParameterList","parameters":[],"src":"5550:0:0"},"scope":706,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":678,"nodeType":"FunctionDefinition","src":"5607:98:0","nodes":[],"body":{"id":677,"nodeType":"Block","src":"5653:52:0","nodes":[],"statements":[{"expression":{"id":669,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"UnaryOperation","operator":"++","prefix":false,"src":"5663:9:0","subExpression":{"id":668,"name":"counter","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":215,"src":"5663:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"id":670,"nodeType":"ExpressionStatement","src":"5663:9:0"},{"expression":{"arguments":[{"id":674,"name":"_v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":665,"src":"5695:2:0","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}],"expression":{"id":671,"name":"this","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":-28,"src":"5682:4:0","typeDescriptions":{"typeIdentifier":"t_contract$_ScriptExample_$706","typeString":"contract ScriptExample"}},"id":673,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"nested2","nodeType":"MemberAccess","referencedDeclaration":693,"src":"5682:12:0","typeDescriptions":{"typeIdentifier":"t_function_external_nonpayable$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) external"}},"id":675,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5682:16:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":676,"nodeType":"ExpressionStatement","src":"5682:16:0"}]},"functionSelector":"a76ccdfa","implemented":true,"kind":"function","modifiers":[],"name":"nested1","nameLocation":"5616:7:0","parameters":{"id":666,"nodeType":"ParameterList","parameters":[{"constant":false,"id":665,"mutability":"mutable","name":"_v","nameLocation":"5640:2:0","nodeType":"VariableDeclaration","scope":678,"src":"5624:18:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":664,"name":"string","nodeType":"ElementaryTypeName","src":"5624:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"5623:20:0"},"returnParameters":{"id":667,"nodeType":"ParameterList","parameters":[],"src":"5653:0:0"},"scope":706,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":693,"nodeType":"FunctionDefinition","src":"5711:97:0","nodes":[],"body":{"id":692,"nodeType":"Block","src":"5757:51:0","nodes":[],"statements":[{"expression":{"id":684,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"UnaryOperation","operator":"++","prefix":false,"src":"5767:9:0","subExpression":{"id":683,"name":"counter","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":215,"src":"5767:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"id":685,"nodeType":"ExpressionStatement","src":"5767:9:0"},{"expression":{"arguments":[{"id":689,"name":"_v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":680,"src":"5798:2:0","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}],"expression":{"id":686,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"5786:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":688,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"5786:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":690,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5786:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":691,"nodeType":"ExpressionStatement","src":"5786:15:0"}]},"functionSelector":"dbf1282f","implemented":true,"kind":"function","modifiers":[],"name":"nested2","nameLocation":"5720:7:0","parameters":{"id":681,"nodeType":"ParameterList","parameters":[{"constant":false,"id":680,"mutability":"mutable","name":"_v","nameLocation":"5744:2:0","nodeType":"VariableDeclaration","scope":693,"src":"5728:18:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":679,"name":"string","nodeType":"ElementaryTypeName","src":"5728:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"5727:20:0"},"returnParameters":{"id":682,"nodeType":"ParameterList","parameters":[],"src":"5757:0:0"},"scope":706,"stateMutability":"nonpayable","virtual":false,"visibility":"external"},{"id":705,"nodeType":"FunctionDefinition","src":"5814:84:0","nodes":[],"body":{"id":704,"nodeType":"Block","src":"5866:32:0","nodes":[],"statements":[{"expression":{"arguments":[{"id":701,"name":"_v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":695,"src":"5888:2:0","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_string_calldata_ptr","typeString":"string calldata"}],"expression":{"id":698,"name":"console","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":192,"src":"5876:7:0","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_console_$192_$","typeString":"type(library console)"}},"id":700,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberName":"log","nodeType":"MemberAccess","referencedDeclaration":120,"src":"5876:11:0","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_string_memory_ptr_$returns$__$","typeString":"function (string memory) pure"}},"id":702,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"names":[],"nodeType":"FunctionCall","src":"5876:15:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":703,"nodeType":"ExpressionStatement","src":"5876:15:0"}]},"functionSelector":"7f8b915c","implemented":true,"kind":"function","modifiers":[],"name":"callPure","nameLocation":"5823:8:0","parameters":{"id":696,"nodeType":"ParameterList","parameters":[{"constant":false,"id":695,"mutability":"mutable","name":"_v","nameLocation":"5848:2:0","nodeType":"VariableDeclaration","scope":705,"src":"5832:18:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_string_calldata_ptr","typeString":"string"},"typeName":{"id":694,"name":"string","nodeType":"ElementaryTypeName","src":"5832:6:0","typeDescriptions":{"typeIdentifier":"t_string_storage_ptr","typeString":"string"}},"visibility":"internal"}],"src":"5831:20:0"},"returnParameters":{"id":697,"nodeType":"ParameterList","parameters":[],"src":"5866:0:0"},"scope":706,"stateMutability":"pure","virtual":false,"visibility":"external"}],"abstract":false,"baseContracts":[],"canonicalName":"ScriptExample","contractDependencies":[719],"contractKind":"contract","documentation":{"id":193,"nodeType":"StructuredDocumentation","src":"2415:126:0","text":"@title ScriptExample\n @notice ScriptExample is an example script. The Go forge script code tests that it can run this."},"fullyImplemented":true,"linearizedBaseContracts":[706],"name":"ScriptExample","nameLocation":"2550:13:0","scope":720,"usedErrors":[]},{"id":719,"nodeType":"ContractDefinition","src":"5902:96:0","nodes":[{"id":708,"nodeType":"VariableDeclaration","src":"5924:18:0","nodes":[],"constant":false,"functionSelector":"c2985578","mutability":"mutable","name":"foo","nameLocation":"5939:3:0","scope":719,"stateVariable":true,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":707,"name":"uint256","nodeType":"ElementaryTypeName","src":"5924:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"public"},{"id":718,"nodeType":"FunctionDefinition","src":"5949:47:0","nodes":[],"body":{"id":717,"nodeType":"Block","src":"5972:24:0","nodes":[],"statements":[{"expression":{"id":715,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"leftHandSide":{"id":713,"name":"foo","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":708,"src":"5982:3:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"nodeType":"Assignment","operator":"=","rightHandSide":{"id":714,"name":"v","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":710,"src":"5988:1:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"src":"5982:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"id":716,"nodeType":"ExpressionStatement","src":"5982:7:0"}]},"implemented":true,"kind":"constructor","modifiers":[],"name":"","nameLocation":"-1:-1:-1","parameters":{"id":711,"nodeType":"ParameterList","parameters":[{"constant":false,"id":710,"mutability":"mutable","name":"v","nameLocation":"5969:1:0","nodeType":"VariableDeclaration","scope":718,"src":"5961:9:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":709,"name":"uint256","nodeType":"ElementaryTypeName","src":"5961:7:0","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"}],"src":"5960:11:0"},"returnParameters":{"id":712,"nodeType":"ParameterList","parameters":[],"src":"5972:0:0"},"scope":719,"stateMutability":"nonpayable","virtual":false,"visibility":"public"}],"abstract":false,"baseContracts":[],"canonicalName":"FooBar","contractDependencies":[],"contractKind":"contract","fullyImplemented":true,"linearizedBaseContracts":[719],"name":"FooBar","nameLocation":"5911:6:0","scope":720,"usedErrors":[]}],"license":"MIT"},"id":0} +\ No newline at end of file
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + (deleted) + +
+
+
+ +
+ +
+ +
+0
+
-45
+ +
+ +
+
+
diff --git OP/op-challenger/game/fault/trace/asterisc/prestate.go CELO/op-challenger/game/fault/trace/asterisc/prestate.go +deleted file mode 100644 +index f65e4d9c901cd8fb01bda99fec7efa90848f1f2f..0000000000000000000000000000000000000000 +--- OP/op-challenger/game/fault/trace/asterisc/prestate.go ++++ /dev/null +@@ -1,45 +0,0 @@ +-package asterisc +- +-import ( +- "context" +- "fmt" +- +- "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" +- "github.com/ethereum/go-ethereum/common" +-) +- +-var _ types.PrestateProvider = (*AsteriscPreStateProvider)(nil) +- +-type AsteriscPreStateProvider struct { +- prestate string +- +- prestateCommitment common.Hash +-} +- +-func NewPrestateProvider(prestate string) *AsteriscPreStateProvider { +- return &AsteriscPreStateProvider{prestate: prestate} +-} +- +-func (p *AsteriscPreStateProvider) absolutePreState() (*VMState, error) { +- state, err := parseState(p.prestate) +- if err != nil { +- return nil, fmt.Errorf("cannot load absolute pre-state: %w", err) +- } +- return state, nil +-} +- +-func (p *AsteriscPreStateProvider) AbsolutePreStateCommitment(_ context.Context) (common.Hash, error) { +- if p.prestateCommitment != (common.Hash{}) { +- return p.prestateCommitment, nil +- } +- state, err := p.absolutePreState() +- if err != nil { +- return common.Hash{}, fmt.Errorf("cannot load absolute pre-state: %w", err) +- } +- p.prestateCommitment = state.StateHash +- return state.StateHash, nil +-} +- +-func (p *AsteriscPreStateProvider) PrestatePath() string { +- return p.prestate +-}
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + (deleted) + +
+
+
+ +
+ +
+ +
+0
+
-59
+ +
+ +
+
+
diff --git OP/op-challenger/game/fault/trace/asterisc/prestate_test.go CELO/op-challenger/game/fault/trace/asterisc/prestate_test.go +deleted file mode 100644 +index 38bc6d360e7b29ca7482f84020e9efd563d0b656..0000000000000000000000000000000000000000 +--- OP/op-challenger/game/fault/trace/asterisc/prestate_test.go ++++ /dev/null +@@ -1,59 +0,0 @@ +-package asterisc +- +-import ( +- "context" +- "os" +- "path/filepath" +- "testing" +- +- "github.com/stretchr/testify/require" +-) +- +-func newAsteriscPrestateProvider(dataDir string, prestate string) *AsteriscPreStateProvider { +- return &AsteriscPreStateProvider{ +- prestate: filepath.Join(dataDir, prestate), +- } +-} +- +-func TestAbsolutePreStateCommitment(t *testing.T) { +- dataDir := t.TempDir() +- +- prestate := "state.json" +- +- t.Run("StateUnavailable", func(t *testing.T) { +- provider := newAsteriscPrestateProvider("/dir/does/not/exist", prestate) +- _, err := provider.AbsolutePreStateCommitment(context.Background()) +- require.ErrorIs(t, err, os.ErrNotExist) +- }) +- +- t.Run("InvalidStateFile", func(t *testing.T) { +- setupPreState(t, dataDir, "invalid.json") +- provider := newAsteriscPrestateProvider(dataDir, prestate) +- _, err := provider.AbsolutePreStateCommitment(context.Background()) +- require.ErrorContains(t, err, "invalid asterisc VM state") +- }) +- +- t.Run("CacheAbsolutePreState", func(t *testing.T) { +- setupPreState(t, dataDir, prestate) +- provider := newAsteriscPrestateProvider(dataDir, prestate) +- first, err := provider.AbsolutePreStateCommitment(context.Background()) +- require.NoError(t, err) +- +- // Remove the prestate from disk +- require.NoError(t, os.Remove(provider.prestate)) +- +- // Value should still be available from cache +- cached, err := provider.AbsolutePreStateCommitment(context.Background()) +- require.NoError(t, err) +- require.Equal(t, first, cached) +- }) +-} +- +-func setupPreState(t *testing.T, dataDir string, filename string) { +- srcDir := filepath.Join("test_data") +- path := filepath.Join(srcDir, filename) +- file, err := testData.ReadFile(path) +- require.NoErrorf(t, err, "reading %v", path) +- err = os.WriteFile(filepath.Join(dataDir, "state.json"), file, 0o644) +- require.NoErrorf(t, err, "writing %v", path) +-}
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+19
+
-28
+ +
+ +
+
+
diff --git OP/op-challenger/game/fault/trace/asterisc/provider.go CELO/op-challenger/game/fault/trace/asterisc/provider.go +index cad5e36b839e084427d5b40fcfe174b0dcf0d791..2ea1b729709e9f72e1f99a756dd2618f954228b2 100644 +--- OP/op-challenger/game/fault/trace/asterisc/provider.go ++++ CELO/op-challenger/game/fault/trace/asterisc/provider.go +@@ -15,6 +15,7 @@ "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/utils" + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/vm" + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" + "github.com/ethereum-optimism/optimism/op-program/host/kvstore" ++ kvtypes "github.com/ethereum-optimism/optimism/op-program/host/types" + "github.com/ethereum-optimism/optimism/op-service/ioutil" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/log" +@@ -27,6 +28,8 @@ prestate string + generator utils.ProofGenerator + gameDepth types.Depth + preimageLoader *utils.PreimageLoader ++ stateConverter vm.StateConverter ++ cfg vm.Config +  + types.PrestateProvider +  +@@ -42,10 +45,12 @@ dir: dir, + prestate: asteriscPrestate, + generator: vm.NewExecutor(logger, m, cfg, vmCfg, asteriscPrestate, localInputs), + gameDepth: gameDepth, +- preimageLoader: utils.NewPreimageLoader(func() utils.PreimageSource { +- return kvstore.NewFileKV(vm.PreimageDir(dir)) ++ preimageLoader: utils.NewPreimageLoader(func() (utils.PreimageSource, error) { ++ return kvstore.NewDiskKV(logger, vm.PreimageDir(dir), kvtypes.DataFormatFile) + }), + PrestateProvider: prestateProvider, ++ stateConverter: NewStateConverter(), ++ cfg: cfg, + } + } +  +@@ -120,31 +125,23 @@ // Try opening the file again now and it should exist. + file, err = ioutil.OpenDecompressed(path) + if errors.Is(err, os.ErrNotExist) { + // Expected proof wasn't generated, check if we reached the end of execution +- state, err := p.finalState() ++ proof, step, exited, err := p.stateConverter.ConvertStateToProof(vm.FinalStatePath(p.dir, p.cfg.BinarySnapshots)) + if err != nil { + return nil, err + } +- if state.Exited && state.Step <= i { +- p.logger.Warn("Requested proof was after the program exited", "proof", i, "last", state.Step) ++ if exited && step <= i { ++ p.logger.Warn("Requested proof was after the program exited", "proof", i, "last", step) + // The final instruction has already been applied to this state, so the last step we can execute + // is one before its Step value. +- p.lastStep = state.Step - 1 ++ p.lastStep = step - 1 + // Extend the trace out to the full length using a no-op instruction that doesn't change any state + // No execution is done, so no proof-data or oracle values are required. +- proof := &utils.ProofData{ +- ClaimValue: state.StateHash, +- StateData: state.Witness, +- ProofData: []byte{}, +- OracleKey: nil, +- OracleValue: nil, +- OracleOffset: 0, +- } + if err := utils.WriteLastStep(p.dir, proof, p.lastStep); err != nil { + p.logger.Warn("Failed to write last step to disk cache", "step", p.lastStep) + } + return proof, nil + } else { +- return nil, fmt.Errorf("expected proof not generated but final state was not exited, requested step %v, final state at step %v", i, state.Step) ++ return nil, fmt.Errorf("expected proof not generated but final state was not exited, requested step %v, final state at step %v", i, step) + } + } + } +@@ -160,14 +157,6 @@ } + return &proof, nil + } +  +-func (c *AsteriscTraceProvider) finalState() (*VMState, error) { +- state, err := parseState(filepath.Join(c.dir, vm.FinalState)) +- if err != nil { +- return nil, fmt.Errorf("cannot read final state: %w", err) +- } +- return state, nil +-} +- + // AsteriscTraceProviderForTest is a AsteriscTraceProvider that can find the step referencing the preimage read + // Only to be used for testing + type AsteriscTraceProviderForTest struct { +@@ -181,9 +170,11 @@ dir: dir, + prestate: cfg.AsteriscAbsolutePreState, + generator: vm.NewExecutor(logger, m, cfg.Asterisc, vm.NewOpProgramServerExecutor(), cfg.AsteriscAbsolutePreState, localInputs), + gameDepth: gameDepth, +- preimageLoader: utils.NewPreimageLoader(func() utils.PreimageSource { +- return kvstore.NewFileKV(vm.PreimageDir(dir)) ++ preimageLoader: utils.NewPreimageLoader(func() (utils.PreimageSource, error) { ++ return kvstore.NewDiskKV(logger, vm.PreimageDir(dir), kvtypes.DataFormatFile) + }), ++ stateConverter: NewStateConverter(), ++ cfg: cfg.Asterisc, + } + return &AsteriscTraceProviderForTest{p} + } +@@ -194,14 +185,14 @@ if err := p.generator.(*vm.Executor).DoGenerateProof(ctx, p.dir, start, math.MaxUint64, preimage()...); err != nil { + return 0, fmt.Errorf("generate asterisc trace (until preimage read): %w", err) + } + // Load the step from the state asterisc finished with +- state, err := p.finalState() ++ _, step, exited, err := p.stateConverter.ConvertStateToProof(vm.FinalStatePath(p.dir, p.cfg.BinarySnapshots)) + if err != nil { + return 0, fmt.Errorf("failed to load final state: %w", err) + } + // Check we didn't get to the end of the trace without finding the preimage read we were looking for +- if state.Exited { ++ if exited { + return 0, fmt.Errorf("preimage read not found: %w", io.EOF) + } + // The state is the post-state so the step we want to execute to read the preimage is step - 1. +- return state.Step - 1, nil ++ return step - 1, nil + }
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+7
+
-6
+ +
+ +
+
+
diff --git OP/op-challenger/game/fault/trace/asterisc/provider_test.go CELO/op-challenger/game/fault/trace/asterisc/provider_test.go +index 939a27decc304e256a04b8b7118b3cd1e9dc4844..ce80b3403dac74a1a81fec89b99bc77b35154bd7 100644 +--- OP/op-challenger/game/fault/trace/asterisc/provider_test.go ++++ CELO/op-challenger/game/fault/trace/asterisc/provider_test.go +@@ -221,11 +221,12 @@ + func setupWithTestData(t *testing.T, dataDir string, prestate string) (*AsteriscTraceProvider, *stubGenerator) { + generator := &stubGenerator{} + return &AsteriscTraceProvider{ +- logger: testlog.Logger(t, log.LevelInfo), +- dir: dataDir, +- generator: generator, +- prestate: filepath.Join(dataDir, prestate), +- gameDepth: 63, ++ logger: testlog.Logger(t, log.LevelInfo), ++ dir: dataDir, ++ generator: generator, ++ prestate: filepath.Join(dataDir, prestate), ++ gameDepth: 63, ++ stateConverter: &StateConverter{}, + }, generator + } +  +@@ -242,7 +243,7 @@ var data []byte + var err error + if e.finalState != nil && e.finalState.Step <= i { + // Requesting a trace index past the end of the trace +- proofFile = filepath.Join(dir, vm.FinalState) ++ proofFile = vm.FinalStatePath(dir, false) + data, err = json.Marshal(e.finalState) + if err != nil { + return err
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+25
+
-0
+ +
+ +
+
+
diff --git OP/op-challenger/game/fault/trace/asterisc/state.go CELO/op-challenger/game/fault/trace/asterisc/state_converter.go +rename from op-challenger/game/fault/trace/asterisc/state.go +rename to op-challenger/game/fault/trace/asterisc/state_converter.go +index e30ebf8702d8287916cfe5273c0ab0ae2d19f709..29c9f8b2ea50db50362353bfe5f30a7b4237c6dc 100644 +--- OP/op-challenger/game/fault/trace/asterisc/state.go ++++ CELO/op-challenger/game/fault/trace/asterisc/state_converter.go +@@ -8,6 +8,7 @@ + "github.com/ethereum/go-ethereum/common" +  + "github.com/ethereum-optimism/optimism/cannon/mipsevm" ++ "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/utils" + "github.com/ethereum-optimism/optimism/op-service/ioutil" + ) +  +@@ -74,3 +75,27 @@ return nil, fmt.Errorf("invalid asterisc VM state %w", err) + } + return &state, nil + } ++ ++type StateConverter struct { ++} ++ ++func NewStateConverter() *StateConverter { ++ return &StateConverter{} ++} ++ ++func (c *StateConverter) ConvertStateToProof(statePath string) (*utils.ProofData, uint64, bool, error) { ++ state, err := parseState(statePath) ++ if err != nil { ++ return nil, 0, false, fmt.Errorf("cannot read final state: %w", err) ++ } ++ // Extend the trace out to the full length using a no-op instruction that doesn't change any state ++ // No execution is done, so no proof-data or oracle values are required. ++ return &utils.ProofData{ ++ ClaimValue: state.StateHash, ++ StateData: state.Witness, ++ ProofData: []byte{}, ++ OracleKey: nil, ++ OracleValue: nil, ++ OracleOffset: 0, ++ }, state.Step, state.Exited, nil ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+0
+
-0
+ +
+ +
+
+
diff --git OP/op-challenger/game/fault/trace/asterisc/state_test.go CELO/op-challenger/game/fault/trace/asterisc/state_converter_test.go +rename from op-challenger/game/fault/trace/asterisc/state_test.go +rename to op-challenger/game/fault/trace/asterisc/state_converter_test.go
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + (deleted) + +
+
+
+ +
+ +
+ +
+0
+
-47
+ +
+ +
+
+
diff --git OP/op-challenger/game/fault/trace/cannon/prestate.go CELO/op-challenger/game/fault/trace/cannon/prestate.go +deleted file mode 100644 +index 6fcb8f50f6628dbc69bb1069c0ecad57c108cdb7..0000000000000000000000000000000000000000 +--- OP/op-challenger/game/fault/trace/cannon/prestate.go ++++ /dev/null +@@ -1,47 +0,0 @@ +-package cannon +- +-import ( +- "context" +- "fmt" +- +- "github.com/ethereum/go-ethereum/common" +- +- "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" +-) +- +-var _ types.PrestateProvider = (*CannonPrestateProvider)(nil) +- +-type CannonPrestateProvider struct { +- prestate string +- +- prestateCommitment common.Hash +-} +- +-func NewPrestateProvider(prestate string) *CannonPrestateProvider { +- return &CannonPrestateProvider{prestate: prestate} +-} +- +-func (p *CannonPrestateProvider) absolutePreState() ([]byte, common.Hash, error) { +- state, err := parseState(p.prestate) +- if err != nil { +- return nil, common.Hash{}, fmt.Errorf("cannot load absolute pre-state: %w", err) +- } +- witness, hash := state.EncodeWitness() +- return witness, hash, nil +-} +- +-func (p *CannonPrestateProvider) AbsolutePreStateCommitment(_ context.Context) (common.Hash, error) { +- if p.prestateCommitment != (common.Hash{}) { +- return p.prestateCommitment, nil +- } +- _, hash, err := p.absolutePreState() +- if err != nil { +- return common.Hash{}, fmt.Errorf("cannot load absolute pre-state: %w", err) +- } +- p.prestateCommitment = hash +- return hash, nil +-} +- +-func (p *CannonPrestateProvider) PrestatePath() string { +- return p.prestate +-}
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + (deleted) + +
+
+
+ +
+ +
+ +
+0
+
-89
+ +
+ +
+
+
diff --git OP/op-challenger/game/fault/trace/cannon/prestate_test.go CELO/op-challenger/game/fault/trace/cannon/prestate_test.go +deleted file mode 100644 +index 9566e9d0664cc4f137439d67fcfc21cad9964003..0000000000000000000000000000000000000000 +--- OP/op-challenger/game/fault/trace/cannon/prestate_test.go ++++ /dev/null +@@ -1,89 +0,0 @@ +-package cannon +- +-import ( +- "context" +- "os" +- "path/filepath" +- "testing" +- +- "github.com/ethereum/go-ethereum/common" +- "github.com/stretchr/testify/require" +- +- "github.com/ethereum-optimism/optimism/cannon/mipsevm" +- "github.com/ethereum-optimism/optimism/cannon/mipsevm/memory" +- "github.com/ethereum-optimism/optimism/cannon/mipsevm/singlethreaded" +-) +- +-func newCannonPrestateProvider(dataDir string, prestate string) *CannonPrestateProvider { +- return &CannonPrestateProvider{ +- prestate: filepath.Join(dataDir, prestate), +- } +-} +- +-func TestAbsolutePreStateCommitment(t *testing.T) { +- dataDir := t.TempDir() +- +- prestate := "state.json" +- +- t.Run("StateUnavailable", func(t *testing.T) { +- provider := newCannonPrestateProvider("/dir/does/not/exist", prestate) +- _, err := provider.AbsolutePreStateCommitment(context.Background()) +- require.ErrorIs(t, err, os.ErrNotExist) +- }) +- +- t.Run("InvalidStateFile", func(t *testing.T) { +- setupPreState(t, dataDir, "invalid.json") +- provider := newCannonPrestateProvider(dataDir, prestate) +- _, err := provider.AbsolutePreStateCommitment(context.Background()) +- require.ErrorContains(t, err, "invalid mipsevm state") +- }) +- +- t.Run("ExpectedAbsolutePreState", func(t *testing.T) { +- setupPreState(t, dataDir, "state.json") +- provider := newCannonPrestateProvider(dataDir, prestate) +- actual, err := provider.AbsolutePreStateCommitment(context.Background()) +- require.NoError(t, err) +- state := singlethreaded.State{ +- Memory: memory.NewMemory(), +- PreimageKey: common.HexToHash("cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"), +- PreimageOffset: 0, +- Cpu: mipsevm.CpuScalars{ +- PC: 0, +- NextPC: 1, +- LO: 0, +- HI: 0, +- }, +- Heap: 0, +- ExitCode: 0, +- Exited: false, +- Step: 0, +- Registers: [32]uint32{}, +- } +- _, expected := state.EncodeWitness() +- require.Equal(t, expected, actual) +- }) +- +- t.Run("CacheAbsolutePreState", func(t *testing.T) { +- setupPreState(t, dataDir, prestate) +- provider := newCannonPrestateProvider(dataDir, prestate) +- first, err := provider.AbsolutePreStateCommitment(context.Background()) +- require.NoError(t, err) +- +- // Remove the prestate from disk +- require.NoError(t, os.Remove(provider.prestate)) +- +- // Value should still be available from cache +- cached, err := provider.AbsolutePreStateCommitment(context.Background()) +- require.NoError(t, err) +- require.Equal(t, first, cached) +- }) +-} +- +-func setupPreState(t *testing.T, dataDir string, filename string) { +- srcDir := filepath.Join("test_data") +- path := filepath.Join(srcDir, filename) +- file, err := testData.ReadFile(path) +- require.NoErrorf(t, err, "reading %v", path) +- err = os.WriteFile(filepath.Join(dataDir, "state.json"), file, 0o644) +- require.NoErrorf(t, err, "writing %v", path) +-}
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+22
+
-35
+ +
+ +
+
+
diff --git OP/op-challenger/game/fault/trace/cannon/provider.go CELO/op-challenger/game/fault/trace/cannon/provider.go +index fc7a71c1cda0b8682f3e321f6bf8a196d4a49e26..823f8c6d814b17a01d80e2105451863faf62f88b 100644 +--- OP/op-challenger/game/fault/trace/cannon/provider.go ++++ CELO/op-challenger/game/fault/trace/cannon/provider.go +@@ -10,11 +10,10 @@ "math" + "os" + "path/filepath" +  ++ kvtypes "github.com/ethereum-optimism/optimism/op-program/host/types" + "github.com/ethereum/go-ethereum/common" +- "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/log" +  +- "github.com/ethereum-optimism/optimism/cannon/mipsevm/singlethreaded" + "github.com/ethereum-optimism/optimism/op-challenger/config" + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/utils" + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/vm" +@@ -30,6 +29,8 @@ prestate string + generator utils.ProofGenerator + gameDepth types.Depth + preimageLoader *utils.PreimageLoader ++ stateConverter vm.StateConverter ++ cfg vm.Config +  + types.PrestateProvider +  +@@ -45,10 +46,12 @@ dir: dir, + prestate: prestate, + generator: vm.NewExecutor(logger, m, cfg, vmCfg, prestate, localInputs), + gameDepth: gameDepth, +- preimageLoader: utils.NewPreimageLoader(func() utils.PreimageSource { +- return kvstore.NewFileKV(vm.PreimageDir(dir)) ++ preimageLoader: utils.NewPreimageLoader(func() (utils.PreimageSource, error) { ++ return kvstore.NewDiskKV(logger, vm.PreimageDir(dir), kvtypes.DataFormatFile) + }), + PrestateProvider: prestateProvider, ++ stateConverter: &StateConverter{}, ++ cfg: cfg, + } + } +  +@@ -122,33 +125,22 @@ } + // Try opening the file again now and it should exist. + file, err = ioutil.OpenDecompressed(path) + if errors.Is(err, os.ErrNotExist) { +- // Expected proof wasn't generated, check if we reached the end of execution +- state, err := p.finalState() ++ proof, stateStep, exited, err := p.stateConverter.ConvertStateToProof(vm.FinalStatePath(p.dir, p.cfg.BinarySnapshots)) + if err != nil { +- return nil, err ++ return nil, fmt.Errorf("cannot create proof from final state: %w", err) + } +- if state.Exited && state.Step <= i { +- p.logger.Warn("Requested proof was after the program exited", "proof", i, "last", state.Step) ++ ++ if exited && stateStep <= i { ++ p.logger.Warn("Requested proof was after the program exited", "proof", i, "last", stateStep) + // The final instruction has already been applied to this state, so the last step we can execute + // is one before its Step value. +- p.lastStep = state.Step - 1 +- // Extend the trace out to the full length using a no-op instruction that doesn't change any state +- // No execution is done, so no proof-data or oracle values are required. +- witness, witnessHash := state.EncodeWitness() +- proof := &utils.ProofData{ +- ClaimValue: witnessHash, +- StateData: hexutil.Bytes(witness), +- ProofData: []byte{}, +- OracleKey: nil, +- OracleValue: nil, +- OracleOffset: 0, +- } ++ p.lastStep = stateStep - 1 + if err := utils.WriteLastStep(p.dir, proof, p.lastStep); err != nil { + p.logger.Warn("Failed to write last step to disk cache", "step", p.lastStep) + } + return proof, nil + } else { +- return nil, fmt.Errorf("expected proof not generated but final state was not exited, requested step %v, final state at step %v", i, state.Step) ++ return nil, fmt.Errorf("expected proof not generated but final state was not exited, requested step %v, final state at step %v", i, stateStep) + } + } + } +@@ -164,14 +156,6 @@ } + return &proof, nil + } +  +-func (c *CannonTraceProvider) finalState() (*singlethreaded.State, error) { +- state, err := parseState(filepath.Join(c.dir, vm.FinalState)) +- if err != nil { +- return nil, fmt.Errorf("cannot read final state: %w", err) +- } +- return state, nil +-} +- + // CannonTraceProviderForTest is a CannonTraceProvider that can find the step referencing the preimage read + // Only to be used for testing + type CannonTraceProviderForTest struct { +@@ -185,9 +169,11 @@ dir: dir, + prestate: cfg.CannonAbsolutePreState, + generator: vm.NewExecutor(logger, m, cfg.Cannon, vm.NewOpProgramServerExecutor(), cfg.CannonAbsolutePreState, localInputs), + gameDepth: gameDepth, +- preimageLoader: utils.NewPreimageLoader(func() utils.PreimageSource { +- return kvstore.NewFileKV(vm.PreimageDir(dir)) ++ preimageLoader: utils.NewPreimageLoader(func() (utils.PreimageSource, error) { ++ return kvstore.NewDiskKV(logger, vm.PreimageDir(dir), kvtypes.DataFormatFile) + }), ++ stateConverter: NewStateConverter(), ++ cfg: cfg.Cannon, + } + return &CannonTraceProviderForTest{p} + } +@@ -198,14 +184,15 @@ if err := p.generator.(*vm.Executor).DoGenerateProof(ctx, p.dir, start, math.MaxUint64, preimage()...); err != nil { + return 0, fmt.Errorf("generate cannon trace (until preimage read): %w", err) + } + // Load the step from the state cannon finished with +- state, err := p.finalState() ++ ++ _, step, exited, err := p.stateConverter.ConvertStateToProof(vm.FinalStatePath(p.dir, p.cfg.BinarySnapshots)) + if err != nil { + return 0, fmt.Errorf("failed to load final state: %w", err) + } + // Check we didn't get to the end of the trace without finding the preimage read we were looking for +- if state.Exited { ++ if exited { + return 0, fmt.Errorf("preimage read not found: %w", io.EOF) + } + // The state is the post-state so the step we want to execute to read the preimage is step - 1. +- return state.Step - 1, nil ++ return step - 1, nil + }
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+7
+
-6
+ +
+ +
+
+
diff --git OP/op-challenger/game/fault/trace/cannon/provider_test.go CELO/op-challenger/game/fault/trace/cannon/provider_test.go +index 3343b581f1c16eaf0aed012f8c07ddabfb4782fa..82edc5562623de4b0b8e4b441ad97cbdfe824dee 100644 +--- OP/op-challenger/game/fault/trace/cannon/provider_test.go ++++ CELO/op-challenger/game/fault/trace/cannon/provider_test.go +@@ -239,11 +239,12 @@ + func setupWithTestData(t *testing.T, dataDir string, prestate string) (*CannonTraceProvider, *stubGenerator) { + generator := &stubGenerator{} + return &CannonTraceProvider{ +- logger: testlog.Logger(t, log.LevelInfo), +- dir: dataDir, +- generator: generator, +- prestate: filepath.Join(dataDir, prestate), +- gameDepth: 63, ++ logger: testlog.Logger(t, log.LevelInfo), ++ dir: dataDir, ++ generator: generator, ++ prestate: filepath.Join(dataDir, prestate), ++ gameDepth: 63, ++ stateConverter: &StateConverter{}, + }, generator + } +  +@@ -260,7 +261,7 @@ var data []byte + var err error + if e.finalState != nil && e.finalState.Step <= i { + // Requesting a trace index past the end of the trace +- proofFile = filepath.Join(dir, vm.FinalState) ++ proofFile = vm.FinalStatePath(dir, false) + data, err = json.Marshal(e.finalState) + if err != nil { + return err
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + (deleted) + +
+
+
+ +
+ +
+ +
+0
+
-27
+ +
+ +
+
+
diff --git OP/op-challenger/game/fault/trace/cannon/state.go CELO/op-challenger/game/fault/trace/cannon/state.go +deleted file mode 100644 +index cf781c8bd428b424246cfe1450569d1c13abb69e..0000000000000000000000000000000000000000 +--- OP/op-challenger/game/fault/trace/cannon/state.go ++++ /dev/null +@@ -1,27 +0,0 @@ +-package cannon +- +-import ( +- "encoding/json" +- "fmt" +- "io" +- +- "github.com/ethereum-optimism/optimism/cannon/mipsevm/singlethreaded" +- "github.com/ethereum-optimism/optimism/op-service/ioutil" +-) +- +-func parseState(path string) (*singlethreaded.State, error) { +- file, err := ioutil.OpenDecompressed(path) +- if err != nil { +- return nil, fmt.Errorf("cannot open state file (%v): %w", path, err) +- } +- return parseStateFromReader(file) +-} +- +-func parseStateFromReader(in io.ReadCloser) (*singlethreaded.State, error) { +- defer in.Close() +- var state singlethreaded.State +- if err := json.NewDecoder(in).Decode(&state); err != nil { +- return nil, fmt.Errorf("invalid mipsevm state: %w", err) +- } +- return &state, nil +-}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+38
+
-0
+ +
+ +
+
+
diff --git OP/op-challenger/game/fault/trace/cannon/state_converter.go CELO/op-challenger/game/fault/trace/cannon/state_converter.go +new file mode 100644 +index 0000000000000000000000000000000000000000..248676cc326e4a919a27f0b52b119b301f2080b7 +--- /dev/null ++++ CELO/op-challenger/game/fault/trace/cannon/state_converter.go +@@ -0,0 +1,38 @@ ++package cannon ++ ++import ( ++ "fmt" ++ ++ "github.com/ethereum-optimism/optimism/cannon/mipsevm" ++ "github.com/ethereum-optimism/optimism/cannon/mipsevm/versions" ++ "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/utils" ++) ++ ++type StateConverter struct { ++} ++ ++func NewStateConverter() *StateConverter { ++ return &StateConverter{} ++} ++ ++func (c *StateConverter) ConvertStateToProof(statePath string) (*utils.ProofData, uint64, bool, error) { ++ state, err := parseState(statePath) ++ if err != nil { ++ return nil, 0, false, fmt.Errorf("cannot read final state: %w", err) ++ } ++ // Extend the trace out to the full length using a no-op instruction that doesn't change any state ++ // No execution is done, so no proof-data or oracle values are required. ++ witness, witnessHash := state.EncodeWitness() ++ return &utils.ProofData{ ++ ClaimValue: witnessHash, ++ StateData: witness, ++ ProofData: []byte{}, ++ OracleKey: nil, ++ OracleValue: nil, ++ OracleOffset: 0, ++ }, state.GetStep(), state.GetExited(), nil ++} ++ ++func parseState(path string) (mipsevm.FPVMState, error) { ++ return versions.LoadStateFromFile(path) ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+96
+
-0
+ +
+ +
+
+
diff --git OP/op-challenger/game/fault/trace/cannon/state_converter_test.go CELO/op-challenger/game/fault/trace/cannon/state_converter_test.go +new file mode 100644 +index 0000000000000000000000000000000000000000..c0c0182529ff69a8e6808fbcadc78d1447a2d444 +--- /dev/null ++++ CELO/op-challenger/game/fault/trace/cannon/state_converter_test.go +@@ -0,0 +1,96 @@ ++package cannon ++ ++import ( ++ _ "embed" ++ "path/filepath" ++ "testing" ++ ++ "github.com/ethereum-optimism/optimism/cannon/mipsevm" ++ "github.com/ethereum-optimism/optimism/cannon/mipsevm/multithreaded" ++ "github.com/ethereum-optimism/optimism/cannon/mipsevm/versions" ++ "github.com/ethereum-optimism/optimism/cannon/serialize" ++ "github.com/stretchr/testify/require" ++ ++ "github.com/ethereum-optimism/optimism/cannon/mipsevm/singlethreaded" ++) ++ ++func TestLoadState(t *testing.T) { ++ tests := []struct { ++ name string ++ creator func() mipsevm.FPVMState ++ supportsJSON bool ++ }{ ++ { ++ name: "singlethreaded", ++ creator: func() mipsevm.FPVMState { return singlethreaded.CreateInitialState(234, 82) }, ++ supportsJSON: true, ++ }, ++ { ++ name: "multithreaded", ++ creator: func() mipsevm.FPVMState { return multithreaded.CreateInitialState(982, 492) }, ++ supportsJSON: false, ++ }, ++ } ++ for _, test := range tests { ++ test := test ++ loadExpectedState := func(t *testing.T) *versions.VersionedState { ++ state, err := versions.NewFromState(test.creator()) ++ require.NoError(t, err) ++ return state ++ } ++ t.Run(test.name, func(t *testing.T) { ++ t.Run("Uncompressed", func(t *testing.T) { ++ if !test.supportsJSON { ++ t.Skip("JSON not supported by state version") ++ } ++ expected := loadExpectedState(t) ++ path := writeState(t, "state.json", expected) ++ ++ state, err := parseState(path) ++ require.NoError(t, err) ++ ++ require.Equal(t, expected, state) ++ }) ++ ++ t.Run("Gzipped", func(t *testing.T) { ++ if !test.supportsJSON { ++ t.Skip("JSON not supported by state version") ++ } ++ expected := loadExpectedState(t) ++ path := writeState(t, "state.json.gz", expected) ++ ++ state, err := parseState(path) ++ require.NoError(t, err) ++ ++ require.Equal(t, expected, state) ++ }) ++ ++ t.Run("Binary", func(t *testing.T) { ++ expected := loadExpectedState(t) ++ ++ path := writeState(t, "state.bin", expected) ++ ++ state, err := parseState(path) ++ require.NoError(t, err) ++ require.Equal(t, expected, state) ++ }) ++ ++ t.Run("BinaryGzip", func(t *testing.T) { ++ expected := loadExpectedState(t) ++ ++ path := writeState(t, "state.bin.gz", expected) ++ ++ state, err := parseState(path) ++ require.NoError(t, err) ++ require.Equal(t, expected, state) ++ }) ++ }) ++ } ++} ++ ++func writeState(t *testing.T, filename string, state *versions.VersionedState) string { ++ dir := t.TempDir() ++ path := filepath.Join(dir, filename) ++ require.NoError(t, serialize.Write(path, state, 0644)) ++ return path ++}
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + (deleted) + +
+
+
+ +
+ +
+ +
+0
+
-51
+ +
+ +
+
+
diff --git OP/op-challenger/game/fault/trace/cannon/state_test.go CELO/op-challenger/game/fault/trace/cannon/state_test.go +deleted file mode 100644 +index ce4757a356713e15420e68b0cc9f81c2d8e3cb0c..0000000000000000000000000000000000000000 +--- OP/op-challenger/game/fault/trace/cannon/state_test.go ++++ /dev/null +@@ -1,51 +0,0 @@ +-package cannon +- +-import ( +- "compress/gzip" +- _ "embed" +- "encoding/json" +- "os" +- "path/filepath" +- "testing" +- +- "github.com/stretchr/testify/require" +- +- "github.com/ethereum-optimism/optimism/cannon/mipsevm/singlethreaded" +-) +- +-//go:embed test_data/state.json +-var testState []byte +- +-func TestLoadState(t *testing.T) { +- t.Run("Uncompressed", func(t *testing.T) { +- dir := t.TempDir() +- path := filepath.Join(dir, "state.json") +- require.NoError(t, os.WriteFile(path, testState, 0644)) +- +- state, err := parseState(path) +- require.NoError(t, err) +- +- var expected singlethreaded.State +- require.NoError(t, json.Unmarshal(testState, &expected)) +- require.Equal(t, &expected, state) +- }) +- +- t.Run("Gzipped", func(t *testing.T) { +- dir := t.TempDir() +- path := filepath.Join(dir, "state.json.gz") +- f, err := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644) +- require.NoError(t, err) +- defer f.Close() +- writer := gzip.NewWriter(f) +- _, err = writer.Write(testState) +- require.NoError(t, err) +- require.NoError(t, writer.Close()) +- +- state, err := parseState(path) +- require.NoError(t, err) +- +- var expected singlethreaded.State +- require.NoError(t, json.Unmarshal(testState, &expected)) +- require.Equal(t, &expected, state) +- }) +-}
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + (deleted) + +
+
+
+ +
+ +
+ +
+0
+
-3
+ +
+ +
+
+
diff --git OP/op-challenger/game/fault/trace/cannon/test_data/invalid.json CELO/op-challenger/game/fault/trace/cannon/test_data/invalid.json +deleted file mode 100644 +index 06a76bf5b23dec2fd00927d436c219721ec76cf8..0000000000000000000000000000000000000000 +--- OP/op-challenger/game/fault/trace/cannon/test_data/invalid.json ++++ /dev/null +@@ -1,3 +0,0 @@ +-{ +- "preimageKey": 1 +-}
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + (deleted) + +
+
+
+ +
+ +
+ +
+0
+
-14
+ +
+ +
+
+
diff --git OP/op-challenger/game/fault/trace/cannon/test_data/state.json CELO/op-challenger/game/fault/trace/cannon/test_data/state.json +deleted file mode 100644 +index 30cd1ccdcf0c8c0f0ea1bc9974cd0a3b9874c2ee..0000000000000000000000000000000000000000 +--- OP/op-challenger/game/fault/trace/cannon/test_data/state.json ++++ /dev/null +@@ -1,14 +0,0 @@ +-{ +- "memory": [], +- "preimageKey": "0xcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc", +- "preimageOffset": 0, +- "pc": 0, +- "nextPC": 1, +- "lo": 0, +- "hi": 0, +- "heap": 0, +- "exit": 0, +- "exited": false, +- "step": 0, +- "registers": [] +-}
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+1
+
-1
+ +
+ +
+
+
diff --git OP/op-challenger/game/fault/trace/outputs/output_asterisc.go CELO/op-challenger/game/fault/trace/outputs/output_asterisc.go +index 726b57e551d7bf70f8feb27be43bdb1d7f950d6a..82dac14f8453fa3740cc1741c0525a07ea81ce16 100644 +--- OP/op-challenger/game/fault/trace/outputs/output_asterisc.go ++++ CELO/op-challenger/game/fault/trace/outputs/output_asterisc.go +@@ -41,7 +41,7 @@ localInputs, err := utils.FetchLocalInputsFromProposals(ctx, l1Head.Hash, l2Client, agreed, claimed) + if err != nil { + return nil, fmt.Errorf("failed to fetch asterisc local inputs: %w", err) + } +- provider := asterisc.NewTraceProvider(logger, m, cfg, vmCfg, prestateProvider, asteriscPrestate, localInputs, subdir, depth) ++ provider := asterisc.NewTraceProvider(logger, m.VmMetrics(cfg.VmType.String()), cfg, vmCfg, prestateProvider, asteriscPrestate, localInputs, subdir, depth) + return provider, nil + } +
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+1
+
-1
+ +
+ +
+
+
diff --git OP/op-challenger/game/fault/trace/outputs/output_cannon.go CELO/op-challenger/game/fault/trace/outputs/output_cannon.go +index 1f9c4285a3542ddc881a6c12dde1a2bb9eec018b..49b6631b5a7f0c89eb7f983104309894ed6caf96 100644 +--- OP/op-challenger/game/fault/trace/outputs/output_cannon.go ++++ CELO/op-challenger/game/fault/trace/outputs/output_cannon.go +@@ -41,7 +41,7 @@ localInputs, err := utils.FetchLocalInputsFromProposals(ctx, l1Head.Hash, l2Client, agreed, claimed) + if err != nil { + return nil, fmt.Errorf("failed to fetch cannon local inputs: %w", err) + } +- provider := cannon.NewTraceProvider(logger, m, cfg, serverExecutor, prestateProvider, cannonPrestate, localInputs, subdir, depth) ++ provider := cannon.NewTraceProvider(logger, m.VmMetrics(cfg.VmType.String()), cfg, serverExecutor, prestateProvider, cannonPrestate, localInputs, subdir, depth) + return provider, nil + } +
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+47
+
-15
+ +
+ +
+
+
diff --git OP/op-challenger/game/fault/trace/prestates/multi.go CELO/op-challenger/game/fault/trace/prestates/multi.go +index ccc22c6d5d4a34f717d4d136dc01488342e975a2..03abbbc564866431d1d39c4e7acffdf2f401b9ee 100644 +--- OP/op-challenger/game/fault/trace/prestates/multi.go ++++ CELO/op-challenger/game/fault/trace/prestates/multi.go +@@ -9,43 +9,64 @@ "net/url" + "os" + "path/filepath" +  ++ "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/vm" + "github.com/ethereum-optimism/optimism/op-service/ioutil" + "github.com/ethereum/go-ethereum/common" + ) +  + var ( + ErrPrestateUnavailable = errors.New("prestate unavailable") ++ ++ // supportedFileTypes lists, in preferred order, the prestate file types to attempt to download ++ supportedFileTypes = []string{".bin.gz", ".json.gz", ".json"} + ) +  + type MultiPrestateProvider struct { +- baseUrl *url.URL +- dataDir string ++ baseUrl *url.URL ++ dataDir string ++ stateConverter vm.StateConverter + } +  +-func NewMultiPrestateProvider(baseUrl *url.URL, dataDir string) *MultiPrestateProvider { ++func NewMultiPrestateProvider(baseUrl *url.URL, dataDir string, stateConverter vm.StateConverter) *MultiPrestateProvider { + return &MultiPrestateProvider{ +- baseUrl: baseUrl, +- dataDir: dataDir, ++ baseUrl: baseUrl, ++ dataDir: dataDir, ++ stateConverter: stateConverter, + } + } +  + func (m *MultiPrestateProvider) PrestatePath(hash common.Hash) (string, error) { +- path := filepath.Join(m.dataDir, hash.Hex()+".json.gz") +- if _, err := os.Stat(path); errors.Is(err, os.ErrNotExist) { +- if err := m.fetchPrestate(hash, path); err != nil { +- return "", fmt.Errorf("failed to fetch prestate: %w", err) ++ // First try to find a previously downloaded prestate ++ for _, fileType := range supportedFileTypes { ++ path := filepath.Join(m.dataDir, hash.Hex()+fileType) ++ if _, err := os.Stat(path); errors.Is(err, os.ErrNotExist) { ++ continue // File doesn't exist, try the next file type ++ } else if err != nil { ++ return "", fmt.Errorf("error checking for existing prestate %v in file %v: %w", hash, path, err) + } +- } else if err != nil { +- return "", fmt.Errorf("error checking for existing prestate %v: %w", hash, err) ++ return path, nil // Found an existing file so use it + } +- return path, nil ++ ++ // Didn't find any available files, try to download one ++ var combinedErr error // Keep a track of each download attempt so we can report them if none work ++ for _, fileType := range supportedFileTypes { ++ path := filepath.Join(m.dataDir, hash.Hex()+fileType) ++ if err := m.fetchPrestate(hash, fileType, path); errors.Is(err, ErrPrestateUnavailable) { ++ combinedErr = errors.Join(combinedErr, err) ++ continue // Didn't find prestate in this format, try the next ++ } else if err != nil { ++ return "", fmt.Errorf("error downloading prestate %v to file %v: %w", hash, path, err) ++ } ++ return path, nil // Successfully downloaded a prestate so use it ++ } ++ return "", errors.Join(ErrPrestateUnavailable, combinedErr) + } +  +-func (m *MultiPrestateProvider) fetchPrestate(hash common.Hash, dest string) error { ++func (m *MultiPrestateProvider) fetchPrestate(hash common.Hash, fileType string, dest string) error { + if err := os.MkdirAll(m.dataDir, 0755); err != nil { + return fmt.Errorf("error creating prestate dir: %w", err) + } +- prestateUrl := m.baseUrl.JoinPath(hash.Hex() + ".json") ++ prestateUrl := m.baseUrl.JoinPath(hash.Hex() + fileType) + resp, err := http.Get(prestateUrl.String()) + if err != nil { + return fmt.Errorf("failed to fetch prestate from %v: %w", prestateUrl, err) +@@ -54,7 +75,8 @@ defer resp.Body.Close() + if resp.StatusCode != http.StatusOK { + return fmt.Errorf("%w from url %v: status %v", ErrPrestateUnavailable, prestateUrl, resp.StatusCode) + } +- out, err := ioutil.NewAtomicWriterCompressed(dest, 0o644) ++ tmpFile := dest + ".tmp" + fileType // Preserve the file type extension so state decoding is applied correctly ++ out, err := ioutil.NewAtomicWriter(tmpFile, 0o644) + if err != nil { + return fmt.Errorf("failed to open atomic writer for %v: %w", dest, err) + } +@@ -67,6 +89,16 @@ return fmt.Errorf("failed to write file %v: %w", dest, err) + } + if err := out.Close(); err != nil { + return fmt.Errorf("failed to close file %v: %w", dest, err) ++ } ++ // Verify the prestate actually matches the expected hash before moving it into the final destination ++ proof, _, _, err := m.stateConverter.ConvertStateToProof(tmpFile) ++ if err != nil || proof.ClaimValue != hash { ++ // Treat invalid prestates as unavailable. Often servers return a 404 page with 200 status code ++ _ = os.Remove(tmpFile) // Best effort attempt to clean up the temporary file ++ return fmt.Errorf("invalid prestate from url: %v, ignoring: %w", prestateUrl, errors.Join(ErrPrestateUnavailable, err)) ++ } ++ if err := os.Rename(tmpFile, dest); err != nil { ++ return fmt.Errorf("failed to move temp file to final destination: %w", err) + } + return nil + }
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+131
+
-33
+ +
+ +
+
+
diff --git OP/op-challenger/game/fault/trace/prestates/multi_test.go CELO/op-challenger/game/fault/trace/prestates/multi_test.go +index 2f825d98da4e0b2103dc78c698477fdb4ad67444..7b09b81bdc676e6e1a86fd29cd61148d8d423b07 100644 +--- OP/op-challenger/game/fault/trace/prestates/multi_test.go ++++ CELO/op-challenger/game/fault/trace/prestates/multi_test.go +@@ -1,60 +1,67 @@ + package prestates +  + import ( ++ "errors" + "io" + "net/http" + "net/http/httptest" + "net/url" + "os" + "path/filepath" ++ "strings" + "testing" +  ++ "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/utils" + "github.com/ethereum-optimism/optimism/op-service/ioutil" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" + ) +  + func TestDownloadPrestate(t *testing.T) { +- dir := t.TempDir() +- server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { +- _, _ = w.Write([]byte(r.URL.Path)) +- })) +- defer server.Close() +- provider := NewMultiPrestateProvider(parseURL(t, server.URL), dir) +- hash := common.Hash{0xaa} +- path, err := provider.PrestatePath(hash) +- require.NoError(t, err) +- in, err := ioutil.OpenDecompressed(path) +- require.NoError(t, err) +- defer in.Close() +- content, err := io.ReadAll(in) +- require.NoError(t, err) +- require.Equal(t, "/"+hash.Hex()+".json", string(content)) ++ for _, ext := range supportedFileTypes { ++ t.Run(ext, func(t *testing.T) { ++ dir := t.TempDir() ++ server := prestateHTTPServer(ext) ++ defer server.Close() ++ hash := common.Hash{0xaa} ++ provider := NewMultiPrestateProvider(parseURL(t, server.URL), dir, &stubStateConverter{hash: hash}) ++ path, err := provider.PrestatePath(hash) ++ require.NoError(t, err) ++ in, err := os.Open(path) ++ require.NoError(t, err) ++ defer in.Close() ++ content, err := io.ReadAll(in) ++ require.NoError(t, err) ++ require.Equal(t, "/"+hash.Hex()+ext, string(content)) ++ }) ++ } + } +  + func TestCreateDirectory(t *testing.T) { +- dir := t.TempDir() +- dir = filepath.Join(dir, "test") +- server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { +- _, _ = w.Write([]byte(r.URL.Path)) +- })) +- defer server.Close() +- provider := NewMultiPrestateProvider(parseURL(t, server.URL), dir) +- hash := common.Hash{0xaa} +- path, err := provider.PrestatePath(hash) +- require.NoError(t, err) +- in, err := ioutil.OpenDecompressed(path) +- require.NoError(t, err) +- defer in.Close() +- content, err := io.ReadAll(in) +- require.NoError(t, err) +- require.Equal(t, "/"+hash.Hex()+".json", string(content)) ++ for _, ext := range supportedFileTypes { ++ t.Run(ext, func(t *testing.T) { ++ dir := t.TempDir() ++ dir = filepath.Join(dir, "test") ++ server := prestateHTTPServer(ext) ++ defer server.Close() ++ hash := common.Hash{0xaa} ++ provider := NewMultiPrestateProvider(parseURL(t, server.URL), dir, &stubStateConverter{hash: hash}) ++ path, err := provider.PrestatePath(hash) ++ require.NoError(t, err) ++ in, err := os.Open(path) ++ require.NoError(t, err) ++ defer in.Close() ++ content, err := io.ReadAll(in) ++ require.NoError(t, err) ++ require.Equal(t, "/"+hash.Hex()+ext, string(content)) ++ }) ++ } + } +  + func TestExistingPrestate(t *testing.T) { + dir := t.TempDir() +- provider := NewMultiPrestateProvider(parseURL(t, "http://127.0.0.1:1"), dir) + hash := common.Hash{0xaa} ++ provider := NewMultiPrestateProvider(parseURL(t, "http://127.0.0.1:1"), dir, &stubStateConverter{hash: hash}) + expectedFile := filepath.Join(dir, hash.Hex()+".json.gz") + err := ioutil.WriteCompressedBytes(expectedFile, []byte("expected content"), os.O_WRONLY|os.O_CREATE, 0o644) + require.NoError(t, err) +@@ -72,16 +79,84 @@ } +  + func TestMissingPrestate(t *testing.T) { + dir := t.TempDir() ++ var requests []string + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ++ requests = append(requests, r.URL.Path) + w.WriteHeader(404) + })) + defer server.Close() +- provider := NewMultiPrestateProvider(parseURL(t, server.URL), dir) + hash := common.Hash{0xaa} ++ provider := NewMultiPrestateProvider(parseURL(t, server.URL), dir, &stubStateConverter{hash: hash}) + path, err := provider.PrestatePath(hash) + require.ErrorIs(t, err, ErrPrestateUnavailable) + _, err = os.Stat(path) + require.ErrorIs(t, err, os.ErrNotExist) ++ expectedRequests := []string{ ++ "/" + hash.Hex() + ".bin.gz", ++ "/" + hash.Hex() + ".json.gz", ++ "/" + hash.Hex() + ".json", ++ } ++ require.Equal(t, expectedRequests, requests) ++} ++ ++func TestStorePrestateWithCorrectExtension(t *testing.T) { ++ extensions := []string{".bin.gz", ".json.gz", ".json"} ++ for _, ext := range extensions { ++ ext := ext ++ t.Run(ext, func(t *testing.T) { ++ dir := t.TempDir() ++ server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ++ if !strings.HasSuffix(r.URL.Path, ext) { ++ w.WriteHeader(404) ++ return ++ } ++ _, _ = w.Write([]byte("content")) ++ })) ++ defer server.Close() ++ hash := common.Hash{0xaa} ++ provider := NewMultiPrestateProvider(parseURL(t, server.URL), dir, &stubStateConverter{hash: hash}) ++ path, err := provider.PrestatePath(hash) ++ require.NoError(t, err) ++ require.Truef(t, strings.HasSuffix(path, ext), "Expected path %v to have extension %v", path, ext) ++ in, err := os.Open(path) ++ require.NoError(t, err) ++ defer in.Close() ++ content, err := io.ReadAll(in) ++ require.NoError(t, err) ++ require.Equal(t, "content", string(content)) ++ }) ++ } ++} ++ ++func TestDetectInvalidPrestate(t *testing.T) { ++ dir := t.TempDir() ++ server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ++ _, _ = w.Write([]byte("content")) ++ })) ++ defer server.Close() ++ hash := common.Hash{0xaa} ++ provider := NewMultiPrestateProvider(parseURL(t, server.URL), dir, &stubStateConverter{hash: hash, err: errors.New("boom")}) ++ _, err := provider.PrestatePath(hash) ++ require.ErrorIs(t, err, ErrPrestateUnavailable) ++ entries, err := os.ReadDir(dir) ++ require.NoError(t, err) ++ require.Empty(t, entries, "should not leave any files in temp dir") ++} ++ ++func TestDetectPrestateWithWrongHash(t *testing.T) { ++ dir := t.TempDir() ++ server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ++ _, _ = w.Write([]byte("content")) ++ })) ++ defer server.Close() ++ hash := common.Hash{0xaa} ++ actualHash := common.Hash{0xbb} ++ provider := NewMultiPrestateProvider(parseURL(t, server.URL), dir, &stubStateConverter{hash: actualHash}) ++ _, err := provider.PrestatePath(hash) ++ require.ErrorIs(t, err, ErrPrestateUnavailable) ++ entries, err := os.ReadDir(dir) ++ require.NoError(t, err) ++ require.Empty(t, entries, "should not leave any files in temp dir") + } +  + func parseURL(t *testing.T, str string) *url.URL { +@@ -89,3 +164,26 @@ parsed, err := url.Parse(str) + require.NoError(t, err) + return parsed + } ++ ++func prestateHTTPServer(ext string) *httptest.Server { ++ return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ++ if strings.HasSuffix(r.URL.Path, ext) { ++ _, _ = w.Write([]byte(r.URL.Path)) ++ } else { ++ w.WriteHeader(http.StatusNotFound) ++ } ++ })) ++} ++ ++type stubStateConverter struct { ++ err error ++ hash common.Hash ++} ++ ++func (s *stubStateConverter) ConvertStateToProof(path string) (*utils.ProofData, uint64, bool, error) { ++ // Return an error if we're given the wrong path ++ if _, err := os.Stat(path); err != nil { ++ return nil, 0, false, err ++ } ++ return &utils.ProofData{ClaimValue: s.hash}, 0, false, s.err ++}
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+7
+
-3
+ +
+ +
+
+
diff --git OP/op-challenger/game/fault/trace/prestates/source.go CELO/op-challenger/game/fault/trace/prestates/source.go +index c59763560b114832e558d5f6fd8f05f152a45179..a4c9839ad1e5da4ad0fef54120c252310d84122f 100644 +--- OP/op-challenger/game/fault/trace/prestates/source.go ++++ CELO/op-challenger/game/fault/trace/prestates/source.go +@@ -1,10 +1,14 @@ + package prestates +  +-import "net/url" ++import ( ++ "net/url" +  +-func NewPrestateSource(baseURL *url.URL, path string, localDir string) PrestateSource { ++ "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/vm" ++) ++ ++func NewPrestateSource(baseURL *url.URL, path string, localDir string, stateConverter vm.StateConverter) PrestateSource { + if baseURL != nil { +- return NewMultiPrestateProvider(baseURL, localDir) ++ return NewMultiPrestateProvider(baseURL, localDir, stateConverter) + } else { + return NewSinglePrestateSource(path) + }
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+9
+
-4
+ +
+ +
+
+
diff --git OP/op-challenger/game/fault/trace/utils/preimage.go CELO/op-challenger/game/fault/trace/utils/preimage.go +index 0c14882fa7740341fffce2c41dcbd86aa92a36e3..5b61a70adb9f7d69855c9d52780a2e8d3498b265 100644 +--- OP/op-challenger/game/fault/trace/utils/preimage.go ++++ CELO/op-challenger/game/fault/trace/utils/preimage.go +@@ -23,7 +23,6 @@ lengthPrefixSize = 8 + ) +  + var ( +- ErrInvalidScalarValue = errors.New("invalid scalar value") + ErrInvalidBlobKeyPreimage = errors.New("invalid blob key preimage") + ) +  +@@ -32,7 +31,7 @@ Get(key common.Hash) ([]byte, error) + Close() error + } +  +-type PreimageSourceCreator func() PreimageSource ++type PreimageSourceCreator func() (PreimageSource, error) +  + type PreimageLoader struct { + makeSource PreimageSourceCreator +@@ -62,7 +61,10 @@ func (l *PreimageLoader) loadBlobPreimage(proof *ProofData) (*types.PreimageOracleData, error) { + // The key for a blob field element is a keccak hash of commitment++fieldElementIndex. + // First retrieve the preimage of the key as a keccak hash so we have the commitment and required field element + inputsKey := preimage.Keccak256Key(proof.OracleKey).PreimageKey() +- source := l.makeSource() ++ source, err := l.makeSource() ++ if err != nil { ++ return nil, fmt.Errorf("failed to open preimage store: %w", err) ++ } + defer source.Close() + inputs, err := source.Get(inputsKey) + if err != nil { +@@ -112,7 +114,10 @@ } +  + func (l *PreimageLoader) loadPrecompilePreimage(proof *ProofData) (*types.PreimageOracleData, error) { + inputKey := preimage.Keccak256Key(proof.OracleKey).PreimageKey() +- source := l.makeSource() ++ source, err := l.makeSource() ++ if err != nil { ++ return nil, fmt.Errorf("failed to open preimage store: %w", err) ++ } + defer source.Close() + input, err := source.Get(inputKey) + if err != nil {
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+18
+
-18
+ +
+ +
+
+
diff --git OP/op-challenger/game/fault/trace/utils/preimage_test.go CELO/op-challenger/game/fault/trace/utils/preimage_test.go +index cc4b8fa0d14be07bee8a0852122b2ecec60c865c..2b5552f28e0cb52eca8e008c5a57f826d018b243 100644 +--- OP/op-challenger/game/fault/trace/utils/preimage_test.go ++++ CELO/op-challenger/game/fault/trace/utils/preimage_test.go +@@ -21,8 +21,8 @@ ) +  + func TestPreimageLoader_NoPreimage(t *testing.T) { + kv := kvstore.NewMemKV() +- loader := NewPreimageLoader(func() PreimageSource { +- return kv ++ loader := NewPreimageLoader(func() (PreimageSource, error) { ++ return kv, nil + }) + actual, err := loader.LoadPreimage(&ProofData{}) + require.NoError(t, err) +@@ -31,8 +31,8 @@ } +  + func TestPreimageLoader_LocalPreimage(t *testing.T) { + kv := kvstore.NewMemKV() +- loader := NewPreimageLoader(func() PreimageSource { +- return kv ++ loader := NewPreimageLoader(func() (PreimageSource, error) { ++ return kv, nil + }) + proof := &ProofData{ + OracleKey: common.Hash{byte(preimage.LocalKeyType), 0xaa, 0xbb}.Bytes(), +@@ -55,8 +55,8 @@ for _, keyType := range tests { + keyType := keyType + t.Run(fmt.Sprintf("type-%v", keyType), func(t *testing.T) { + kv := kvstore.NewMemKV() +- loader := NewPreimageLoader(func() PreimageSource { +- return kv ++ loader := NewPreimageLoader(func() (PreimageSource, error) { ++ return kv, nil + }) + proof := &ProofData{ + OracleKey: common.Hash{byte(keyType), 0xaa, 0xbb}.Bytes(), +@@ -99,8 +99,8 @@ } +  + t.Run("NoKeyPreimage", func(t *testing.T) { + kv := kvstore.NewMemKV() +- loader := NewPreimageLoader(func() PreimageSource { +- return kv ++ loader := NewPreimageLoader(func() (PreimageSource, error) { ++ return kv, nil + }) + proof := &ProofData{ + OracleKey: common.Hash{byte(preimage.BlobKeyType), 0xaf}.Bytes(), +@@ -113,8 +113,8 @@ }) +  + t.Run("InvalidKeyPreimage", func(t *testing.T) { + kv := kvstore.NewMemKV() +- loader := NewPreimageLoader(func() PreimageSource { +- return kv ++ loader := NewPreimageLoader(func() (PreimageSource, error) { ++ return kv, nil + }) + proof := &ProofData{ + OracleKey: common.Hash{byte(preimage.BlobKeyType), 0xad}.Bytes(), +@@ -128,8 +128,8 @@ }) +  + t.Run("MissingBlobs", func(t *testing.T) { + kv := kvstore.NewMemKV() +- loader := NewPreimageLoader(func() PreimageSource { +- return kv ++ loader := NewPreimageLoader(func() (PreimageSource, error) { ++ return kv, nil + }) + proof := &ProofData{ + OracleKey: common.Hash{byte(preimage.BlobKeyType), 0xae}.Bytes(), +@@ -143,8 +143,8 @@ }) +  + t.Run("Valid", func(t *testing.T) { + kv := kvstore.NewMemKV() +- loader := NewPreimageLoader(func() PreimageSource { +- return kv ++ loader := NewPreimageLoader(func() (PreimageSource, error) { ++ return kv, nil + }) + storeBlob(t, kv, gokzg4844.KZGCommitment(commitment), gokzg4844.Blob(blob)) + actual, err := loader.LoadPreimage(proof) +@@ -178,16 +178,16 @@ } +  + t.Run("NoInputPreimage", func(t *testing.T) { + kv := kvstore.NewMemKV() +- loader := NewPreimageLoader(func() PreimageSource { +- return kv ++ loader := NewPreimageLoader(func() (PreimageSource, error) { ++ return kv, nil + }) + _, err := loader.LoadPreimage(proof) + require.ErrorIs(t, err, kvstore.ErrNotFound) + }) + t.Run("Valid", func(t *testing.T) { + kv := kvstore.NewMemKV() +- loader := NewPreimageLoader(func() PreimageSource { +- return kv ++ loader := NewPreimageLoader(func() (PreimageSource, error) { ++ return kv, nil + }) + require.NoError(t, kv.Put(preimage.Keccak256Key(proof.OracleKey).PreimageKey(), input)) + actual, err := loader.LoadPreimage(proof)
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+17
+
-12
+ +
+ +
+
+
diff --git OP/op-challenger/game/fault/trace/vm/executor.go CELO/op-challenger/game/fault/trace/vm/executor.go +index 65c18d67d221e75cff52e3aa16b127284458ebd5..9e2cd0d29e93e53d5e28160b643b4439aec181a5 100644 +--- OP/op-challenger/game/fault/trace/vm/executor.go ++++ CELO/op-challenger/game/fault/trace/vm/executor.go +@@ -22,17 +22,18 @@ debugFilename = "debug-info.json" + ) +  + type Metricer interface { +- RecordVmExecutionTime(vmType string, t time.Duration) +- RecordVmMemoryUsed(vmType string, memoryUsed uint64) ++ RecordExecutionTime(t time.Duration) ++ RecordMemoryUsed(memoryUsed uint64) + } +  + type Config struct { + // VM Configuration +- VmType types.TraceType +- VmBin string // Path to the vm executable to run when generating trace data +- SnapshotFreq uint // Frequency of snapshots to create when executing (in VM instructions) +- InfoFreq uint // Frequency of progress log messages (in VM instructions) +- DebugInfo bool ++ VmType types.TraceType ++ VmBin string // Path to the vm executable to run when generating trace data ++ SnapshotFreq uint // Frequency of snapshots to create when executing (in VM instructions) ++ InfoFreq uint // Frequency of progress log messages (in VM instructions) ++ DebugInfo bool // Whether to record debug info from the execution ++ BinarySnapshots bool // Whether to use binary snapshots instead of JSON +  + // Host Configuration + L1 string +@@ -82,13 +83,13 @@ // DoGenerateProof executes vm from the specified starting trace index until the end trace index. + // The proof is stored at the specified directory. + func (e *Executor) DoGenerateProof(ctx context.Context, dir string, begin uint64, end uint64, extraVmArgs ...string) error { + snapshotDir := filepath.Join(dir, SnapsDir) +- start, err := e.selectSnapshot(e.logger, snapshotDir, e.absolutePreState, begin) ++ start, err := e.selectSnapshot(e.logger, snapshotDir, e.absolutePreState, begin, e.cfg.BinarySnapshots) + if err != nil { + return fmt.Errorf("find starting snapshot: %w", err) + } + proofDir := filepath.Join(dir, utils.ProofsDir) + dataDir := PreimageDir(dir) +- lastGeneratedState := filepath.Join(dir, FinalState) ++ lastGeneratedState := FinalStatePath(dir, e.cfg.BinarySnapshots) + args := []string{ + "run", + "--input", start, +@@ -98,7 +99,11 @@ "--info-at", "%" + strconv.FormatUint(uint64(e.cfg.InfoFreq), 10), + "--proof-at", "=" + strconv.FormatUint(end, 10), + "--proof-fmt", filepath.Join(proofDir, "%d.json.gz"), + "--snapshot-at", "%" + strconv.FormatUint(uint64(e.cfg.SnapshotFreq), 10), +- "--snapshot-fmt", filepath.Join(snapshotDir, "%d.json.gz"), ++ } ++ if e.cfg.BinarySnapshots { ++ args = append(args, "--snapshot-fmt", filepath.Join(snapshotDir, "%d.bin.gz")) ++ } else { ++ args = append(args, "--snapshot-fmt", filepath.Join(snapshotDir, "%d.json.gz")) + } + if end < math.MaxUint64 { + args = append(args, "--stop-at", "="+strconv.FormatUint(end+1, 10)) +@@ -128,12 +133,12 @@ execStart := time.Now() + err = e.cmdExecutor(ctx, e.logger.New("proof", end), e.cfg.VmBin, args...) + execTime := time.Since(execStart) + memoryUsed := "unknown" +- e.metrics.RecordVmExecutionTime(e.cfg.VmType.String(), execTime) ++ e.metrics.RecordExecutionTime(execTime) + if e.cfg.DebugInfo && err == nil { + if info, err := jsonutil.LoadJSON[debugInfo](filepath.Join(dataDir, debugFilename)); err != nil { + e.logger.Warn("Failed to load debug metrics", "err", err) + } else { +- e.metrics.RecordVmMemoryUsed(e.cfg.VmType.String(), uint64(info.MemoryUsed)) ++ e.metrics.RecordMemoryUsed(uint64(info.MemoryUsed)) + memoryUsed = fmt.Sprintf("%d", uint64(info.MemoryUsed)) + } + }
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+20
+
-5
+ +
+ +
+
+
diff --git OP/op-challenger/game/fault/trace/vm/executor_test.go CELO/op-challenger/game/fault/trace/vm/executor_test.go +index 695f9bf9fceb9f369340d415cf6069e3255cda18..ff4a8ba7e1ab272ccbb4cea94b7d51f3946d9e72 100644 +--- OP/op-challenger/game/fault/trace/vm/executor_test.go ++++ CELO/op-challenger/game/fault/trace/vm/executor_test.go +@@ -9,7 +9,6 @@ "testing" + "time" +  + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/utils" +- "github.com/ethereum-optimism/optimism/op-challenger/metrics" + "github.com/ethereum-optimism/optimism/op-service/testlog" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/log" +@@ -43,7 +42,7 @@ } + captureExec := func(t *testing.T, cfg Config, proofAt uint64) (string, string, map[string]string) { + m := &stubVmMetrics{} + executor := NewExecutor(testlog.Logger(t, log.LevelInfo), m, cfg, NewOpProgramServerExecutor(), prestate, inputs) +- executor.selectSnapshot = func(logger log.Logger, dir string, absolutePreState string, i uint64) (string, error) { ++ executor.selectSnapshot = func(logger log.Logger, dir string, absolutePreState string, i uint64, binary bool) (string, error) { + return input, nil + } + var binary string +@@ -82,7 +81,7 @@ require.Equal(t, "run", subcommand) + require.Equal(t, input, args["--input"]) + require.Contains(t, args, "--meta") + require.Equal(t, "", args["--meta"]) +- require.Equal(t, filepath.Join(dir, FinalState), args["--output"]) ++ require.Equal(t, FinalStatePath(dir, cfg.BinarySnapshots), args["--output"]) + require.Equal(t, "=150000000", args["--proof-at"]) + require.Equal(t, "=150000001", args["--stop-at"]) + require.Equal(t, "%500", args["--snapshot-at"]) +@@ -128,13 +127,29 @@ // stop-at would need to be one more than the proof step which would overflow back to 0 + // so expect that it will be omitted. We'll ultimately want asterisc to execute until the program exits. + require.NotContains(t, args, "--stop-at") + }) ++ ++ t.Run("BinarySnapshots", func(t *testing.T) { ++ cfg.Network = "mainnet" ++ cfg.BinarySnapshots = true ++ _, _, args := captureExec(t, cfg, 100) ++ require.Equal(t, filepath.Join(dir, SnapsDir, "%d.bin.gz"), args["--snapshot-fmt"]) ++ }) ++ ++ t.Run("JsonSnapshots", func(t *testing.T) { ++ cfg.Network = "mainnet" ++ cfg.BinarySnapshots = false ++ _, _, args := captureExec(t, cfg, 100) ++ require.Equal(t, filepath.Join(dir, SnapsDir, "%d.json.gz"), args["--snapshot-fmt"]) ++ }) + } +  + type stubVmMetrics struct { +- metrics.NoopMetricsImpl + executionTimeRecordCount int + } +  +-func (c *stubVmMetrics) RecordVmExecutionTime(_ string, _ time.Duration) { ++func (c *stubVmMetrics) RecordExecutionTime(_ time.Duration) { + c.executionTimeRecordCount++ + } ++ ++func (c *stubVmMetrics) RecordMemoryUsed(_ uint64) { ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+9
+
-0
+ +
+ +
+
+
diff --git OP/op-challenger/game/fault/trace/vm/iface.go CELO/op-challenger/game/fault/trace/vm/iface.go +new file mode 100644 +index 0000000000000000000000000000000000000000..188f19e0c8e27cd5232d3cb967838979dd1eca81 +--- /dev/null ++++ CELO/op-challenger/game/fault/trace/vm/iface.go +@@ -0,0 +1,9 @@ ++package vm ++ ++import "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/utils" ++ ++type StateConverter interface { ++ // ConvertStateToProof reads the state snapshot at the specified path and converts it to ProofData. ++ // Returns the proof data, the VM step the state is from and whether or not the VM had exited. ++ ConvertStateToProof(statePath string) (*utils.ProofData, uint64, bool, error) ++}
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+34
+
-14
+ +
+ +
+
+
diff --git OP/op-challenger/game/fault/trace/vm/kona_server_executor.go CELO/op-challenger/game/fault/trace/vm/kona_server_executor.go +index ac5b0fbb0fe07809f34cf1df8dea139f5309038c..a8be1c7bc5620ec5e1262f699b1a7731377acdd5 100644 +--- OP/op-challenger/game/fault/trace/vm/kona_server_executor.go ++++ CELO/op-challenger/game/fault/trace/vm/kona_server_executor.go +@@ -8,32 +8,52 @@ "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/utils" + "github.com/ethereum-optimism/optimism/op-node/chaincfg" + ) +  +-type KonaServerExecutor struct { ++type KonaExecutor struct { ++ nativeMode bool ++ clientBinPath string + } +  +-var _ OracleServerExecutor = (*KonaServerExecutor)(nil) ++var _ OracleServerExecutor = (*KonaExecutor)(nil) +  +-func NewKonaServerExecutor() *KonaServerExecutor { +- return &KonaServerExecutor{} ++func NewKonaExecutor() *KonaExecutor { ++ return &KonaExecutor{nativeMode: false} + } +  +-func (s *KonaServerExecutor) OracleCommand(cfg Config, dataDir string, inputs utils.LocalGameInputs) ([]string, error) { +- if cfg.Network == "" { +- return nil, errors.New("network is not defined") +- } ++func NewNativeKonaExecutor(clientBinPath string) *KonaExecutor { ++ return &KonaExecutor{nativeMode: true, clientBinPath: clientBinPath} ++} +  +- chainCfg := chaincfg.ChainByName(cfg.Network) +- return []string{ +- cfg.Server, "--server", ++func (s *KonaExecutor) OracleCommand(cfg Config, dataDir string, inputs utils.LocalGameInputs) ([]string, error) { ++ args := []string{ ++ cfg.Server, + "--l1-node-address", cfg.L1, + "--l1-beacon-address", cfg.L1Beacon, + "--l2-node-address", cfg.L2, +- "--data-dir", dataDir, +- "--l2-chain-id", strconv.FormatUint(chainCfg.ChainID, 10), + "--l1-head", inputs.L1Head.Hex(), + "--l2-head", inputs.L2Head.Hex(), + "--l2-output-root", inputs.L2OutputRoot.Hex(), + "--l2-claim", inputs.L2Claim.Hex(), + "--l2-block-number", inputs.L2BlockNumber.Text(10), +- }, nil ++ "-v", ++ } ++ ++ if s.nativeMode { ++ args = append(args, "--exec", s.clientBinPath) ++ } else { ++ args = append(args, "--server") ++ args = append(args, "--data-dir", dataDir) ++ } ++ ++ if cfg.RollupConfigPath != "" { ++ args = append(args, "--rollup-config-path", cfg.RollupConfigPath) ++ } else { ++ if cfg.Network == "" { ++ return nil, errors.New("network is not defined") ++ } ++ ++ chainCfg := chaincfg.ChainByName(cfg.Network) ++ args = append(args, "--l2-chain-id", strconv.FormatUint(chainCfg.ChainID, 10)) ++ } ++ ++ return args, nil + }
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+1
+
-1
+ +
+ +
+
+
diff --git OP/op-challenger/game/fault/trace/vm/kona_server_executor_test.go CELO/op-challenger/game/fault/trace/vm/kona_server_executor_test.go +index 45fb5faa904082f8e3f3f6788dc086be228d493f..ba690b5c088183aabae6c382a2d62ad19c7b452f 100644 +--- OP/op-challenger/game/fault/trace/vm/kona_server_executor_test.go ++++ CELO/op-challenger/game/fault/trace/vm/kona_server_executor_test.go +@@ -26,7 +26,7 @@ L2OutputRoot: common.Hash{0x33}, + L2Claim: common.Hash{0x44}, + L2BlockNumber: big.NewInt(3333), + } +- vmConfig := NewKonaServerExecutor() ++ vmConfig := NewKonaExecutor() +  + args, err := vmConfig.OracleCommand(cfg, dir, inputs) + require.NoError(t, err)
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+42
+
-0
+ +
+ +
+
+
diff --git OP/op-challenger/game/fault/trace/vm/prestate.go CELO/op-challenger/game/fault/trace/vm/prestate.go +new file mode 100644 +index 0000000000000000000000000000000000000000..bbb4a9437d9aaf3a8196af797bf6500eef9aeb56 +--- /dev/null ++++ CELO/op-challenger/game/fault/trace/vm/prestate.go +@@ -0,0 +1,42 @@ ++package vm ++ ++import ( ++ "context" ++ "fmt" ++ ++ "github.com/ethereum/go-ethereum/common" ++ ++ "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" ++) ++ ++var _ types.PrestateProvider = (*PrestateProvider)(nil) ++ ++type PrestateProvider struct { ++ prestate string ++ stateConverter StateConverter ++ ++ prestateCommitment common.Hash ++} ++ ++func NewPrestateProvider(prestate string, converter StateConverter) *PrestateProvider { ++ return &PrestateProvider{ ++ prestate: prestate, ++ stateConverter: converter, ++ } ++} ++ ++func (p *PrestateProvider) AbsolutePreStateCommitment(_ context.Context) (common.Hash, error) { ++ if p.prestateCommitment != (common.Hash{}) { ++ return p.prestateCommitment, nil ++ } ++ proof, _, _, err := p.stateConverter.ConvertStateToProof(p.prestate) ++ if err != nil { ++ return common.Hash{}, fmt.Errorf("cannot load absolute pre-state: %w", err) ++ } ++ p.prestateCommitment = proof.ClaimValue ++ return proof.ClaimValue, nil ++} ++ ++func (p *PrestateProvider) PrestatePath() string { ++ return p.prestate ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+63
+
-0
+ +
+ +
+
+
diff --git OP/op-challenger/game/fault/trace/vm/prestate_test.go CELO/op-challenger/game/fault/trace/vm/prestate_test.go +new file mode 100644 +index 0000000000000000000000000000000000000000..69498e323c59d08313289dca78027e7b05a7382d +--- /dev/null ++++ CELO/op-challenger/game/fault/trace/vm/prestate_test.go +@@ -0,0 +1,63 @@ ++package vm ++ ++import ( ++ "context" ++ "errors" ++ "path/filepath" ++ "testing" ++ ++ "github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/utils" ++ "github.com/ethereum/go-ethereum/common" ++ "github.com/stretchr/testify/require" ++) ++ ++type stubConverter struct { ++ err error ++ hash common.Hash ++} ++ ++func (s *stubConverter) ConvertStateToProof(statePath string) (*utils.ProofData, uint64, bool, error) { ++ if s.err != nil { ++ return nil, 0, false, s.err ++ } ++ return &utils.ProofData{ ++ ClaimValue: s.hash, ++ }, 0, false, nil ++} ++ ++func newPrestateProvider(prestate common.Hash) *PrestateProvider { ++ return NewPrestateProvider("state.json", &stubConverter{hash: prestate}) ++} ++ ++func TestAbsolutePreStateCommitment(t *testing.T) { ++ prestate := common.Hash{0xaa, 0xbb} ++ ++ t.Run("StateUnavailable", func(t *testing.T) { ++ expectedErr := errors.New("kaboom") ++ provider := NewPrestateProvider("foo", &stubConverter{err: expectedErr}) ++ _, err := provider.AbsolutePreStateCommitment(context.Background()) ++ require.ErrorIs(t, err, expectedErr) ++ }) ++ ++ t.Run("ExpectedAbsolutePreState", func(t *testing.T) { ++ provider := newPrestateProvider(prestate) ++ actual, err := provider.AbsolutePreStateCommitment(context.Background()) ++ require.NoError(t, err) ++ require.Equal(t, prestate, actual) ++ }) ++ ++ t.Run("CacheAbsolutePreState", func(t *testing.T) { ++ converter := &stubConverter{hash: prestate} ++ provider := NewPrestateProvider(filepath.Join("state.json"), converter) ++ first, err := provider.AbsolutePreStateCommitment(context.Background()) ++ require.NoError(t, err) ++ ++ // Remove the prestate from disk ++ converter.err = errors.New("no soup for you") ++ ++ // Value should still be available from cache ++ cached, err := provider.AbsolutePreStateCommitment(context.Background()) ++ require.NoError(t, err) ++ require.Equal(t, first, cached) ++ }) ++}
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+25
+
-9
+ +
+ +
+
+
diff --git OP/op-challenger/game/fault/trace/vm/prestates.go CELO/op-challenger/game/fault/trace/vm/prestates.go +index c51dda7de1e5bf1346d1657be0d235ad4f473255..b54d86ed9ccafd77cfbe79ce1769727d1e5f39bc 100644 +--- OP/op-challenger/game/fault/trace/vm/prestates.go ++++ CELO/op-challenger/game/fault/trace/vm/prestates.go +@@ -14,16 +14,26 @@ log2 "github.com/ethereum-optimism/optimism/op-service/log" + "github.com/ethereum/go-ethereum/log" + ) +  +-type SnapshotSelect func(logger log.Logger, dir string, absolutePreState string, i uint64) (string, error) ++type SnapshotSelect func(logger log.Logger, dir string, absolutePreState string, i uint64, binary bool) (string, error) + type CmdExecutor func(ctx context.Context, l log.Logger, binary string, args ...string) error +  + const ( +- SnapsDir = "snapshots" +- PreimagesDir = "preimages" +- FinalState = "final.json.gz" ++ SnapsDir = "snapshots" ++ PreimagesDir = "preimages" ++ finalStateJson = "final.json.gz" ++ finalStateBinary = "final.bin.gz" + ) +  +-var snapshotNameRegexp = regexp.MustCompile(`^[0-9]+\.json.gz$`) ++func FinalStatePath(dir string, binarySnapshots bool) string { ++ filename := finalStateJson ++ if binarySnapshots { ++ filename = finalStateBinary ++ } ++ return filepath.Join(dir, filename) ++} ++ ++var snapshotJsonNameRegexp = regexp.MustCompile(`^[0-9]+\.json\.gz$`) ++var snapshotBinaryNameRegexp = regexp.MustCompile(`^[0-9]+\.bin\.gz$`) +  + func PreimageDir(dir string) string { + return filepath.Join(dir, PreimagesDir) +@@ -43,7 +53,13 @@ } +  + // FindStartingSnapshot finds the closest snapshot before the specified traceIndex in snapDir. + // If no suitable snapshot can be found it returns absolutePreState. +-func FindStartingSnapshot(logger log.Logger, snapDir string, absolutePreState string, traceIndex uint64) (string, error) { ++func FindStartingSnapshot(logger log.Logger, snapDir string, absolutePreState string, traceIndex uint64, binarySnapshots bool) (string, error) { ++ suffix := ".json.gz" ++ nameRegexp := snapshotJsonNameRegexp ++ if binarySnapshots { ++ suffix = ".bin.gz" ++ nameRegexp = snapshotBinaryNameRegexp ++ } + // Find the closest snapshot to start from + entries, err := os.ReadDir(snapDir) + if err != nil { +@@ -59,11 +75,11 @@ logger.Warn("Unexpected directory in snapshots dir", "parent", snapDir, "child", entry.Name()) + continue + } + name := entry.Name() +- if !snapshotNameRegexp.MatchString(name) { ++ if !nameRegexp.MatchString(name) { + logger.Warn("Unexpected file in snapshots dir", "parent", snapDir, "child", entry.Name()) + continue + } +- index, err := strconv.ParseUint(name[0:len(name)-len(".json.gz")], 10, 64) ++ index, err := strconv.ParseUint(name[0:len(name)-len(suffix)], 10, 64) + if err != nil { + logger.Error("Unable to parse trace index of snapshot file", "parent", snapDir, "child", entry.Name()) + continue +@@ -75,7 +91,7 @@ } + if bestSnap == 0 { + return absolutePreState, nil + } +- startFrom := fmt.Sprintf("%v/%v.json.gz", snapDir, bestSnap) ++ startFrom := fmt.Sprintf("%v/%v%v", snapDir, bestSnap, suffix) +  + return startFrom, nil + }
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+3
+
-1
+ +
+ +
+
+
diff --git OP/op-challenger/game/fault/types/types.go CELO/op-challenger/game/fault/types/types.go +index 93c8b19bd54257e0181e9999577ae3191fc39179..46227668e92850d5da6dbeed8bab0c30aa77f44d 100644 +--- OP/op-challenger/game/fault/types/types.go ++++ CELO/op-challenger/game/fault/types/types.go +@@ -67,7 +67,7 @@ TraceTypeAsteriscKona TraceType = "asterisc-kona" + TraceTypePermissioned TraceType = "permissioned" + ) +  +-var TraceTypes = []TraceType{TraceTypeAlphabet, TraceTypeCannon, TraceTypePermissioned, TraceTypeAsterisc, TraceTypeFast} ++var TraceTypes = []TraceType{TraceTypeAlphabet, TraceTypeCannon, TraceTypePermissioned, TraceTypeAsterisc, TraceTypeAsteriscKona, TraceTypeFast} +  + func (t TraceType) String() string { + return string(t) +@@ -104,6 +104,8 @@ case TraceTypePermissioned: + return PermissionedGameType + case TraceTypeAsterisc: + return AsteriscGameType ++ case TraceTypeAsteriscKona: ++ return AsteriscKonaGameType + case TraceTypeFast: + return FastGameType + case TraceTypeAlphabet:
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+21
+
-8
+ +
+ +
+
+
diff --git OP/op-conductor/conductor/config.go CELO/op-conductor/conductor/config.go +index 2d356a6553e1be44a281f4b87cc50da4464d099d..ca18de7d1a18fae74506a6c1eb328fb86f088c96 100644 +--- OP/op-conductor/conductor/config.go ++++ CELO/op-conductor/conductor/config.go +@@ -3,6 +3,7 @@ + import ( + "fmt" + "math" ++ "time" +  + "github.com/ethereum/go-ethereum/log" + "github.com/pkg/errors" +@@ -32,6 +33,15 @@ RaftStorageDir string +  + // RaftBootstrap is true if this node should bootstrap a new raft cluster. + RaftBootstrap bool ++ ++ // RaftSnapshotInterval is the interval to check if a snapshot should be taken. ++ RaftSnapshotInterval time.Duration ++ ++ // RaftSnapshotThreshold is the number of logs to trigger a snapshot. ++ RaftSnapshotThreshold uint64 ++ ++ // RaftTrailingLogs is the number of logs to keep after a snapshot. ++ RaftTrailingLogs uint64 +  + // NodeRPC is the HTTP provider URL for op-node. + NodeRPC string +@@ -107,14 +117,17 @@ return nil, errors.Wrap(err, "failed to load rollup config") + } +  + return &Config{ +- ConsensusAddr: ctx.String(flags.ConsensusAddr.Name), +- ConsensusPort: ctx.Int(flags.ConsensusPort.Name), +- RaftBootstrap: ctx.Bool(flags.RaftBootstrap.Name), +- RaftServerID: ctx.String(flags.RaftServerID.Name), +- RaftStorageDir: ctx.String(flags.RaftStorageDir.Name), +- NodeRPC: ctx.String(flags.NodeRPC.Name), +- ExecutionRPC: ctx.String(flags.ExecutionRPC.Name), +- Paused: ctx.Bool(flags.Paused.Name), ++ ConsensusAddr: ctx.String(flags.ConsensusAddr.Name), ++ ConsensusPort: ctx.Int(flags.ConsensusPort.Name), ++ RaftBootstrap: ctx.Bool(flags.RaftBootstrap.Name), ++ RaftServerID: ctx.String(flags.RaftServerID.Name), ++ RaftStorageDir: ctx.String(flags.RaftStorageDir.Name), ++ RaftSnapshotInterval: ctx.Duration(flags.RaftSnapshotInterval.Name), ++ RaftSnapshotThreshold: ctx.Uint64(flags.RaftSnapshotThreshold.Name), ++ RaftTrailingLogs: ctx.Uint64(flags.RaftTrailingLogs.Name), ++ NodeRPC: ctx.String(flags.NodeRPC.Name), ++ ExecutionRPC: ctx.String(flags.ExecutionRPC.Name), ++ Paused: ctx.Bool(flags.Paused.Name), + HealthCheck: HealthCheckConfig{ + Interval: ctx.Uint64(flags.HealthCheckInterval.Name), + UnsafeInterval: ctx.Uint64(flags.HealthCheckUnsafeInterval.Name),
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+11
+
-1
+ +
+ +
+
+
diff --git OP/op-conductor/conductor/service.go CELO/op-conductor/conductor/service.go +index 2a39193c6bcc76995ccb35c27e09da636280319a..d2eb4fe89d9dc73c447ddea5c99e1af0226bc5d8 100644 +--- OP/op-conductor/conductor/service.go ++++ CELO/op-conductor/conductor/service.go +@@ -149,7 +149,17 @@ return nil + } +  + serverAddr := fmt.Sprintf("%s:%d", c.cfg.ConsensusAddr, c.cfg.ConsensusPort) +- cons, err := consensus.NewRaftConsensus(c.log, c.cfg.RaftServerID, serverAddr, c.cfg.RaftStorageDir, c.cfg.RaftBootstrap, &c.cfg.RollupCfg) ++ raftConsensusConfig := &consensus.RaftConsensusConfig{ ++ ServerID: c.cfg.RaftServerID, ++ ServerAddr: serverAddr, ++ StorageDir: c.cfg.RaftStorageDir, ++ Bootstrap: c.cfg.RaftBootstrap, ++ RollupCfg: &c.cfg.RollupCfg, ++ SnapshotInterval: c.cfg.RaftSnapshotInterval, ++ SnapshotThreshold: c.cfg.RaftSnapshotThreshold, ++ TrailingLogs: c.cfg.RaftTrailingLogs, ++ } ++ cons, err := consensus.NewRaftConsensus(c.log, raftConsensusConfig) + if err != nil { + return errors.Wrap(err, "failed to create raft consensus") + }
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+24
+
-10
+ +
+ +
+
+
diff --git OP/op-conductor/consensus/raft.go CELO/op-conductor/consensus/raft.go +index c534d03058478078306cd6458792c71958be1503..f6acc0fb76f171789dcae82bd0cabc4c54ce94fa 100644 +--- OP/op-conductor/consensus/raft.go ++++ CELO/op-conductor/consensus/raft.go +@@ -32,6 +32,17 @@ + unsafeTracker *unsafeHeadTracker + } +  ++type RaftConsensusConfig struct { ++ ServerID string ++ ServerAddr string ++ StorageDir string ++ Bootstrap bool ++ RollupCfg *rollup.Config ++ SnapshotInterval time.Duration ++ SnapshotThreshold uint64 ++ TrailingLogs uint64 ++} ++ + // checkTCPPortOpen attempts to connect to the specified address and returns an error if the connection fails. + func checkTCPPortOpen(address string) error { + conn, err := net.DialTimeout("tcp", address, 5*time.Second) +@@ -43,11 +54,14 @@ return nil + } +  + // NewRaftConsensus creates a new RaftConsensus instance. +-func NewRaftConsensus(log log.Logger, serverID, serverAddr, storageDir string, bootstrap bool, rollupCfg *rollup.Config) (*RaftConsensus, error) { ++func NewRaftConsensus(log log.Logger, cfg *RaftConsensusConfig) (*RaftConsensus, error) { + rc := raft.DefaultConfig() +- rc.LocalID = raft.ServerID(serverID) ++ rc.SnapshotInterval = cfg.SnapshotInterval ++ rc.TrailingLogs = cfg.TrailingLogs ++ rc.SnapshotThreshold = cfg.SnapshotThreshold ++ rc.LocalID = raft.ServerID(cfg.ServerID) +  +- baseDir := filepath.Join(storageDir, serverID) ++ baseDir := filepath.Join(cfg.StorageDir, cfg.ServerID) + if _, err := os.Stat(baseDir); os.IsNotExist(err) { + if err := os.MkdirAll(baseDir, 0o755); err != nil { + return nil, fmt.Errorf("error creating storage dir: %w", err) +@@ -72,7 +86,7 @@ if err != nil { + return nil, fmt.Errorf(`raft.NewFileSnapshotStore(%q): %w`, baseDir, err) + } +  +- addr, err := net.ResolveTCPAddr("tcp", serverAddr) ++ addr, err := net.ResolveTCPAddr("tcp", cfg.ServerAddr) + if err != nil { + return nil, errors.Wrap(err, "failed to resolve tcp address") + } +@@ -95,18 +109,18 @@ } +  + // If bootstrap = true, start raft in bootstrap mode, this will allow the current node to elect itself as leader when there's no other participants + // and allow other nodes to join the cluster. +- if bootstrap { +- cfg := raft.Configuration{ ++ if cfg.Bootstrap { ++ raftCfg := raft.Configuration{ + Servers: []raft.Server{ + { + ID: rc.LocalID, +- Address: raft.ServerAddress(serverAddr), ++ Address: raft.ServerAddress(cfg.ServerAddr), + Suffrage: raft.Voter, + }, + }, + } +  +- f := r.BootstrapCluster(cfg) ++ f := r.BootstrapCluster(raftCfg) + if err := f.Error(); err != nil { + return nil, errors.Wrap(err, "failed to bootstrap raft cluster") + } +@@ -115,9 +129,9 @@ + return &RaftConsensus{ + log: log, + r: r, +- serverID: raft.ServerID(serverID), ++ serverID: raft.ServerID(cfg.ServerID), + unsafeTracker: fsm, +- rollupCfg: rollupCfg, ++ rollupCfg: cfg.RollupCfg, + }, nil + } +
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+11
+
-4
+ +
+ +
+
+
diff --git OP/op-conductor/consensus/raft_test.go CELO/op-conductor/consensus/raft_test.go +index 332bbd203e7e6f45d2439a417da2f5548f5c8318..fbd9c7cb3bc81d306bfdf3a9c89ec9ceb0b10a2f 100644 +--- OP/op-conductor/consensus/raft_test.go ++++ CELO/op-conductor/consensus/raft_test.go +@@ -18,9 +18,6 @@ ) +  + func TestCommitAndRead(t *testing.T) { + log := testlog.Logger(t, log.LevelInfo) +- serverID := "SequencerA" +- serverAddr := "127.0.0.1:0" +- bootstrap := true + now := uint64(time.Now().Unix()) + rollupCfg := &rollup.Config{ + CanyonTime: &now, +@@ -29,8 +26,18 @@ storageDir := "/tmp/sequencerA" + if err := os.RemoveAll(storageDir); err != nil { + t.Fatal(err) + } ++ raftConsensusConfig := &RaftConsensusConfig{ ++ ServerID: "SequencerA", ++ ServerAddr: "127.0.0.1:0", ++ StorageDir: storageDir, ++ Bootstrap: true, ++ RollupCfg: rollupCfg, ++ SnapshotInterval: 120 * time.Second, ++ SnapshotThreshold: 10240, ++ TrailingLogs: 8192, ++ } +  +- cons, err := NewRaftConsensus(log, serverID, serverAddr, storageDir, bootstrap, rollupCfg) ++ cons, err := NewRaftConsensus(log, raftConsensusConfig) + require.NoError(t, err) +  + // wait till it became leader
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+22
+
-0
+ +
+ +
+
+
diff --git OP/op-conductor/flags/flags.go CELO/op-conductor/flags/flags.go +index 4870ba4a3ab03c6a9d6afaa705cc66351639812a..249e8a676e0798f545d67d23c13320c3f976b773 100644 +--- OP/op-conductor/flags/flags.go ++++ CELO/op-conductor/flags/flags.go +@@ -2,6 +2,7 @@ package flags +  + import ( + "fmt" ++ "time" +  + "github.com/urfave/cli/v2" +  +@@ -43,6 +44,24 @@ RaftStorageDir = &cli.StringFlag{ + Name: "raft.storage.dir", + Usage: "Directory to store raft data", + EnvVars: opservice.PrefixEnvVar(EnvVarPrefix, "RAFT_STORAGE_DIR"), ++ } ++ RaftSnapshotInterval = &cli.DurationFlag{ ++ Name: "raft.snapshot-interval", ++ Usage: "The interval to check if a snapshot should be taken.", ++ EnvVars: opservice.PrefixEnvVar(EnvVarPrefix, "RAFT_SNAPSHOT_INTERVAL"), ++ Value: 120 * time.Second, ++ } ++ RaftSnapshotThreshold = &cli.Uint64Flag{ ++ Name: "raft.snapshot-threshold", ++ Usage: "Number of logs to trigger a snapshot", ++ EnvVars: opservice.PrefixEnvVar(EnvVarPrefix, "RAFT_SNAPSHOT_THRESHOLD"), ++ Value: 8192, ++ } ++ RaftTrailingLogs = &cli.Uint64Flag{ ++ Name: "raft.trailing-logs", ++ Usage: "Number of logs to keep after a snapshot", ++ EnvVars: opservice.PrefixEnvVar(EnvVarPrefix, "RAFT_TRAILING_LOGS"), ++ Value: 10240, + } + NodeRPC = &cli.StringFlag{ + Name: "node.rpc", +@@ -113,6 +132,9 @@ RPCEnableProxy, + RaftBootstrap, + HealthCheckSafeEnabled, + HealthCheckSafeInterval, ++ RaftSnapshotInterval, ++ RaftSnapshotThreshold, ++ RaftTrailingLogs, + } +  + func init() {
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+7
+
-21
+ +
+ +
+
+
diff --git OP/op-dispute-mon/mon/bonds/monitor.go CELO/op-dispute-mon/mon/bonds/monitor.go +index efa7804d340850125981f0699193c85f30df9e0b..2ce23dc472e749ffe64b78ea1540ea4ac2154009 100644 +--- OP/op-dispute-mon/mon/bonds/monitor.go ++++ CELO/op-dispute-mon/mon/bonds/monitor.go +@@ -17,22 +17,19 @@ + type BondMetrics interface { + RecordCredit(expectation metrics.CreditExpectation, count int) + RecordBondCollateral(addr common.Address, required *big.Int, available *big.Int) +- RecordHonestWithdrawableAmounts(map[common.Address]*big.Int) + } +  + type Bonds struct { +- logger log.Logger +- clock RClock +- metrics BondMetrics +- honestActors types.HonestActors ++ logger log.Logger ++ clock RClock ++ metrics BondMetrics + } +  +-func NewBonds(logger log.Logger, metrics BondMetrics, honestActors types.HonestActors, clock RClock) *Bonds { ++func NewBonds(logger log.Logger, metrics BondMetrics, clock RClock) *Bonds { + return &Bonds{ +- logger: logger, +- clock: clock, +- metrics: metrics, +- honestActors: honestActors, ++ logger: logger, ++ clock: clock, ++ metrics: metrics, + } + } +  +@@ -50,10 +47,6 @@ } +  + func (b *Bonds) checkCredits(games []*types.EnrichedGameData) { + creditMetrics := make(map[metrics.CreditExpectation]int) +- honestWithdrawableAmounts := make(map[common.Address]*big.Int) +- for address := range b.honestActors { +- honestWithdrawableAmounts[address] = big.NewInt(0) +- } +  + for _, game := range games { + // Check if the max duration has been reached for this game +@@ -101,12 +94,6 @@ expected = big.NewInt(0) + } + comparison := actual.Cmp(expected) + if maxDurationReached { +- if actual.Cmp(big.NewInt(0)) > 0 && b.honestActors.Contains(recipient) { +- total := honestWithdrawableAmounts[recipient] +- total = new(big.Int).Add(total, actual) +- honestWithdrawableAmounts[recipient] = total +- b.logger.Warn("Found unclaimed credit", "recipient", recipient, "game", game.Proxy, "amount", actual) +- } + if comparison > 0 { + creditMetrics[metrics.CreditAboveWithdrawable] += 1 + b.logger.Warn("Credit above expected amount", "recipient", recipient, "expected", expected, "actual", actual, "game", game.Proxy, "withdrawable", "withdrawable") +@@ -136,5 +123,4 @@ + b.metrics.RecordCredit(metrics.CreditBelowNonWithdrawable, creditMetrics[metrics.CreditBelowNonWithdrawable]) + b.metrics.RecordCredit(metrics.CreditEqualNonWithdrawable, creditMetrics[metrics.CreditEqualNonWithdrawable]) + b.metrics.RecordCredit(metrics.CreditAboveNonWithdrawable, creditMetrics[metrics.CreditAboveNonWithdrawable]) +- b.metrics.RecordHonestWithdrawableAmounts(honestWithdrawableAmounts) + }
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+10
+
-47
+ +
+ +
+
+
diff --git OP/op-dispute-mon/mon/bonds/monitor_test.go CELO/op-dispute-mon/mon/bonds/monitor_test.go +index 5fd766b870613b7f6537e496be0f2c651d1eca10..dbeddd74d9c71dadbc6c30e0171813d57ca4c202 100644 +--- OP/op-dispute-mon/mon/bonds/monitor_test.go ++++ CELO/op-dispute-mon/mon/bonds/monitor_test.go +@@ -17,10 +17,7 @@ "github.com/stretchr/testify/require" + ) +  + var ( +- frozen = time.Unix(int64(time.Hour.Seconds()), 0) +- honestActor1 = common.Address{0x11, 0xaa} +- honestActor2 = common.Address{0x22, 0xbb} +- honestActor3 = common.Address{0x33, 0xcc} ++ frozen = time.Unix(int64(time.Hour.Seconds()), 0) + ) +  + func TestCheckBonds(t *testing.T) { +@@ -64,8 +61,8 @@ require.Nil(t, logs.FindLog(testlog.NewAttributesFilter("delayedWETH", weth1.Hex()))) + } +  + func TestCheckRecipientCredit(t *testing.T) { +- addr1 := honestActor1 +- addr2 := honestActor2 ++ addr1 := common.Address{0x11, 0xaa} ++ addr2 := common.Address{0x22, 0xbb} + addr3 := common.Address{0x3c} + addr4 := common.Address{0x4d} + notRootPosition := types.NewPositionFromGIndex(big.NewInt(2)) +@@ -349,14 +346,6 @@ require.Equal(t, 3, m.credits[metrics.CreditBelowNonWithdrawable], "CreditBelowNonWithdrawable") + require.Equal(t, 2, m.credits[metrics.CreditEqualNonWithdrawable], "CreditEqualNonWithdrawable") + require.Equal(t, 2, m.credits[metrics.CreditAboveNonWithdrawable], "CreditAboveNonWithdrawable") +  +- require.Len(t, m.honestWithdrawable, 3) +- requireBigInt := func(name string, expected, actual *big.Int) { +- require.Truef(t, expected.Cmp(actual) == 0, "Expected %v withdrawable to be %v but was %v", name, expected, actual) +- } +- requireBigInt("honest addr1", m.honestWithdrawable[addr1], big.NewInt(19)) +- requireBigInt("honest addr2", m.honestWithdrawable[addr2], big.NewInt(13)) +- requireBigInt("honest addr3", m.honestWithdrawable[honestActor3], big.NewInt(0)) +- + // Logs from game1 + // addr1 is correct so has no logs + // addr2 is below expected before max duration, so warn about early withdrawal +@@ -382,18 +371,8 @@ testlog.NewAttributesFilter("recipient", addr4.Hex()), + testlog.NewAttributesFilter("withdrawable", "non_withdrawable"))) +  + // Logs from game 2 +- // addr1 is below expected - no warning as withdrawals may now be possible, but has unclaimed credit +- require.NotNil(t, logs.FindLog( +- testlog.NewLevelFilter(log.LevelWarn), +- testlog.NewMessageFilter("Found unclaimed credit"), +- testlog.NewAttributesFilter("game", game2.Proxy.Hex()), +- testlog.NewAttributesFilter("recipient", addr1.Hex()))) +- // addr2 is correct but has unclaimed credit +- require.NotNil(t, logs.FindLog( +- testlog.NewLevelFilter(log.LevelWarn), +- testlog.NewMessageFilter("Found unclaimed credit"), +- testlog.NewAttributesFilter("game", game2.Proxy.Hex()), +- testlog.NewAttributesFilter("recipient", addr2.Hex()))) ++ // addr1 is below expected - no warning as withdrawals may now be possible ++ // addr2 is correct + // addr3 is above expected - warn + require.NotNil(t, logs.FindLog( + testlog.NewLevelFilter(log.LevelWarn), +@@ -422,18 +401,8 @@ testlog.NewAttributesFilter("recipient", addr4.Hex()), + testlog.NewAttributesFilter("withdrawable", "non_withdrawable"))) +  + // Logs from game 4 +- // addr1 is correct but has unclaimed credit +- require.NotNil(t, logs.FindLog( +- testlog.NewLevelFilter(log.LevelWarn), +- testlog.NewMessageFilter("Found unclaimed credit"), +- testlog.NewAttributesFilter("game", game4.Proxy.Hex()), +- testlog.NewAttributesFilter("recipient", addr1.Hex()))) +- // addr2 is below expected before max duration, no log because withdrawals may be possible but warn about unclaimed +- require.NotNil(t, logs.FindLog( +- testlog.NewLevelFilter(log.LevelWarn), +- testlog.NewMessageFilter("Found unclaimed credit"), +- testlog.NewAttributesFilter("game", game4.Proxy.Hex()), +- testlog.NewAttributesFilter("recipient", addr2.Hex()))) ++ // addr1 is correct ++ // addr2 is below expected before max duration, no log because withdrawals may be possible + // addr3 is not involved so no logs + // addr4 is above expected before max duration, so warn + require.NotNil(t, logs.FindLog( +@@ -450,19 +419,13 @@ metrics := &stubBondMetrics{ + credits: make(map[metrics.CreditExpectation]int), + recorded: make(map[common.Address]Collateral), + } +- honestActors := monTypes.NewHonestActors([]common.Address{honestActor1, honestActor2, honestActor3}) +- bonds := NewBonds(logger, metrics, honestActors, clock.NewDeterministicClock(frozen)) ++ bonds := NewBonds(logger, metrics, clock.NewDeterministicClock(frozen)) + return bonds, metrics, logs + } +  + type stubBondMetrics struct { +- credits map[metrics.CreditExpectation]int +- recorded map[common.Address]Collateral +- honestWithdrawable map[common.Address]*big.Int +-} +- +-func (s *stubBondMetrics) RecordHonestWithdrawableAmounts(values map[common.Address]*big.Int) { +- s.honestWithdrawable = values ++ credits map[metrics.CreditExpectation]int ++ recorded map[common.Address]Collateral + } +  + func (s *stubBondMetrics) RecordBondCollateral(addr common.Address, required *big.Int, available *big.Int) {
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+2
+
-2
+ +
+ +
+
+
diff --git OP/op-dispute-mon/mon/service.go CELO/op-dispute-mon/mon/service.go +index e637b23d63b0d79298fe0bd806868e8eae0e26a7..8ce97b7b8dd9219bf4c28104ce4850d2b7d4365f 100644 +--- OP/op-dispute-mon/mon/service.go ++++ CELO/op-dispute-mon/mon/service.go +@@ -116,7 +116,7 @@ s.resolutions = NewResolutionMonitor(s.logger, s.metrics, s.cl) + } +  + func (s *Service) initWithdrawalMonitor() { +- s.withdrawals = NewWithdrawalMonitor(s.logger, s.metrics) ++ s.withdrawals = NewWithdrawalMonitor(s.logger, s.cl, s.metrics, s.honestActors) + } +  + func (s *Service) initGameCallerCreator() { +@@ -145,7 +145,7 @@ s.forecast = NewForecast(s.logger, s.metrics) + } +  + func (s *Service) initBonds() { +- s.bonds = bonds.NewBonds(s.logger, s.metrics, s.honestActors, s.cl) ++ s.bonds = bonds.NewBonds(s.logger, s.metrics, s.cl) + } +  + func (s *Service) initOutputRollupClient(ctx context.Context, cfg *config.Config) error {
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+31
+
-7
+ +
+ +
+
+
diff --git OP/op-dispute-mon/mon/withdrawals.go CELO/op-dispute-mon/mon/withdrawals.go +index 5563b099afe5aac382a641027dee72b2c9742259..1c7e9da2f9af0236570c8964d6b24d971a05e0d8 100644 +--- OP/op-dispute-mon/mon/withdrawals.go ++++ CELO/op-dispute-mon/mon/withdrawals.go +@@ -1,6 +1,9 @@ + package mon +  + import ( ++ "math/big" ++ "time" ++ + "github.com/ethereum-optimism/optimism/op-dispute-mon/mon/types" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/log" +@@ -8,25 +11,35 @@ ) +  + type WithdrawalMetrics interface { + RecordWithdrawalRequests(delayedWeth common.Address, matches bool, count int) ++ RecordHonestWithdrawableAmounts(map[common.Address]*big.Int) + } +  + type WithdrawalMonitor struct { +- logger log.Logger +- metrics WithdrawalMetrics ++ logger log.Logger ++ clock RClock ++ metrics WithdrawalMetrics ++ honestActors types.HonestActors + } +  +-func NewWithdrawalMonitor(logger log.Logger, metrics WithdrawalMetrics) *WithdrawalMonitor { ++func NewWithdrawalMonitor(logger log.Logger, clock RClock, metrics WithdrawalMetrics, honestActors types.HonestActors) *WithdrawalMonitor { + return &WithdrawalMonitor{ +- logger: logger, +- metrics: metrics, ++ logger: logger, ++ clock: clock, ++ metrics: metrics, ++ honestActors: honestActors, + } + } +  + func (w *WithdrawalMonitor) CheckWithdrawals(games []*types.EnrichedGameData) { ++ now := w.clock.Now() // Use a consistent time for all checks + matching := make(map[common.Address]int) + divergent := make(map[common.Address]int) ++ honestWithdrawableAmounts := make(map[common.Address]*big.Int) ++ for address := range w.honestActors { ++ honestWithdrawableAmounts[address] = big.NewInt(0) ++ } + for _, game := range games { +- matches, diverges := w.validateGameWithdrawals(game) ++ matches, diverges := w.validateGameWithdrawals(game, now, honestWithdrawableAmounts) + matching[game.WETHContract] += matches + divergent[game.WETHContract] += diverges + } +@@ -36,9 +49,10 @@ } + for contract, count := range divergent { + w.metrics.RecordWithdrawalRequests(contract, false, count) + } ++ w.metrics.RecordHonestWithdrawableAmounts(honestWithdrawableAmounts) + } +  +-func (w *WithdrawalMonitor) validateGameWithdrawals(game *types.EnrichedGameData) (int, int) { ++func (w *WithdrawalMonitor) validateGameWithdrawals(game *types.EnrichedGameData, now time.Time, honestWithdrawableAmounts map[common.Address]*big.Int) (int, int) { + matching := 0 + divergent := 0 + for recipient, withdrawalAmount := range game.WithdrawalRequests { +@@ -47,6 +61,16 @@ matching++ + } else { + divergent++ + w.logger.Error("Withdrawal request amount does not match credit", "game", game.Proxy, "recipient", recipient, "credit", game.Credits[recipient], "withdrawal", game.WithdrawalRequests[recipient].Amount) ++ } ++ ++ if withdrawalAmount.Amount.Cmp(big.NewInt(0)) > 0 && w.honestActors.Contains(recipient) { ++ if time.Unix(withdrawalAmount.Timestamp.Int64(), 0).Add(game.WETHDelay).Before(now) { ++ // Credits are withdrawable ++ total := honestWithdrawableAmounts[recipient] ++ total = new(big.Int).Add(total, withdrawalAmount.Amount) ++ honestWithdrawableAmounts[recipient] = total ++ w.logger.Warn("Found unclaimed credit", "recipient", recipient, "game", game.Proxy, "amount", withdrawalAmount.Amount) ++ } + } + } + return matching, divergent
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+86
+
-19
+ +
+ +
+
+
diff --git OP/op-dispute-mon/mon/withdrawals_test.go CELO/op-dispute-mon/mon/withdrawals_test.go +index f598ea38df97a352ef02a2c94b3637ec6d3a3e96..ad17493adf6560b4741f05722f0290eda7936406 100644 +--- OP/op-dispute-mon/mon/withdrawals_test.go ++++ CELO/op-dispute-mon/mon/withdrawals_test.go +@@ -3,9 +3,12 @@ + import ( + "math/big" + "testing" ++ "time" +  + "github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts" ++ "github.com/ethereum-optimism/optimism/op-challenger/game/types" + monTypes "github.com/ethereum-optimism/optimism/op-dispute-mon/mon/types" ++ "github.com/ethereum-optimism/optimism/op-service/clock" + "github.com/ethereum-optimism/optimism/op-service/testlog" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/log" +@@ -15,58 +18,76 @@ + var ( + weth1 = common.Address{0x1a} + weth2 = common.Address{0x2b} ++ ++ honestActor1 = common.Address{0x11, 0xaa} ++ honestActor2 = common.Address{0x22, 0xbb} ++ honestActor3 = common.Address{0x33, 0xcc} ++ dishonestActor4 = common.Address{0x44, 0xdd} ++ ++ nowUnix = int64(10_000) + ) +  + func makeGames() []*monTypes.EnrichedGameData { + weth1Balance := big.NewInt(4200) + weth2Balance := big.NewInt(6000) ++ + game1 := &monTypes.EnrichedGameData{ ++ GameMetadata: types.GameMetadata{Proxy: common.Address{0x11, 0x11, 0x11}}, + Credits: map[common.Address]*big.Int{ +- common.Address{0x01}: big.NewInt(3), +- common.Address{0x02}: big.NewInt(1), ++ honestActor1: big.NewInt(3), ++ honestActor2: big.NewInt(1), + }, + WithdrawalRequests: map[common.Address]*contracts.WithdrawalRequest{ +- common.Address{0x01}: &contracts.WithdrawalRequest{Amount: big.NewInt(3)}, +- common.Address{0x02}: &contracts.WithdrawalRequest{Amount: big.NewInt(1)}, ++ honestActor1: {Amount: big.NewInt(3), Timestamp: big.NewInt(nowUnix - 101)}, // Claimable ++ honestActor2: {Amount: big.NewInt(1), Timestamp: big.NewInt(nowUnix - 99)}, // Not claimable + }, + WETHContract: weth1, + ETHCollateral: weth1Balance, ++ WETHDelay: 100 * time.Second, + } + game2 := &monTypes.EnrichedGameData{ ++ GameMetadata: types.GameMetadata{Proxy: common.Address{0x22, 0x22, 0x22}}, + Credits: map[common.Address]*big.Int{ +- common.Address{0x01}: big.NewInt(46), +- common.Address{0x02}: big.NewInt(1), ++ honestActor1: big.NewInt(46), ++ honestActor2: big.NewInt(1), + }, + WithdrawalRequests: map[common.Address]*contracts.WithdrawalRequest{ +- common.Address{0x01}: &contracts.WithdrawalRequest{Amount: big.NewInt(3)}, +- common.Address{0x02}: &contracts.WithdrawalRequest{Amount: big.NewInt(1)}, ++ honestActor1: {Amount: big.NewInt(3), Timestamp: big.NewInt(nowUnix - 501)}, // Claimable ++ honestActor2: {Amount: big.NewInt(1), Timestamp: big.NewInt(nowUnix)}, // Not claimable + }, + WETHContract: weth2, + ETHCollateral: weth2Balance, ++ WETHDelay: 500 * time.Second, + } + game3 := &monTypes.EnrichedGameData{ ++ GameMetadata: types.GameMetadata{Proxy: common.Address{0x33, 0x33, 0x33}}, + Credits: map[common.Address]*big.Int{ +- common.Address{0x03}: big.NewInt(2), +- common.Address{0x04}: big.NewInt(4), ++ honestActor3: big.NewInt(2), ++ dishonestActor4: big.NewInt(4), + }, + WithdrawalRequests: map[common.Address]*contracts.WithdrawalRequest{ +- common.Address{0x03}: &contracts.WithdrawalRequest{Amount: big.NewInt(2)}, +- common.Address{0x04}: &contracts.WithdrawalRequest{Amount: big.NewInt(4)}, ++ honestActor3: {Amount: big.NewInt(2), Timestamp: big.NewInt(nowUnix - 1)}, // Claimable ++ dishonestActor4: {Amount: big.NewInt(4), Timestamp: big.NewInt(nowUnix - 5)}, // Claimable + }, + WETHContract: weth2, + ETHCollateral: weth2Balance, ++ WETHDelay: 0 * time.Second, + } + return []*monTypes.EnrichedGameData{game1, game2, game3} + } +  + func TestCheckWithdrawals(t *testing.T) { +- logger := testlog.Logger(t, log.LvlInfo) ++ now := time.Unix(nowUnix, 0) ++ cl := clock.NewDeterministicClock(now) ++ logger, logs := testlog.CaptureLogger(t, log.LvlInfo) + metrics := &stubWithdrawalsMetrics{ + matching: make(map[common.Address]int), + divergent: make(map[common.Address]int), + } +- withdrawals := NewWithdrawalMonitor(logger, metrics) +- withdrawals.CheckWithdrawals(makeGames()) ++ honestActors := monTypes.NewHonestActors([]common.Address{honestActor1, honestActor2, honestActor3}) ++ withdrawals := NewWithdrawalMonitor(logger, cl, metrics, honestActors) ++ games := makeGames() ++ withdrawals.CheckWithdrawals(games) +  + require.Equal(t, metrics.matchCalls, 2) + require.Equal(t, metrics.divergeCalls, 2) +@@ -80,13 +101,59 @@ require.Equal(t, metrics.matching[weth1], 2) + require.Equal(t, metrics.matching[weth2], 3) + require.Equal(t, metrics.divergent[weth1], 0) + require.Equal(t, metrics.divergent[weth2], 1) ++ ++ require.Len(t, metrics.honestWithdrawable, 3) ++ requireBigInt := func(name string, expected, actual *big.Int) { ++ require.Truef(t, expected.Cmp(actual) == 0, "Expected %v withdrawable to be %v but was %v", name, expected, actual) ++ } ++ requireBigInt("honest addr1", big.NewInt(6), metrics.honestWithdrawable[honestActor1]) ++ requireBigInt("honest addr2", big.NewInt(0), metrics.honestWithdrawable[honestActor2]) ++ requireBigInt("honest addr3", big.NewInt(2), metrics.honestWithdrawable[honestActor3]) ++ require.Nil(t, metrics.honestWithdrawable[dishonestActor4], "should only report withdrawable credits for honest actors") ++ ++ findUnclaimedCreditWarning := func(game common.Address, actor common.Address) *testlog.CapturedRecord { ++ return logs.FindLog( ++ testlog.NewLevelFilter(log.LevelWarn), ++ testlog.NewMessageFilter("Found unclaimed credit"), ++ testlog.NewAttributesFilter("game", game.Hex()), ++ testlog.NewAttributesFilter("recipient", actor.Hex())) ++ } ++ requireUnclaimedWarning := func(game common.Address, actor common.Address) { ++ require.NotNil(t, findUnclaimedCreditWarning(game, actor)) ++ } ++ noUnclaimedWarning := func(game common.Address, actor common.Address) { ++ require.Nil(t, findUnclaimedCreditWarning(game, actor)) ++ } ++ // Game 1, unclaimed for honestActor1 only ++ requireUnclaimedWarning(games[0].Proxy, honestActor1) ++ noUnclaimedWarning(games[0].Proxy, honestActor2) ++ noUnclaimedWarning(games[0].Proxy, honestActor3) ++ noUnclaimedWarning(games[0].Proxy, dishonestActor4) ++ ++ // Game 2, unclaimed for honestActor1 only ++ requireUnclaimedWarning(games[1].Proxy, honestActor1) ++ noUnclaimedWarning(games[1].Proxy, honestActor2) ++ noUnclaimedWarning(games[1].Proxy, honestActor3) ++ noUnclaimedWarning(games[1].Proxy, dishonestActor4) ++ ++ // Game 3, unclaimed for honestActor3 only ++ // dishonestActor4 has unclaimed credits but we don't track them ++ noUnclaimedWarning(games[2].Proxy, honestActor1) ++ noUnclaimedWarning(games[2].Proxy, honestActor2) ++ requireUnclaimedWarning(games[2].Proxy, honestActor3) ++ noUnclaimedWarning(games[2].Proxy, dishonestActor4) + } +  + type stubWithdrawalsMetrics struct { +- matchCalls int +- divergeCalls int +- matching map[common.Address]int +- divergent map[common.Address]int ++ matchCalls int ++ divergeCalls int ++ matching map[common.Address]int ++ divergent map[common.Address]int ++ honestWithdrawable map[common.Address]*big.Int ++} ++ ++func (s *stubWithdrawalsMetrics) RecordHonestWithdrawableAmounts(honestWithdrawable map[common.Address]*big.Int) { ++ s.honestWithdrawable = honestWithdrawable + } +  + func (s *stubWithdrawalsMetrics) RecordWithdrawalRequests(addr common.Address, matches bool, count int) {
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+28
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/interop/contracts/test-artifacts/emit.sol/EmitEvent.abi CELO/op-e2e/interop/contracts/test-artifacts/emit.sol/EmitEvent.abi +new file mode 100644 +index 0000000000000000000000000000000000000000..79170e79f968e83958eb5966383ee8bbbdde2800 +--- /dev/null ++++ CELO/op-e2e/interop/contracts/test-artifacts/emit.sol/EmitEvent.abi +@@ -0,0 +1,28 @@ ++[ + { -+ type: 'event', -+ name: 'WithdrawalFinalized', -+ inputs: [ -+ { -+ name: 'withdrawalHash', -+ type: 'bytes32', -+ indexed: true, -+ internalType: 'bytes32', -+ }, ++ "type": "function", ++ "name": "emitData", ++ "inputs": [ + { -+ name: 'success', -+ type: 'bool', -+ indexed: false, -+ internalType: 'bool', -+ }, ++ "name": "data", ++ "type": "bytes", ++ "internalType": "bytes" ++ } + ], -+ anonymous: false, ++ "outputs": [], ++ "stateMutability": "nonpayable" + }, + { -+ type: 'event', -+ name: 'WithdrawalProven', -+ inputs: [ -+ { -+ name: 'withdrawalHash', -+ type: 'bytes32', -+ indexed: true, -+ internalType: 'bytes32', -+ }, -+ { -+ name: 'from', -+ type: 'address', -+ indexed: true, -+ internalType: 'address', -+ }, ++ "type": "event", ++ "name": "DataEmitted", ++ "inputs": [ + { -+ name: 'to', -+ type: 'address', -+ indexed: true, -+ internalType: 'address', -+ }, ++ "name": "data", ++ "type": "bytes", ++ "indexed": true, ++ "internalType": "bytes" ++ } + ], -+ anonymous: false, -+ }, -+ { -+ type: 'error', -+ name: 'BadTarget', -+ inputs: [], -+ }, -+ { -+ type: 'error', -+ name: 'CallPaused', -+ inputs: [], -+ }, -+ { -+ type: 'error', -+ name: 'ContentLengthMismatch', -+ inputs: [], -+ }, -+ { -+ type: 'error', -+ name: 'EmptyItem', -+ inputs: [], -+ }, -+ { -+ type: 'error', -+ name: 'GasEstimation', -+ inputs: [], -+ }, -+ { -+ type: 'error', -+ name: 'InvalidDataRemainder', -+ inputs: [], -+ }, -+ { -+ type: 'error', -+ name: 'InvalidHeader', -+ inputs: [], -+ }, -+ { -+ type: 'error', -+ name: 'LargeCalldata', -+ inputs: [], -+ }, -+ { -+ type: 'error', -+ name: 'NoValue', -+ inputs: [], -+ }, -+ { -+ type: 'error', -+ name: 'NonReentrant', -+ inputs: [], -+ }, -+ { -+ type: 'error', -+ name: 'OnlyCustomGasToken', -+ inputs: [], -+ }, -+ { -+ type: 'error', -+ name: 'OutOfGas', -+ inputs: [], -+ }, -+ { -+ type: 'error', -+ name: 'SmallGasLimit', -+ inputs: [], -+ }, -+ { -+ type: 'error', -+ name: 'TransferFailed', -+ inputs: [], -+ }, ++ "anonymous": false ++ } ++]
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+1
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/interop/contracts/test-artifacts/emit.sol/EmitEvent.bin CELO/op-e2e/interop/contracts/test-artifacts/emit.sol/EmitEvent.bin +new file mode 100644 +index 0000000000000000000000000000000000000000..f4c15ab05dca76bcb4ddfef4f6965fd81c6f733c +--- /dev/null ++++ CELO/op-e2e/interop/contracts/test-artifacts/emit.sol/EmitEvent.bin +@@ -0,0 +1 @@ ++0x6080604052348015600e575f80fd5b5060ff8061001b5f395ff3fe6080604052348015600e575f80fd5b50600436106026575f3560e01c8063d836083e14602a575b5f80fd5b60396035366004607c565b603b565b005b8181604051604992919060e3565b604051908190038120907fe00bbfe6f6f8f1bbed2da38e3f5a139c6f9da594ab248a3cf8b44fc73627772c905f90a25050565b5f8060208385031215608c575f80fd5b823567ffffffffffffffff8082111560a2575f80fd5b818501915085601f83011260b4575f80fd5b81358181111560c1575f80fd5b86602082850101111560d1575f80fd5b60209290920196919550909350505050565b818382375f910190815291905056fea164736f6c6343000819000a
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+0
+
-0
+ +
+ +
+
+
diff --git OP/op-e2e/interop/contracts/test-artifacts/emit.sol/EmitEvent.json CELO/op-e2e/interop/contracts/test-artifacts/emit.sol/EmitEvent.json +new file mode 100644 +index 0000000000000000000000000000000000000000..422f62ea7324217083b2a4205f8ebc913d145121 +--- /dev/null ++++ CELO/op-e2e/interop/contracts/test-artifacts/emit.sol/EmitEvent.json +@@ -0,0 +1 @@ ++{"abi":[{"type":"function","name":"emitData","inputs":[{"name":"data","type":"bytes","internalType":"bytes"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"event","name":"DataEmitted","inputs":[{"name":"data","type":"bytes","indexed":true,"internalType":"bytes"}],"anonymous":false}],"bytecode":{"object":"0x6080604052348015600e575f80fd5b5060ff8061001b5f395ff3fe6080604052348015600e575f80fd5b50600436106026575f3560e01c8063d836083e14602a575b5f80fd5b60396035366004607c565b603b565b005b8181604051604992919060e3565b604051908190038120907fe00bbfe6f6f8f1bbed2da38e3f5a139c6f9da594ab248a3cf8b44fc73627772c905f90a25050565b5f8060208385031215608c575f80fd5b823567ffffffffffffffff8082111560a2575f80fd5b818501915085601f83011260b4575f80fd5b81358181111560c1575f80fd5b86602082850101111560d1575f80fd5b60209290920196919550909350505050565b818382375f910190815291905056fea164736f6c6343000819000a","sourceMap":"58:275:0:-:0;;;;;;;;;;;;;;;;;;;","linkReferences":{}},"deployedBytecode":{"object":"0x6080604052348015600e575f80fd5b50600436106026575f3560e01c8063d836083e14602a575b5f80fd5b60396035366004607c565b603b565b005b8181604051604992919060e3565b604051908190038120907fe00bbfe6f6f8f1bbed2da38e3f5a139c6f9da594ab248a3cf8b44fc73627772c905f90a25050565b5f8060208385031215608c575f80fd5b823567ffffffffffffffff8082111560a2575f80fd5b818501915085601f83011260b4575f80fd5b81358181111560c1575f80fd5b86602082850101111560d1575f80fd5b60209290920196919550909350505050565b818382375f910190815291905056fea164736f6c6343000819000a","sourceMap":"58:275:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;244:87;;;;;;:::i;:::-;;:::i;:::-;;;319:4;;307:17;;;;;;;:::i;:::-;;;;;;;;;;;;;;;244:87;;:::o;14:591:1:-;84:6;92;145:2;133:9;124:7;120:23;116:32;113:52;;;161:1;158;151:12;113:52;201:9;188:23;230:18;271:2;263:6;260:14;257:34;;;287:1;284;277:12;257:34;325:6;314:9;310:22;300:32;;370:7;363:4;359:2;355:13;351:27;341:55;;392:1;389;382:12;341:55;432:2;419:16;458:2;450:6;447:14;444:34;;;474:1;471;464:12;444:34;519:7;514:2;505:6;501:2;497:15;493:24;490:37;487:57;;;540:1;537;530:12;487:57;571:2;563:11;;;;;593:6;;-1:-1:-1;14:591:1;;-1:-1:-1;;;;14:591:1:o;610:271::-;793:6;785;780:3;767:33;749:3;819:16;;844:13;;;819:16;610:271;-1:-1:-1;610:271:1:o","linkReferences":{}},"methodIdentifiers":{"emitData(bytes)":"d836083e"},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"DataEmitted\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"emitData\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/emit.sol\":\"EmitEvent\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\"},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[]},\"sources\":{\"src/emit.sol\":{\"keccak256\":\"0xdee458d231a8b41e5ba097be7258a6da27501fafb2a6f865705953458aecafbf\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://912d125138604114be66c8d044a39ef83861e6dc2d5fe3be32a1a4e014ea2763\",\"dweb:/ipfs/QmUx5NRsTXzujjwU1SXMSNp5Wjys3v5PDLuhdpoAyCy7nx\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.25+commit.b61c2a91"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"bytes","name":"data","type":"bytes","indexed":true}],"type":"event","name":"DataEmitted","anonymous":false},{"inputs":[{"internalType":"bytes","name":"data","type":"bytes"}],"stateMutability":"nonpayable","type":"function","name":"emitData"}],"devdoc":{"kind":"dev","methods":{},"version":1},"userdoc":{"kind":"user","methods":{},"version":1}},"settings":{"remappings":[],"optimizer":{"enabled":true,"runs":999999},"metadata":{"bytecodeHash":"none"},"compilationTarget":{"src/emit.sol":"EmitEvent"},"evmVersion":"cancun","libraries":{}},"sources":{"src/emit.sol":{"keccak256":"0xdee458d231a8b41e5ba097be7258a6da27501fafb2a6f865705953458aecafbf","urls":["bzz-raw://912d125138604114be66c8d044a39ef83861e6dc2d5fe3be32a1a4e014ea2763","dweb:/ipfs/QmUx5NRsTXzujjwU1SXMSNp5Wjys3v5PDLuhdpoAyCy7nx"],"license":"MIT"}},"version":1},"storageLayout":{"storage":[],"types":{}},"userdoc":{"version":1,"kind":"user"},"devdoc":{"version":1,"kind":"dev"},"ast":{"absolutePath":"src/emit.sol","id":17,"exportedSymbols":{"EmitEvent":[16]},"nodeType":"SourceUnit","src":"32:302:0","nodes":[{"id":1,"nodeType":"PragmaDirective","src":"32:24:0","nodes":[],"literals":["solidity","^","0.8",".15"]},{"id":16,"nodeType":"ContractDefinition","src":"58:275:0","nodes":[{"id":5,"nodeType":"EventDefinition","src":"133:38:0","nodes":[],"anonymous":false,"eventSelector":"e00bbfe6f6f8f1bbed2da38e3f5a139c6f9da594ab248a3cf8b44fc73627772c","name":"DataEmitted","nameLocation":"139:11:0","parameters":{"id":4,"nodeType":"ParameterList","parameters":[{"constant":false,"id":3,"indexed":true,"mutability":"mutable","name":"data","nameLocation":"165:4:0","nodeType":"VariableDeclaration","scope":5,"src":"151:18:0","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bytes_memory_ptr","typeString":"bytes"},"typeName":{"id":2,"name":"bytes","nodeType":"ElementaryTypeName","src":"151:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"150:20:0"}},{"id":15,"nodeType":"FunctionDefinition","src":"244:87:0","nodes":[],"body":{"id":14,"nodeType":"Block","src":"292:39:0","nodes":[],"statements":[{"eventCall":{"arguments":[{"id":11,"name":"data","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":7,"src":"319:4:0","typeDescriptions":{"typeIdentifier":"t_bytes_calldata_ptr","typeString":"bytes calldata"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes_calldata_ptr","typeString":"bytes calldata"}],"id":10,"name":"DataEmitted","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":5,"src":"307:11:0","typeDescriptions":{"typeIdentifier":"t_function_event_nonpayable$_t_bytes_memory_ptr_$returns$__$","typeString":"function (bytes memory)"}},"id":12,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"nameLocations":[],"names":[],"nodeType":"FunctionCall","src":"307:17:0","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":13,"nodeType":"EmitStatement","src":"302:22:0"}]},"functionSelector":"d836083e","implemented":true,"kind":"function","modifiers":[],"name":"emitData","nameLocation":"253:8:0","parameters":{"id":8,"nodeType":"ParameterList","parameters":[{"constant":false,"id":7,"mutability":"mutable","name":"data","nameLocation":"277:4:0","nodeType":"VariableDeclaration","scope":15,"src":"262:19:0","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_bytes_calldata_ptr","typeString":"bytes"},"typeName":{"id":6,"name":"bytes","nodeType":"ElementaryTypeName","src":"262:5:0","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"261:21:0"},"returnParameters":{"id":9,"nodeType":"ParameterList","parameters":[],"src":"292:0:0"},"scope":16,"stateMutability":"nonpayable","virtual":false,"visibility":"external"}],"abstract":false,"baseContracts":[],"canonicalName":"EmitEvent","contractDependencies":[],"contractKind":"contract","fullyImplemented":true,"linearizedBaseContracts":[16],"name":"EmitEvent","nameLocation":"67:9:0","scope":17,"usedErrors":[],"usedEvents":[5]}],"license":"MIT"},"id":0} +\ No newline at end of file
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+4
+
-2
+ +
+ +
+
+
diff --git OP/op-node/cmd/batch_decoder/reassemble/reassemble.go CELO/op-node/cmd/batch_decoder/reassemble/reassemble.go +index 8844b2ab8fba303d74ada179ac81791afe63b37b..d8fc136b50438fa35fedcd4cfc064add0e5093df 100644 +--- OP/op-node/cmd/batch_decoder/reassemble/reassemble.go ++++ CELO/op-node/cmd/batch_decoder/reassemble/reassemble.go +@@ -72,7 +72,7 @@ for _, frame := range frames { + framesByChannel[frame.Frame.ID] = append(framesByChannel[frame.Frame.ID], frame) + } + for id, frames := range framesByChannel { +- ch := processFrames(config, rollupCfg, id, frames) ++ ch := ProcessFrames(config, rollupCfg, id, frames) + filename := path.Join(config.OutDirectory, fmt.Sprintf("%s.json", id.String())) + if err := writeChannel(ch, filename); err != nil { + log.Fatal(err) +@@ -90,7 +90,9 @@ enc := json.NewEncoder(file) + return enc.Encode(ch) + } +  +-func processFrames(cfg Config, rollupCfg *rollup.Config, id derive.ChannelID, frames []FrameWithMetadata) ChannelWithMetadata { ++// ProcessFrames processes the frames for a given channel and reads batches and other relevant metadata ++// from the channel. Returns a ChannelWithMetadata struct containing all the relevant data. ++func ProcessFrames(cfg Config, rollupCfg *rollup.Config, id derive.ChannelID, frames []FrameWithMetadata) ChannelWithMetadata { + spec := rollup.NewChainSpec(rollupCfg) + ch := derive.NewChannel(id, eth.L1BlockRef{Number: frames[0].InclusionBlock}) + invalidFrame := false
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+1
+
-1
+ +
+ +
+
+
diff --git OP/op-program/client/l2/engine_backend_test.go CELO/op-program/client/l2/engine_backend_test.go +index 63eeba9285f9fa1883a3e788ac119e6d5fea475b..427f256d0a459fd01c6b56a3a81215ad87094c45 100644 +--- OP/op-program/client/l2/engine_backend_test.go ++++ CELO/op-program/client/l2/engine_backend_test.go +@@ -312,7 +312,7 @@ deployConfig.L2GenesisEcotoneTimeOffset = &ts + } + l1Genesis, err := genesis.NewL1Genesis(deployConfig) + require.NoError(t, err) +- l2Genesis, err := genesis.NewL2Genesis(deployConfig, l1Genesis.ToBlock()) ++ l2Genesis, err := genesis.NewL2Genesis(deployConfig, l1Genesis.ToBlock().Header()) + require.NoError(t, err) +  + l2Genesis.Alloc[fundedAddress] = types.Account{
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+2
+
-3
+ +
+ +
+
+
diff --git OP/op-program/host/config/config.go CELO/op-program/host/config/config.go +index dd9a2dff15ca720304c09e85a480b0cd41de7749..c04f959a8b7defadb0a5e835b2414956823aa29e 100644 +--- OP/op-program/host/config/config.go ++++ CELO/op-program/host/config/config.go +@@ -113,8 +113,7 @@ return nil + } +  + func (c *Config) FetchingEnabled() bool { +- // TODO: Include Beacon URL once cancun is active on all chains we fault prove. +- return c.L1URL != "" && c.L2URL != "" ++ return c.L1URL != "" && c.L2URL != "" && c.L1BeaconURL != "" + } +  + // NewConfig creates a Config with all optional values set to the CLI default value +@@ -139,7 +138,7 @@ L2Claim: l2Claim, + L2ClaimBlockNumber: l2ClaimBlockNum, + L1RPCKind: sources.RPCKindStandard, + IsCustomChainConfig: isCustomConfig, +- DataFormat: types.DataFormatFile, ++ DataFormat: types.DataFormatDirectory, + } + } +
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+2
+
-1
+ +
+ +
+
+
diff --git OP/op-program/host/config/config_test.go CELO/op-program/host/config/config_test.go +index b9aaccc65416c2579fa5913b988f30a28be4d1c2..e9cc54edd6a68a14d52684932c5b07682dda4432 100644 +--- OP/op-program/host/config/config_test.go ++++ CELO/op-program/host/config/config_test.go +@@ -140,7 +140,8 @@ + t.Run("FetchingEnabledWhenBothFetcherUrlsSpecified", func(t *testing.T) { + cfg := validConfig() + cfg.L1URL = "https://example.com:1234" +- cfg.L2URL = "https://example.com:5678" ++ cfg.L1BeaconURL = "https://example.com:5678" ++ cfg.L2URL = "https://example.com:91011" + require.True(t, cfg.FetchingEnabled(), "Should enable fetching when node URL supplied") + }) + }
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+1
+
-1
+ +
+ +
+
+
diff --git OP/op-program/host/flags/flags.go CELO/op-program/host/flags/flags.go +index c46422876d63fec3d485d2b43576469ac5371cbf..5eb633c7202f55bf202db245d8c2b28ea8d3cab0 100644 +--- OP/op-program/host/flags/flags.go ++++ CELO/op-program/host/flags/flags.go +@@ -40,7 +40,7 @@ DataFormat = &cli.StringFlag{ + Name: "data.format", + Usage: fmt.Sprintf("Format to use for preimage data storage. Available formats: %s", openum.EnumString(types.SupportedDataFormats)), + EnvVars: prefixEnvVars("DATA_FORMAT"), +- Value: string(types.DataFormatFile), ++ Value: string(types.DataFormatDirectory), + } + L2NodeAddr = &cli.StringFlag{ + Name: "l2",
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+45
+
-19
+ +
+ +
+
+
diff --git OP/op-program/host/host.go CELO/op-program/host/host.go +index a2ee245adede18155625ab0165d874c5e88705cc..a60e451b972d4588361137a0a42f2675001a4c93 100644 +--- OP/op-program/host/host.go ++++ CELO/op-program/host/host.go +@@ -16,7 +16,6 @@ "github.com/ethereum-optimism/optimism/op-program/host/config" + "github.com/ethereum-optimism/optimism/op-program/host/flags" + "github.com/ethereum-optimism/optimism/op-program/host/kvstore" + "github.com/ethereum-optimism/optimism/op-program/host/prefetcher" +- "github.com/ethereum-optimism/optimism/op-program/host/types" + opservice "github.com/ethereum-optimism/optimism/op-service" + "github.com/ethereum-optimism/optimism/op-service/client" + "github.com/ethereum-optimism/optimism/op-service/ctxinterrupt" +@@ -30,6 +29,24 @@ *L2Client + *sources.DebugClient + } +  ++type Prefetcher interface { ++ Hint(hint string) error ++ GetPreimage(ctx context.Context, key common.Hash) ([]byte, error) ++} ++type PrefetcherCreator func(ctx context.Context, logger log.Logger, kv kvstore.KV, cfg *config.Config) (Prefetcher, error) ++ ++type creatorsCfg struct { ++ prefetcher PrefetcherCreator ++} ++ ++type ProgramOpt func(c *creatorsCfg) ++ ++func WithPrefetcher(creator PrefetcherCreator) ProgramOpt { ++ return func(c *creatorsCfg) { ++ c.prefetcher = creator ++ } ++} ++ + func Main(logger log.Logger, cfg *config.Config) error { + if err := cfg.Check(); err != nil { + return fmt.Errorf("invalid config: %w", err) +@@ -43,7 +60,7 @@ ctx := ctxinterrupt.WithCancelOnInterrupt(hostCtx) + if cfg.ServerMode { + preimageChan := preimage.ClientPreimageChannel() + hinterChan := preimage.ClientHinterChannel() +- return PreimageServer(ctx, logger, cfg, preimageChan, hinterChan) ++ return PreimageServer(ctx, logger, cfg, preimageChan, hinterChan, makeDefaultPrefetcher) + } +  + if err := FaultProofProgram(ctx, logger, cfg); err != nil { +@@ -54,7 +71,13 @@ return nil + } +  + // FaultProofProgram is the programmatic entry-point for the fault proof program +-func FaultProofProgram(ctx context.Context, logger log.Logger, cfg *config.Config) error { ++func FaultProofProgram(ctx context.Context, logger log.Logger, cfg *config.Config, opts ...ProgramOpt) error { ++ creators := &creatorsCfg{ ++ prefetcher: makeDefaultPrefetcher, ++ } ++ for _, opt := range opts { ++ opt(creators) ++ } + var ( + serverErr chan error + pClientRW preimage.FileChannel +@@ -91,7 +114,7 @@ // Use a channel to receive the server result so we can wait for it to complete before returning + serverErr = make(chan error) + go func() { + defer close(serverErr) +- serverErr <- PreimageServer(ctx, logger, cfg, pHostRW, hHostRW) ++ serverErr <- PreimageServer(ctx, logger, cfg, pHostRW, hHostRW, creators.prefetcher) + }() +  + var cmd *exec.Cmd +@@ -123,7 +146,7 @@ // PreimageServer reads hints and preimage requests from the provided channels and processes those requests. + // This method will block until both the hinter and preimage handlers complete. + // If either returns an error both handlers are stopped. + // The supplied preimageChannel and hintChannel will be closed before this function returns. +-func PreimageServer(ctx context.Context, logger log.Logger, cfg *config.Config, preimageChannel preimage.FileChannel, hintChannel preimage.FileChannel) error { ++func PreimageServer(ctx context.Context, logger log.Logger, cfg *config.Config, preimageChannel preimage.FileChannel, hintChannel preimage.FileChannel, prefetcherCreator PrefetcherCreator) error { + var serverDone chan error + var hinterDone chan error + logger.Info("Starting preimage server") +@@ -151,29 +174,25 @@ if cfg.DataDir == "" { + logger.Info("Using in-memory storage") + kv = kvstore.NewMemKV() + } else { +- logger.Info("Creating disk storage", "datadir", cfg.DataDir, "format", cfg.DataFormat) + if err := os.MkdirAll(cfg.DataDir, 0755); err != nil { + return fmt.Errorf("creating datadir: %w", err) + } +- switch cfg.DataFormat { +- case types.DataFormatFile: +- kv = kvstore.NewFileKV(cfg.DataDir) +- case types.DataFormatPebble: +- kv = kvstore.NewPebbleKV(cfg.DataDir) +- default: +- return fmt.Errorf("invalid data format: %s", cfg.DataFormat) ++ store, err := kvstore.NewDiskKV(logger, cfg.DataDir, cfg.DataFormat) ++ if err != nil { ++ return fmt.Errorf("creating kvstore: %w", err) + } ++ kv = store + } +  + var ( + getPreimage kvstore.PreimageSource + hinter preimage.HintHandler + ) +- if cfg.FetchingEnabled() { +- prefetch, err := makePrefetcher(ctx, logger, kv, cfg) +- if err != nil { +- return fmt.Errorf("failed to create prefetcher: %w", err) +- } ++ prefetch, err := prefetcherCreator(ctx, logger, kv, cfg) ++ if err != nil { ++ return fmt.Errorf("failed to create prefetcher: %w", err) ++ } ++ if prefetch != nil { + getPreimage = func(key common.Hash) ([]byte, error) { return prefetch.GetPreimage(ctx, key) } + hinter = prefetch.Hint + } else { +@@ -198,11 +217,18 @@ case err := <-hinterDone: + return err + case <-ctx.Done(): + logger.Info("Shutting down") ++ if errors.Is(ctx.Err(), context.Canceled) { ++ // We were asked to shutdown by the context being cancelled so don't treat it as an error condition. ++ return nil ++ } + return ctx.Err() + } + } +  +-func makePrefetcher(ctx context.Context, logger log.Logger, kv kvstore.KV, cfg *config.Config) (*prefetcher.Prefetcher, error) { ++func makeDefaultPrefetcher(ctx context.Context, logger log.Logger, kv kvstore.KV, cfg *config.Config) (Prefetcher, error) { ++ if !cfg.FetchingEnabled() { ++ return nil, nil ++ } + logger.Info("Connecting to L1 node", "l1", cfg.L1URL) + l1RPC, err := client.NewRPC(ctx, logger, cfg.L1URL, client.WithDialBackoff(10)) + if err != nil {
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+1
+
-1
+ +
+ +
+
+
diff --git OP/op-program/host/host_test.go CELO/op-program/host/host_test.go +index 9dddfe689cfcd2ff8aae415b0d1580470e0f4897..c5d63e17ab34e60401b3e28f2b74f2a3efe69043 100644 +--- OP/op-program/host/host_test.go ++++ CELO/op-program/host/host_test.go +@@ -37,7 +37,7 @@ defer hintClient.Close() + logger := testlog.Logger(t, log.LevelTrace) + result := make(chan error) + go func() { +- result <- PreimageServer(context.Background(), logger, cfg, preimageServer, hintServer) ++ result <- PreimageServer(context.Background(), logger, cfg, preimageServer, hintServer, makeDefaultPrefetcher) + }() +  + pClient := preimage.NewOracleClient(preimageClient)
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+86
+
-0
+ +
+ +
+
+
diff --git OP/op-program/host/kvstore/directory.go CELO/op-program/host/kvstore/directory.go +new file mode 100644 +index 0000000000000000000000000000000000000000..4176a6453d64e4d16da517dd9beaf1522615f543 +--- /dev/null ++++ CELO/op-program/host/kvstore/directory.go +@@ -0,0 +1,86 @@ ++package kvstore ++ ++import ( ++ "encoding/hex" ++ "errors" ++ "fmt" ++ "io" ++ "os" ++ "path" ++ "sync" ++ ++ "github.com/ethereum/go-ethereum/common" ++) ++ ++// directoryKV is a disk-backed key-value store, every key-value pair is a hex-encoded .txt file, with the value as content. ++// directoryKV is safe for concurrent use with a single directoryKV instance. ++// directoryKV is safe for concurrent use between different directoryKV instances of the same disk directory as long as the ++// file system supports atomic renames. ++type directoryKV struct { ++ sync.RWMutex ++ path string ++} ++ ++// newDirectoryKV creates a directoryKV that puts/gets pre-images as files in the given directory path. ++// The path must exist, or subsequent Put/Get calls will error when it does not. ++func newDirectoryKV(path string) *directoryKV { ++ return &directoryKV{path: path} ++} ++ ++// pathKey returns the file path for the given key. ++// This is composed of the first characters of the non-0x-prefixed hex key as a directory, and the rest as the file name. ++func (d *directoryKV) pathKey(k common.Hash) string { ++ key := k.String() ++ dir, name := key[2:6], key[6:] ++ return path.Join(d.path, dir, name+".txt") ++} ++ ++func (d *directoryKV) Put(k common.Hash, v []byte) error { ++ d.Lock() ++ defer d.Unlock() ++ f, err := openTempFile(d.path, k.String()+".txt.*") ++ if err != nil { ++ return fmt.Errorf("failed to open temp file for pre-image %s: %w", k, err) ++ } ++ defer os.Remove(f.Name()) // Clean up the temp file if it doesn't actually get moved into place ++ if _, err := f.Write([]byte(hex.EncodeToString(v))); err != nil { ++ _ = f.Close() ++ return fmt.Errorf("failed to write pre-image %s to disk: %w", k, err) ++ } ++ if err := f.Close(); err != nil { ++ return fmt.Errorf("failed to close temp pre-image %s file: %w", k, err) ++ } ++ ++ targetFile := d.pathKey(k) ++ if err := os.MkdirAll(path.Dir(targetFile), 0777); err != nil { ++ return fmt.Errorf("failed to create parent directory for pre-image %s: %w", f.Name(), err) ++ } ++ if err := os.Rename(f.Name(), targetFile); err != nil { ++ return fmt.Errorf("failed to move temp file %v to final destination %v: %w", f.Name(), targetFile, err) ++ } ++ return nil ++} ++ ++func (d *directoryKV) Get(k common.Hash) ([]byte, error) { ++ d.RLock() ++ defer d.RUnlock() ++ f, err := os.OpenFile(d.pathKey(k), os.O_RDONLY, filePermission) ++ if err != nil { ++ if errors.Is(err, os.ErrNotExist) { ++ return nil, ErrNotFound ++ } ++ return nil, fmt.Errorf("failed to open pre-image file %s: %w", k, err) ++ } ++ defer f.Close() // fine to ignore closing error here ++ dat, err := io.ReadAll(f) ++ if err != nil { ++ return nil, fmt.Errorf("failed to read pre-image from file %s: %w", k, err) ++ } ++ return hex.DecodeString(string(dat)) ++} ++ ++func (d *directoryKV) Close() error { ++ return nil ++} ++ ++var _ KV = (*directoryKV)(nil)
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+28
+
-0
+ +
+ +
+
+
diff --git OP/op-program/host/kvstore/directory_test.go CELO/op-program/host/kvstore/directory_test.go +new file mode 100644 +index 0000000000000000000000000000000000000000..0a76f5843b539aa8550a48f8f19060de092947f7 +--- /dev/null ++++ CELO/op-program/host/kvstore/directory_test.go +@@ -0,0 +1,28 @@ ++package kvstore ++ ++import ( ++ "path/filepath" ++ "testing" ++ ++ "github.com/ethereum/go-ethereum/crypto" ++ "github.com/stretchr/testify/require" ++) ++ ++func TestDirectoryKV(t *testing.T) { ++ tmp := t.TempDir() // automatically removed by testing cleanup ++ kv := newDirectoryKV(tmp) ++ t.Cleanup(func() { // Can't use defer because kvTest runs tests in parallel. ++ require.NoError(t, kv.Close()) ++ }) ++ kvTest(t, kv) ++} ++ ++func TestDirectoryKV_CreateMissingDirectory(t *testing.T) { ++ tmp := t.TempDir() ++ dir := filepath.Join(tmp, "data") ++ kv := newDirectoryKV(dir) ++ defer kv.Close() ++ val := []byte{1, 2, 3, 4} ++ key := crypto.Keccak256Hash(val) ++ require.NoError(t, kv.Put(key, val)) ++}
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+12
+
-12
+ +
+ +
+
+
diff --git OP/op-program/host/kvstore/file.go CELO/op-program/host/kvstore/file.go +index 353bcedfe7c4e6b4997563bb99af805f91a65fd2..9116f83df720e1795a9618bfb482fd279a7554e7 100644 +--- OP/op-program/host/kvstore/file.go ++++ CELO/op-program/host/kvstore/file.go +@@ -15,26 +15,26 @@ + // read/write mode for user/group/other, not executable. + const filePermission = 0666 +  +-// FileKV is a disk-backed key-value store, every key-value pair is a hex-encoded .txt file, with the value as content. +-// FileKV is safe for concurrent use with a single FileKV instance. +-// FileKV is safe for concurrent use between different FileKV instances of the same disk directory as long as the ++// fileKV is a disk-backed key-value store, every key-value pair is a hex-encoded .txt file, with the value as content. ++// fileKV is safe for concurrent use with a single fileKV instance. ++// fileKV is safe for concurrent use between different fileKV instances of the same disk directory as long as the + // file system supports atomic renames. +-type FileKV struct { ++type fileKV struct { + sync.RWMutex + path string + } +  +-// NewFileKV creates a FileKV that puts/gets pre-images as files in the given directory path. ++// newFileKV creates a fileKV that puts/gets pre-images as files in the given directory path. + // The path must exist, or subsequent Put/Get calls will error when it does not. +-func NewFileKV(path string) *FileKV { +- return &FileKV{path: path} ++func newFileKV(path string) *fileKV { ++ return &fileKV{path: path} + } +  +-func (d *FileKV) pathKey(k common.Hash) string { ++func (d *fileKV) pathKey(k common.Hash) string { + return path.Join(d.path, k.String()+".txt") + } +  +-func (d *FileKV) Put(k common.Hash, v []byte) error { ++func (d *fileKV) Put(k common.Hash, v []byte) error { + d.Lock() + defer d.Unlock() + f, err := openTempFile(d.path, k.String()+".txt.*") +@@ -72,7 +72,7 @@ } + return f, nil + } +  +-func (d *FileKV) Get(k common.Hash) ([]byte, error) { ++func (d *fileKV) Get(k common.Hash) ([]byte, error) { + d.RLock() + defer d.RUnlock() + f, err := os.OpenFile(d.pathKey(k), os.O_RDONLY, filePermission) +@@ -90,8 +90,8 @@ } + return hex.DecodeString(string(dat)) + } +  +-func (d *FileKV) Close() error { ++func (d *fileKV) Close() error { + return nil + } +  +-var _ KV = (*FileKV)(nil) ++var _ KV = (*fileKV)(nil)
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+4
+
-4
+ +
+ +
+
+
diff --git OP/op-program/host/kvstore/file_test.go CELO/op-program/host/kvstore/file_test.go +index b30517db2faaadb3c1455c74eb8be4ea13fb6656..cb96039bc2ceb6921daa625157bb2fb3bbe51a3b 100644 +--- OP/op-program/host/kvstore/file_test.go ++++ CELO/op-program/host/kvstore/file_test.go +@@ -8,19 +8,19 @@ "github.com/ethereum/go-ethereum/crypto" + "github.com/stretchr/testify/require" + ) +  +-func TestDiskKV(t *testing.T) { ++func TestFileKV(t *testing.T) { + tmp := t.TempDir() // automatically removed by testing cleanup +- kv := NewFileKV(tmp) ++ kv := newFileKV(tmp) + t.Cleanup(func() { // Can't use defer because kvTest runs tests in parallel. + require.NoError(t, kv.Close()) + }) + kvTest(t, kv) + } +  +-func TestCreateMissingDirectory(t *testing.T) { ++func TestFileKV_CreateMissingDirectory(t *testing.T) { + tmp := t.TempDir() + dir := filepath.Join(tmp, "data") +- kv := NewFileKV(dir) ++ kv := newFileKV(dir) + defer kv.Close() + val := []byte{1, 2, 3, 4} + key := crypto.Keccak256Hash(val)
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+69
+
-0
+ +
+ +
+
+
diff --git OP/op-program/host/kvstore/format.go CELO/op-program/host/kvstore/format.go +new file mode 100644 +index 0000000000000000000000000000000000000000..08cbc1b18c5dc6a4a28dbe215785cd11892dca36 +--- /dev/null ++++ CELO/op-program/host/kvstore/format.go +@@ -0,0 +1,69 @@ ++package kvstore ++ ++import ( ++ "errors" ++ "fmt" ++ "os" ++ "path/filepath" ++ "slices" ++ ++ "github.com/ethereum-optimism/optimism/op-program/host/types" ++ "github.com/ethereum/go-ethereum/log" ++) ++ ++const formatFilename = "kvformat" ++ ++var ( ++ ErrFormatUnavailable = errors.New("format unavailable") ++ ErrUnsupportedFormat = errors.New("unsupported format") ++) ++ ++func recordKVFormat(dir string, format types.DataFormat) error { ++ return os.WriteFile(filepath.Join(dir, formatFilename), []byte(format), 0o644) ++} ++ ++func readKVFormat(dir string) (types.DataFormat, error) { ++ data, err := os.ReadFile(filepath.Join(dir, formatFilename)) ++ if errors.Is(err, os.ErrNotExist) { ++ return "", ErrFormatUnavailable ++ } else if err != nil { ++ return "", fmt.Errorf("failed to read kv format: %w", err) ++ } ++ format := types.DataFormat(data) ++ if !slices.Contains(types.SupportedDataFormats, format) { ++ return "", fmt.Errorf("%w: %s", ErrUnsupportedFormat, format) ++ } ++ return format, nil ++} ++ ++// NewDiskKV creates a new KV implementation. If the specified directly contains an existing KV store ++// that has the format recorded, the recorded format is used ensuring compatibility with the existing data. ++// If the directory does not contain existing data or doesn't have the format recorded, defaultFormat is used ++// which may result in the existing data being unused. ++// If the existing data records a format that is not supported, an error is returned. ++// The format is automatically recorded if it wasn't previously stored. ++func NewDiskKV(logger log.Logger, dir string, defaultFormat types.DataFormat) (KV, error) { ++ format, err := readKVFormat(dir) ++ if errors.Is(err, ErrFormatUnavailable) { ++ format = defaultFormat ++ logger.Info("Creating disk storage", "datadir", dir, "format", format) ++ if err := recordKVFormat(dir, format); err != nil { ++ return nil, fmt.Errorf("failed to record new kv store format: %w", err) ++ } ++ } else if err != nil { ++ return nil, err ++ } else { ++ logger.Info("Using existing disk storage", "datadir", dir, "format", format) ++ } ++ ++ switch format { ++ case types.DataFormatFile: ++ return newFileKV(dir), nil ++ case types.DataFormatDirectory: ++ return newDirectoryKV(dir), nil ++ case types.DataFormatPebble: ++ return newPebbleKV(dir), nil ++ default: ++ return nil, fmt.Errorf("invalid data format: %s", format) ++ } ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+66
+
-0
+ +
+ +
+
+
diff --git OP/op-program/host/kvstore/format_test.go CELO/op-program/host/kvstore/format_test.go +new file mode 100644 +index 0000000000000000000000000000000000000000..8be0368bd09c4e9a2f55cd2da209fc7488a76727 +--- /dev/null ++++ CELO/op-program/host/kvstore/format_test.go +@@ -0,0 +1,66 @@ ++package kvstore ++ ++import ( ++ "fmt" ++ "testing" ++ ++ "github.com/ethereum-optimism/optimism/op-program/host/types" ++ "github.com/ethereum-optimism/optimism/op-service/testlog" ++ "github.com/ethereum/go-ethereum/common" ++ "github.com/ethereum/go-ethereum/log" ++ "github.com/stretchr/testify/require" ++) ++ ++func TestRecordAndReadKVFormat(t *testing.T) { ++ for _, format := range types.SupportedDataFormats { ++ format := format ++ t.Run(string(format), func(t *testing.T) { ++ dir := t.TempDir() ++ require.NoError(t, recordKVFormat(dir, format)) ++ actual, err := readKVFormat(dir) ++ require.NoError(t, err) ++ require.Equal(t, format, actual) ++ }) ++ } ++ ++ t.Run("Unsupported", func(t *testing.T) { ++ dir := t.TempDir() ++ require.NoError(t, recordKVFormat(dir, "nope")) ++ _, err := readKVFormat(dir) ++ require.ErrorIs(t, err, ErrUnsupportedFormat) ++ }) ++ ++ t.Run("NotRecorded", func(t *testing.T) { ++ dir := t.TempDir() ++ _, err := readKVFormat(dir) ++ require.ErrorIs(t, err, ErrFormatUnavailable) ++ }) ++} ++ ++func TestNewDiskKV(t *testing.T) { ++ for _, existingFormat := range types.SupportedDataFormats { ++ existingFormat := existingFormat ++ ++ for _, specifiedFormat := range types.SupportedDataFormats { ++ specifiedFormat := specifiedFormat ++ t.Run(fmt.Sprintf("%v->%v", existingFormat, specifiedFormat), func(t *testing.T) { ++ dir := t.TempDir() ++ logger := testlog.Logger(t, log.LevelError) ++ hash := common.Hash{0xaa} ++ value := []byte{1, 2, 3, 4, 5, 6} ++ kv1, err := NewDiskKV(logger, dir, existingFormat) ++ require.NoError(t, err) ++ require.NoError(t, kv1.Put(hash, value)) ++ require.NoError(t, kv1.Close()) ++ ++ // Should use existing format ++ kv2, err := NewDiskKV(logger, dir, specifiedFormat) ++ require.NoError(t, err) ++ actual, err := kv2.Get(hash) ++ require.NoError(t, err) ++ require.Equal(t, value, actual) ++ require.NoError(t, kv2.Close()) ++ }) ++ } ++ } ++}
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+11
+
-11
+ +
+ +
+
+
diff --git OP/op-program/host/kvstore/pebble.go CELO/op-program/host/kvstore/pebble.go +index 1276fa6b7ef7b78f12dbb1935ae79e845562b690..5bc7fcc9f23a716aea93769142817a9fc6132782 100644 +--- OP/op-program/host/kvstore/pebble.go ++++ CELO/op-program/host/kvstore/pebble.go +@@ -10,16 +10,16 @@ "github.com/cockroachdb/pebble" + "github.com/ethereum/go-ethereum/common" + ) +  +-// PebbleKV is a disk-backed key-value store, with PebbleDB as the underlying DBMS. +-// PebbleKV is safe for concurrent use with a single PebbleKV instance. +-type PebbleKV struct { ++// pebbleKV is a disk-backed key-value store, with PebbleDB as the underlying DBMS. ++// pebbleKV is safe for concurrent use with a single pebbleKV instance. ++type pebbleKV struct { + sync.RWMutex + db *pebble.DB + } +  +-// NewPebbleKV creates a PebbleKV that puts/gets pre-images as files in the given directory path. ++// newPebbleKV creates a pebbleKV that puts/gets pre-images as files in the given directory path. + // The path must exist, or subsequent Put/Get calls will error when it does not. +-func NewPebbleKV(path string) *PebbleKV { ++func newPebbleKV(path string) *pebbleKV { + opts := &pebble.Options{ + Cache: pebble.NewCache(int64(32 * 1024 * 1024)), + MaxConcurrentCompactions: runtime.NumCPU, +@@ -32,16 +32,16 @@ if err != nil { + panic(fmt.Errorf("failed to open pebbledb at %s: %w", path, err)) + } +  +- return &PebbleKV{db: db} ++ return &pebbleKV{db: db} + } +  +-func (d *PebbleKV) Put(k common.Hash, v []byte) error { ++func (d *pebbleKV) Put(k common.Hash, v []byte) error { + d.Lock() + defer d.Unlock() +- return d.db.Set(k.Bytes(), v, pebble.Sync) ++ return d.db.Set(k.Bytes(), v, pebble.NoSync) + } +  +-func (d *PebbleKV) Get(k common.Hash) ([]byte, error) { ++func (d *pebbleKV) Get(k common.Hash) ([]byte, error) { + d.RLock() + defer d.RUnlock() +  +@@ -58,11 +58,11 @@ closer.Close() + return ret, nil + } +  +-func (d *PebbleKV) Close() error { ++func (d *pebbleKV) Close() error { + d.Lock() + defer d.Unlock() +  + return d.db.Close() + } +  +-var _ KV = (*PebbleKV)(nil) ++var _ KV = (*pebbleKV)(nil)
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+2
+
-2
+ +
+ +
+
+
diff --git OP/op-program/host/kvstore/pebble_test.go CELO/op-program/host/kvstore/pebble_test.go +index 28aab0c5824881e9c9506ab716ae3f47b6789a68..e009d67970217ec4cc32a61624c8855db25b71ae 100644 +--- OP/op-program/host/kvstore/pebble_test.go ++++ CELO/op-program/host/kvstore/pebble_test.go +@@ -10,7 +10,7 @@ ) +  + func TestPebbleKV(t *testing.T) { + tmp := t.TempDir() // automatically removed by testing cleanup +- kv := NewPebbleKV(tmp) ++ kv := newPebbleKV(tmp) + t.Cleanup(func() { // Can't use defer because kvTest runs tests in parallel. + require.NoError(t, kv.Close()) + }) +@@ -20,7 +20,7 @@ + func TestPebbleKV_CreateMissingDirectory(t *testing.T) { + tmp := t.TempDir() + dir := filepath.Join(tmp, "data") +- kv := NewPebbleKV(dir) ++ kv := newPebbleKV(dir) + defer kv.Close() + val := []byte{1, 2, 3, 4} + key := crypto.Keccak256Hash(val)
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+4
+
-3
+ +
+ +
+
+
diff --git OP/op-program/host/types/types.go CELO/op-program/host/types/types.go +index 104dafe2dbc449586a7a254e59006617454e7804..7cb24b55f65db72fb660a6b762c0b45888226da0 100644 +--- OP/op-program/host/types/types.go ++++ CELO/op-program/host/types/types.go +@@ -3,8 +3,9 @@ + type DataFormat string +  + const ( +- DataFormatFile DataFormat = "file" +- DataFormatPebble DataFormat = "pebble" ++ DataFormatFile DataFormat = "file" ++ DataFormatDirectory DataFormat = "directory" ++ DataFormatPebble DataFormat = "pebble" + ) +  +-var SupportedDataFormats = []DataFormat{DataFormatFile, DataFormatPebble} ++var SupportedDataFormats = []DataFormat{DataFormatFile, DataFormatDirectory, DataFormatPebble}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+39
+
-0
+ +
+ +
+
+
diff --git OP/op-program/scripts/build-prestates.sh CELO/op-program/scripts/build-prestates.sh +new file mode 100755 +index 0000000000000000000000000000000000000000..5394c7a135e0514bcfb497cfb5a3bdd213f59e05 +--- /dev/null ++++ CELO/op-program/scripts/build-prestates.sh +@@ -0,0 +1,39 @@ ++#!/bin/bash ++set -euo pipefail ++SCRIPTS_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) ++ ++TMP_DIR=$(mktemp -d) ++function cleanup() { ++ rm -rf "${TMP_DIR}" ++} ++trap cleanup EXIT ++echo "Using temp dir: ${TMP_DIR}" ++cd "${TMP_DIR}" ++ ++# Need to check out a fresh copy of the monorepo so we can switch to specific tags without it also affecting the ++# contents of this script (which is checked into the repo). ++git clone https://github.com/ethereum-optimism/optimism --recurse-submodules ++ ++STATES_DIR="${SCRIPTS_DIR}/../temp/states" ++LOGS_DIR="${SCRIPTS_DIR}/../temp/logs" ++REPO_DIR="${TMP_DIR}/optimism" ++BIN_DIR="${REPO_DIR}/op-program/bin/" ++ ++mkdir -p "${STATES_DIR}" "${LOGS_DIR}" ++ ++cd "${REPO_DIR}" ++ ++VERSIONS=$(git tag | grep 'op-program\/v') ++ ++for VERSION in ${VERSIONS} ++do ++ LOG_FILE="${LOGS_DIR}/build-$(echo "${VERSION}" | cut -c 12-).txt" ++ echo "Building Version: ${VERSION} Logs: ${LOG_FILE}" ++ git checkout "${VERSION}" > "${LOG_FILE}" 2>&1 ++ make reproducible-prestate >> "${LOG_FILE}" 2>&1 ++ HASH=$(cat "${BIN_DIR}/prestate-proof.json" | jq -r .pre) ++ cp "${BIN_DIR}/prestate.json" "${STATES_DIR}/${HASH}.json" ++ echo "Built ${VERSION}: ${HASH}" ++done ++ ++echo "All prestates successfully built and available in ${STATES_DIR}"
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+84
+
-0
+ +
+ +
+
+
diff --git OP/op-service/client/lazy_dial.go CELO/op-service/client/lazy_dial.go +new file mode 100644 +index 0000000000000000000000000000000000000000..9064fbe1fe09d08347f7de97c1874c0389ee2f21 +--- /dev/null ++++ CELO/op-service/client/lazy_dial.go +@@ -0,0 +1,84 @@ ++package client ++ ++import ( ++ "context" ++ "errors" ++ "fmt" ++ "sync" ++ ++ "github.com/ethereum/go-ethereum" ++ "github.com/ethereum/go-ethereum/rpc" ++) ++ ++// LazyRPC defers connection attempts to the usage of the RPC. ++// This allows a websocket connection to be established lazily. ++// The underlying RPC should handle reconnects. ++type LazyRPC struct { ++ // mutex to prevent more than one active dial attempt at a time. ++ mu sync.Mutex ++ // inner is the actual RPC client. ++ // It is initialized once. The underlying RPC handles reconnections. ++ inner RPC ++ // options to initialize `inner` with. ++ opts []rpc.ClientOption ++ endpoint string ++ // If we have not initialized `inner` yet, ++ // do not try to do so after closing the client. ++ closed bool ++} ++ ++var _ RPC = (*LazyRPC)(nil) ++ ++func NewLazyRPC(endpoint string, opts ...rpc.ClientOption) *LazyRPC { ++ return &LazyRPC{ ++ opts: opts, ++ endpoint: endpoint, ++ } ++} ++ ++func (l *LazyRPC) dial(ctx context.Context) error { ++ l.mu.Lock() ++ defer l.mu.Unlock() ++ if l.inner != nil { ++ return nil ++ } ++ if l.closed { ++ return errors.New("cannot dial RPC, client was already closed") ++ } ++ underlying, err := rpc.DialOptions(ctx, l.endpoint, l.opts...) ++ if err != nil { ++ return fmt.Errorf("failed to dial: %w", err) ++ } ++ l.inner = NewBaseRPCClient(underlying) ++ return nil ++} ++ ++func (l *LazyRPC) Close() { ++ l.mu.Lock() ++ defer l.mu.Unlock() ++ if l.inner != nil { ++ l.inner.Close() ++ } ++ l.closed = true ++} ++ ++func (l *LazyRPC) CallContext(ctx context.Context, result any, method string, args ...any) error { ++ if err := l.dial(ctx); err != nil { ++ return err ++ } ++ return l.inner.CallContext(ctx, result, method, args...) ++} ++ ++func (l *LazyRPC) BatchCallContext(ctx context.Context, b []rpc.BatchElem) error { ++ if err := l.dial(ctx); err != nil { ++ return err ++ } ++ return l.inner.BatchCallContext(ctx, b) ++} ++ ++func (l *LazyRPC) EthSubscribe(ctx context.Context, channel any, args ...any) (ethereum.Subscription, error) { ++ if err := l.dial(ctx); err != nil { ++ return nil, err ++ } ++ return l.inner.EthSubscribe(ctx, channel, args...) ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+66
+
-0
+ +
+ +
+
+
diff --git OP/op-service/client/lazy_dial_test.go CELO/op-service/client/lazy_dial_test.go +new file mode 100644 +index 0000000000000000000000000000000000000000..79608dc2b236ffcf29007c0af86576941bf35f45 +--- /dev/null ++++ CELO/op-service/client/lazy_dial_test.go +@@ -0,0 +1,66 @@ ++package client ++ ++import ( ++ "context" ++ "net" ++ "net/http" ++ "testing" ++ "time" ++ ++ "github.com/stretchr/testify/require" ++ ++ "github.com/ethereum/go-ethereum/node" ++ "github.com/ethereum/go-ethereum/rpc" ++) ++ ++type mockServer struct { ++ count int ++} ++ ++func (m *mockServer) Count() { ++ m.count += 1 ++} ++ ++func TestLazyRPC(t *testing.T) { ++ listener, err := net.Listen("tcp", "127.0.0.1:0") ++ require.NoError(t, err) ++ defer listener.Close() ++ ++ addr := listener.Addr().String() ++ ++ cl := NewLazyRPC("ws://" + addr) ++ defer cl.Close() ++ ++ // At this point the connection is online, but the RPC is not. ++ // RPC request attempts should fail. ++ { ++ ctx, cancel := context.WithTimeout(context.Background(), time.Second*4) ++ attempt1Err := cl.CallContext(ctx, nil, "foo_count") ++ cancel() ++ require.ErrorContains(t, attempt1Err, "i/o timeout") ++ require.NotNil(t, ctx.Err()) ++ } ++ ++ // Now let's serve a websocket RPC ++ rpcSrv := rpc.NewServer() ++ defer rpcSrv.Stop() ++ wsHandler := rpcSrv.WebsocketHandler([]string{"*"}) ++ httpSrv := &http.Server{Handler: wsHandler} ++ defer httpSrv.Close() ++ ++ go func() { ++ _ = httpSrv.Serve(listener) // always non-nil, returned when server exits. ++ }() ++ ++ ms := &mockServer{} ++ require.NoError(t, node.RegisterApis([]rpc.API{{ ++ Namespace: "foo", ++ Service: ms, ++ }}, nil, rpcSrv)) ++ ++ // and see if the lazy-dial client can reach it ++ require.Equal(t, 0, ms.count) ++ attempt2Err := cl.CallContext(context.Background(), nil, "foo_count") ++ require.NoError(t, attempt2Err) ++ require.Equal(t, 1, ms.count) ++}
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+49
+
-9
+ +
+ +
+
+
diff --git OP/op-service/client/rpc.go CELO/op-service/client/rpc.go +index 0ec2f3896535f30d804342bfa717a828f1a3b851..8fb2d4d37b886c6b4fa0e0227468d131cc44a15f 100644 +--- OP/op-service/client/rpc.go ++++ CELO/op-service/client/rpc.go +@@ -35,10 +35,27 @@ httpPollInterval time.Duration + backoffAttempts int + limit float64 + burst int ++ lazy bool ++ callTimeout time.Duration ++ batchCallTimeout time.Duration + } +  + type RPCOption func(cfg *rpcConfig) error +  ++func WithCallTimeout(d time.Duration) RPCOption { ++ return func(cfg *rpcConfig) error { ++ cfg.callTimeout = d ++ return nil ++ } ++} ++ ++func WithBatchCallTimeout(d time.Duration) RPCOption { ++ return func(cfg *rpcConfig) error { ++ cfg.batchCallTimeout = d ++ return nil ++ } ++} ++ + // WithDialBackoff configures the number of attempts for the initial dial to the RPC, + // attempts are executed with an exponential backoff strategy. + func WithDialBackoff(attempts int) RPCOption { +@@ -74,6 +91,17 @@ return nil + } + } +  ++// WithLazyDial makes the RPC client initialization defer the initial connection attempt, ++// and defer to later RPC requests upon subsequent dial errors. ++// Any dial-backoff option will be ignored if this option is used. ++// This is implemented by wrapping the inner RPC client with a LazyRPC. ++func WithLazyDial() RPCOption { ++ return func(cfg *rpcConfig) error { ++ cfg.lazy = true ++ return nil ++ } ++} ++ + // NewRPC returns the correct client.RPC instance for a given RPC url. + func NewRPC(ctx context.Context, lgr log.Logger, addr string, opts ...RPCOption) (RPC, error) { + var cfg rpcConfig +@@ -86,13 +114,23 @@ + if cfg.backoffAttempts < 1 { // default to at least 1 attempt, or it always fails to dial. + cfg.backoffAttempts = 1 + } +- +- underlying, err := dialRPCClientWithBackoff(ctx, lgr, addr, cfg.backoffAttempts, cfg.gethRPCOptions...) +- if err != nil { +- return nil, err ++ if cfg.callTimeout == 0 { ++ cfg.callTimeout = 10 * time.Second ++ } ++ if cfg.batchCallTimeout == 0 { ++ cfg.batchCallTimeout = 20 * time.Second + } +  +- var wrapped RPC = &BaseRPCClient{c: underlying} ++ var wrapped RPC ++ if cfg.lazy { ++ wrapped = NewLazyRPC(addr, cfg.gethRPCOptions...) ++ } else { ++ underlying, err := dialRPCClientWithBackoff(ctx, lgr, addr, cfg.backoffAttempts, cfg.gethRPCOptions...) ++ if err != nil { ++ return nil, err ++ } ++ wrapped = &BaseRPCClient{c: underlying, callTimeout: cfg.callTimeout, batchCallTimeout: cfg.batchCallTimeout} ++ } +  + if cfg.limit != 0 { + wrapped = NewRateLimitingClient(wrapped, rate.Limit(cfg.limit), cfg.burst) +@@ -155,11 +193,13 @@ // BaseRPCClient is a wrapper around a concrete *rpc.Client instance to make it compliant + // with the client.RPC interface. + // It sets a timeout of 10s on CallContext & 20s on BatchCallContext made through it. + type BaseRPCClient struct { +- c *rpc.Client ++ c *rpc.Client ++ batchCallTimeout time.Duration ++ callTimeout time.Duration + } +  + func NewBaseRPCClient(c *rpc.Client) *BaseRPCClient { +- return &BaseRPCClient{c: c} ++ return &BaseRPCClient{c: c, callTimeout: 10 * time.Second, batchCallTimeout: 20 * time.Second} + } +  + func (b *BaseRPCClient) Close() { +@@ -167,13 +207,13 @@ b.c.Close() + } +  + func (b *BaseRPCClient) CallContext(ctx context.Context, result any, method string, args ...any) error { +- cCtx, cancel := context.WithTimeout(ctx, 10*time.Second) ++ cCtx, cancel := context.WithTimeout(ctx, b.callTimeout) + defer cancel() + return b.c.CallContext(cCtx, result, method, args...) + } +  + func (b *BaseRPCClient) BatchCallContext(ctx context.Context, batch []rpc.BatchElem) error { +- cCtx, cancel := context.WithTimeout(ctx, 20*time.Second) ++ cCtx, cancel := context.WithTimeout(ctx, b.batchCallTimeout) + defer cancel() + return b.c.BatchCallContext(cCtx, batch) + }
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+19
+
-0
+ +
+ +
+
+
diff --git OP/op-service/crypto/secrets.go CELO/op-service/crypto/secrets.go +new file mode 100644 +index 0000000000000000000000000000000000000000..410de63cb3ca8c402b601cc069c800fa23cd690a +--- /dev/null ++++ CELO/op-service/crypto/secrets.go +@@ -0,0 +1,19 @@ ++package crypto ++ ++import ( ++ "crypto/ecdsa" ++ ++ "github.com/ethereum/go-ethereum/common/hexutil" ++) ++ ++// EncodePrivKey encodes the given private key in 32 bytes ++func EncodePrivKey(priv *ecdsa.PrivateKey) hexutil.Bytes { ++ privkey := make([]byte, 32) ++ blob := priv.D.Bytes() ++ copy(privkey[32-len(blob):], blob) ++ return privkey ++} ++ ++func EncodePrivKeyToString(priv *ecdsa.PrivateKey) string { ++ return hexutil.Encode(EncodePrivKey(priv)) ++}
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+6
+
-0
+ +
+ +
+
+
diff --git OP/op-service/crypto/signature.go CELO/op-service/crypto/signature.go +index 0b0afc02ecef85ec6d7f0d40909433c2feb8805e..a6a7c1cc0d1e241e92c395244a2a5134118beebd 100644 +--- OP/op-service/crypto/signature.go ++++ CELO/op-service/crypto/signature.go +@@ -35,6 +35,12 @@ return tx.WithSignature(signer, signature) + } + } +  ++func SignerFnFromBind(fn bind.SignerFn) SignerFn { ++ return func(_ context.Context, address common.Address, tx *types.Transaction) (*types.Transaction, error) { ++ return fn(address, tx) ++ } ++} ++ + // SignerFn is a generic transaction signing function. It may be a remote signer so it takes a context. + // It also takes the address that should be used to sign the transaction with. + type SignerFn func(context.Context, common.Address, *types.Transaction) (*types.Transaction, error)
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+8
+
-7
+ +
+ +
+
+
diff --git OP/op-service/dial/active_l2_provider_test.go CELO/op-service/dial/active_l2_provider_test.go +index 31d5a6cc65217e605c342f2816e579bfa4dd0712..1533ab6849ff6213c5729edcea93983c7d52f291 100644 +--- OP/op-service/dial/active_l2_provider_test.go ++++ CELO/op-service/dial/active_l2_provider_test.go +@@ -2,6 +2,7 @@ package dial +  + import ( + "context" ++ "errors" + "fmt" + "testing" + "time" +@@ -204,7 +205,7 @@ firstSequencerUsed, err := rollupProvider.RollupClient(context.Background()) + require.NoError(t, err) + require.Same(t, primarySequencer, firstSequencerUsed) +  +- primarySequencer.ExpectSequencerActive(true, fmt.Errorf("a test error")) // error-out after that ++ primarySequencer.ExpectSequencerActive(true, errors.New("a test error")) // error-out after that + primarySequencer.MaybeClose() + secondarySequencer.ExpectSequencerActive(true, nil) + secondSequencerUsed, err := rollupProvider.RollupClient(context.Background()) +@@ -231,7 +232,7 @@ firstSequencerUsed, err := activeProvider.EthClient(context.Background()) + require.NoError(t, err) + require.Same(t, primaryEthClient, firstSequencerUsed) +  +- primarySequencer.ExpectSequencerActive(true, fmt.Errorf("a test error")) // error out after that ++ primarySequencer.ExpectSequencerActive(true, errors.New("a test error")) // error out after that + primarySequencer.MaybeClose() + primaryEthClient.MaybeClose() + secondarySequencer.ExpectSequencerActive(true, nil) +@@ -465,7 +466,7 @@ func TestRollupProvider_ConstructorErrorOnFirstSequencerOffline(t *testing.T) { + ept := setupEndpointProviderTest(t, 2) +  + // First sequencer is dead, second sequencer is active +- ept.rollupClients[0].ExpectSequencerActive(false, fmt.Errorf("I am offline")) ++ ept.rollupClients[0].ExpectSequencerActive(false, errors.New("I am offline")) + ept.rollupClients[0].MaybeClose() + ept.rollupClients[1].ExpectSequencerActive(true, nil) +  +@@ -482,7 +483,7 @@ func TestEndpointProvider_ConstructorErrorOnFirstSequencerOffline(t *testing.T) { + ept := setupEndpointProviderTest(t, 2) +  + // First sequencer is dead, second sequencer is active +- ept.rollupClients[0].ExpectSequencerActive(false, fmt.Errorf("I am offline")) ++ ept.rollupClients[0].ExpectSequencerActive(false, errors.New("I am offline")) + ept.rollupClients[0].MaybeClose() + ept.rollupClients[1].ExpectSequencerActive(true, nil) + ept.rollupClients[1].ExpectSequencerActive(true, nil) // see comment in other tests about why we expect this twice +@@ -533,7 +534,7 @@ ept := setupEndpointProviderTest(t, 2) +  + // All sequencers are inactive + for _, sequencer := range ept.rollupClients { +- sequencer.ExpectSequencerActive(true, fmt.Errorf("a test error")) ++ sequencer.ExpectSequencerActive(true, errors.New("a test error")) + sequencer.MaybeClose() + } +  +@@ -549,7 +550,7 @@ ept := setupEndpointProviderTest(t, 2) +  + // All sequencers are inactive + for _, sequencer := range ept.rollupClients { +- sequencer.ExpectSequencerActive(true, fmt.Errorf("a test error")) ++ sequencer.ExpectSequencerActive(true, errors.New("a test error")) + sequencer.MaybeClose() + } +  +@@ -711,7 +712,7 @@ rollupProvider, err := ept.newActiveL2RollupProvider(0) + require.NoError(t, err) +  + // primarySequencer goes down +- seq0.ExpectSequencerActive(false, fmt.Errorf("I'm offline now")) ++ seq0.ExpectSequencerActive(false, errors.New("I'm offline now")) + seq0.MaybeClose() + ept.setRollupDialOutcome(0, false) // primarySequencer fails to dial + // secondarySequencer is inactive, but online
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+3
+
-2
+ +
+ +
+
+
diff --git OP/op-service/eth/status.go CELO/op-service/eth/status.go +index 3baab5725f267ccf11ea24e2b94adf24f030bcf4..52e2e9c58cc4f01c0dd58a2082541edc408e27e3 100644 +--- OP/op-service/eth/status.go ++++ CELO/op-service/eth/status.go +@@ -1,18 +1,19 @@ + package eth +  + import ( ++ "errors" + "fmt" + ) +  + func ForkchoiceUpdateErr(payloadStatus PayloadStatusV1) error { + switch payloadStatus.Status { + case ExecutionSyncing: +- return fmt.Errorf("updated forkchoice, but node is syncing") ++ return errors.New("updated forkchoice, but node is syncing") + case ExecutionAccepted, ExecutionInvalidTerminalBlock, ExecutionInvalidBlockHash: + // ACCEPTED, INVALID_TERMINAL_BLOCK, INVALID_BLOCK_HASH are only for execution + return fmt.Errorf("unexpected %s status, could not update forkchoice", payloadStatus.Status) + case ExecutionInvalid: +- return fmt.Errorf("cannot update forkchoice, block is invalid") ++ return errors.New("cannot update forkchoice, block is invalid") + case ExecutionValid: + return nil + default:
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+7
+
-0
+ +
+ +
+
+
diff --git OP/op-service/eth/sync_status.go CELO/op-service/eth/sync_status.go +index e6dae130de7f3d5045d44e2e132ab8e0cfb79210..f9db1f672b8246664049ea42b349c0f6d285dea7 100644 +--- OP/op-service/eth/sync_status.go ++++ CELO/op-service/eth/sync_status.go +@@ -22,13 +22,20 @@ // UnsafeL2 is the absolute tip of the L2 chain, + // pointing to block data that has not been submitted to L1 yet. + // The sequencer is building this, and verifiers may also be ahead of the + // SafeL2 block if they sync blocks via p2p or other offchain sources. ++ // This is considered to only be local-unsafe post-interop, see CrossUnsafe for cross-L2 guarantees. + UnsafeL2 L2BlockRef `json:"unsafe_l2"` + // SafeL2 points to the L2 block that was derived from the L1 chain. + // This point may still reorg if the L1 chain reorgs. ++ // This is considered to be cross-safe post-interop, see LocalSafe to ignore cross-L2 guarantees. + SafeL2 L2BlockRef `json:"safe_l2"` + // FinalizedL2 points to the L2 block that was derived fully from + // finalized L1 information, thus irreversible. + FinalizedL2 L2BlockRef `json:"finalized_l2"` + // PendingSafeL2 points to the L2 block processed from the batch, but not consolidated to the safe block yet. + PendingSafeL2 L2BlockRef `json:"pending_safe_l2"` ++ // CrossUnsafeL2 is an unsafe L2 block, that has been verified to match cross-L2 dependencies. ++ // Pre-interop every unsafe L2 block is also cross-unsafe. ++ CrossUnsafeL2 L2BlockRef `json:"cross_unsafe_l2"` ++ // LocalSafeL2 is an L2 block derived from L1, not yet verified to have valid cross-L2 dependencies. ++ LocalSafeL2 L2BlockRef `json:"local_safe_l2"` + }
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+16
+
-1
+ +
+ +
+
+
diff --git OP/op-service/ioutil/atomic.go CELO/op-service/ioutil/atomic.go +index 7fc24d01900c1e85bc0b5c2086e8a42fa567d23b..3cc38c1e6d97b95987d55e44b751e7697b4b2f32 100644 +--- OP/op-service/ioutil/atomic.go ++++ CELO/op-service/ioutil/atomic.go +@@ -17,6 +17,17 @@ // The contents are initially written to a temporary file and only renamed into place when the writer is closed. + // NOTE: It's vital to check if an error is returned from Close() as it may indicate the file could not be renamed + // If path ends in .gz the contents written will be gzipped. + func NewAtomicWriterCompressed(path string, perm os.FileMode) (*AtomicWriter, error) { ++ return newAtomicWriter(path, perm, true) ++} ++ ++// NewAtomicWriter creates a io.WriteCloser that performs an atomic write. ++// The contents are initially written to a temporary file and only renamed into place when the writer is closed. ++// NOTE: It's vital to check if an error is returned from Close() as it may indicate the file could not be renamed ++func NewAtomicWriter(path string, perm os.FileMode) (*AtomicWriter, error) { ++ return newAtomicWriter(path, perm, false) ++} ++ ++func newAtomicWriter(path string, perm os.FileMode, compressByFileType bool) (*AtomicWriter, error) { + f, err := os.CreateTemp(filepath.Dir(path), filepath.Base(path)) + if err != nil { + return nil, err +@@ -25,10 +36,14 @@ if err := f.Chmod(perm); err != nil { + _ = f.Close() + return nil, err + } ++ out := io.WriteCloser(f) ++ if compressByFileType { ++ out = CompressByFileType(path, f) ++ } + return &AtomicWriter{ + dest: path, + temp: f.Name(), +- out: CompressByFileType(path, f), ++ out: out, + }, nil + } +
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+35
+
-1
+ +
+ +
+
+
diff --git OP/op-service/ioutil/atomic_test.go CELO/op-service/ioutil/atomic_test.go +index 46f2f19a5058050eef2c59b91231eb68324209ca..5d46911287a5ae206ec04020d0d6ecfeece1dda4 100644 +--- OP/op-service/ioutil/atomic_test.go ++++ CELO/op-service/ioutil/atomic_test.go +@@ -70,7 +70,7 @@ require.NoError(t, err) + require.ErrorIs(t, f.Abort(), os.ErrClosed) + } +  +-func TestAtomicWriter_ApplyGzip(t *testing.T) { ++func TestAtomicWriterCompressed_ApplyGzip(t *testing.T) { + tests := []struct { + name string + filename string +@@ -108,3 +108,37 @@ require.Equal(t, data, readData) + }) + } + } ++ ++func TestAtomicWriter_ApplyGzip(t *testing.T) { ++ tests := []struct { ++ name string ++ filename string ++ }{ ++ {"Uncompressed", "test.notgz"}, ++ {"Gzipped", "test.gz"}, ++ } ++ for _, test := range tests { ++ test := test ++ t.Run(test.name, func(t *testing.T) { ++ data := []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 0} ++ dir := t.TempDir() ++ path := filepath.Join(dir, test.filename) ++ out, err := NewAtomicWriter(path, 0o644) ++ require.NoError(t, err) ++ defer out.Close() ++ _, err = out.Write(data) ++ require.NoError(t, err) ++ require.NoError(t, out.Close()) ++ ++ writtenData, err := os.ReadFile(path) ++ require.NoError(t, err) ++ require.Equal(t, data, writtenData, "should not have compressed data on disk") ++ ++ in, err := os.Open(path) ++ require.NoError(t, err) ++ readData, err := io.ReadAll(in) ++ require.NoError(t, err) ++ require.Equal(t, data, readData) ++ }) ++ } ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+52
+
-0
+ +
+ +
+
+
diff --git OP/op-service/ioutil/streams.go CELO/op-service/ioutil/streams.go +new file mode 100644 +index 0000000000000000000000000000000000000000..91f122906db0daa7c966ab46e535536764ab399f +--- /dev/null ++++ CELO/op-service/ioutil/streams.go +@@ -0,0 +1,52 @@ ++package ioutil ++ ++import ( ++ "io" ++ "os" ++) ++ ++var ( ++ stdOutStream OutputTarget = func() (io.Writer, io.Closer, Aborter, error) { ++ return os.Stdout, &noopCloser{}, func() {}, nil ++ } ++) ++ ++type Aborter func() ++ ++type OutputTarget func() (io.Writer, io.Closer, Aborter, error) ++ ++func NoOutputStream() OutputTarget { ++ return func() (io.Writer, io.Closer, Aborter, error) { ++ return nil, nil, nil, nil ++ } ++} ++ ++func ToAtomicFile(path string, perm os.FileMode) OutputTarget { ++ return func() (io.Writer, io.Closer, Aborter, error) { ++ f, err := NewAtomicWriterCompressed(path, perm) ++ if err != nil { ++ return nil, nil, nil, err ++ } ++ return f, f, func() { _ = f.Abort() }, nil ++ } ++} ++ ++func ToStdOut() OutputTarget { ++ return stdOutStream ++} ++ ++func ToStdOutOrFileOrNoop(outputPath string, perm os.FileMode) OutputTarget { ++ if outputPath == "" { ++ return NoOutputStream() ++ } else if outputPath == "-" { ++ return ToStdOut() ++ } else { ++ return ToAtomicFile(outputPath, perm) ++ } ++} ++ ++type noopCloser struct{} ++ ++func (c *noopCloser) Close() error { ++ return nil ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+100
+
-0
+ +
+ +
+
+
diff --git OP/op-service/ioutil/streams_test.go CELO/op-service/ioutil/streams_test.go +new file mode 100644 +index 0000000000000000000000000000000000000000..cbbed7e62171525432c5cf224bc109abf5bcf576 +--- /dev/null ++++ CELO/op-service/ioutil/streams_test.go +@@ -0,0 +1,100 @@ ++package ioutil ++ ++import ( ++ "os" ++ "path/filepath" ++ "testing" ++ ++ "github.com/stretchr/testify/require" ++) ++ ++func TestNoOutputStream(t *testing.T) { ++ writer, closer, aborter, err := NoOutputStream()() ++ require.NoError(t, err) ++ require.Nil(t, writer) ++ require.Nil(t, closer) ++ require.Nil(t, aborter) ++} ++ ++func TestToStdOut(t *testing.T) { ++ writer, closer, aborter, err := ToStdOut()() ++ require.NoError(t, err) ++ require.Same(t, os.Stdout, writer) ++ ++ // Should not close StdOut ++ require.NoError(t, closer.Close()) ++ _, err = os.Stdout.WriteString("TestToStdOut After Close\n") ++ require.NoError(t, err) ++ ++ aborter() ++ _, err = os.Stdout.WriteString("TestToStdOut After Abort\n") ++ require.NoError(t, err) ++} ++ ++func TestToAtomicFile(t *testing.T) { ++ t.Run("Abort", func(t *testing.T) { ++ dir := t.TempDir() ++ path := filepath.Join(dir, "test.txt") ++ writer, closer, aborter, err := ToAtomicFile(path, 0o644)() ++ defer closer.Close() ++ require.NoError(t, err) ++ ++ expected := []byte("test") ++ _, err = writer.Write(expected) ++ require.NoError(t, err) ++ aborter() ++ ++ _, err = os.Stat(path) ++ require.ErrorIs(t, err, os.ErrNotExist, "Should not have written file") ++ }) ++ ++ t.Run("Close", func(t *testing.T) { ++ dir := t.TempDir() ++ path := filepath.Join(dir, "test.txt") ++ writer, closer, _, err := ToAtomicFile(path, 0o644)() ++ defer closer.Close() ++ require.NoError(t, err) ++ ++ expected := []byte("test") ++ _, err = writer.Write(expected) ++ require.NoError(t, err) ++ ++ _, err = os.Stat(path) ++ require.ErrorIs(t, err, os.ErrNotExist, "Target file should not exist prior to Close") ++ ++ require.NoError(t, closer.Close()) ++ actual, err := os.ReadFile(path) ++ require.NoError(t, err) ++ require.Equal(t, expected, actual) ++ }) ++} ++ ++func TestToStdOutOrFileOrNoop(t *testing.T) { ++ t.Run("EmptyOutputPath", func(t *testing.T) { ++ writer, _, _, err := ToStdOutOrFileOrNoop("", 0o644)() ++ require.NoError(t, err) ++ require.Nil(t, writer, "Should use no output stream") ++ }) ++ ++ t.Run("StdOut", func(t *testing.T) { ++ writer, _, _, err := ToStdOutOrFileOrNoop("-", 0o644)() ++ require.NoError(t, err) ++ require.Same(t, os.Stdout, writer, "Should use std out") ++ }) ++ ++ t.Run("File", func(t *testing.T) { ++ dir := t.TempDir() ++ path := filepath.Join(dir, "test.txt") ++ writer, closer, _, err := ToStdOutOrFileOrNoop(path, 0o644)() ++ defer closer.Close() ++ require.NoError(t, err) ++ ++ expected := []byte("test") ++ _, err = writer.Write(expected) ++ require.NoError(t, err) ++ require.NoError(t, closer.Close()) ++ actual, err := os.ReadFile(path) ++ require.NoError(t, err) ++ require.Equal(t, expected, actual) ++ }) ++}
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+115
+
-33
+ +
+ +
+
+
diff --git OP/op-service/jsonutil/json.go CELO/op-service/jsonutil/json.go +index 94dcfd91c252815c29f3c6ad9bca5945dd7cd7d4..5993138595b400773a1a73d5cf739242f884289f 100644 +--- OP/op-service/jsonutil/json.go ++++ CELO/op-service/jsonutil/json.go +@@ -5,12 +5,106 @@ "encoding/json" + "errors" + "fmt" + "io" +- "os" ++ ++ "github.com/BurntSushi/toml" +  + "github.com/ethereum-optimism/optimism/op-service/ioutil" + ) +  ++type Decoder interface { ++ Decode(v interface{}) error ++} ++ ++type DecoderFactory func(r io.Reader) Decoder ++ ++type Encoder interface { ++ Encode(v interface{}) error ++} ++ ++type EncoderFactory func(w io.Writer) Encoder ++ ++type jsonDecoder struct { ++ d *json.Decoder ++} ++ ++func newJSONDecoder(r io.Reader) Decoder { ++ return &jsonDecoder{ ++ d: json.NewDecoder(r), ++ } ++} ++ ++func (d *jsonDecoder) Decode(v interface{}) error { ++ if err := d.d.Decode(v); err != nil { ++ return fmt.Errorf("failed to decode JSON: %w", err) ++ } ++ if _, err := d.d.Token(); err != io.EOF { ++ return errors.New("unexpected trailing data") ++ } ++ return nil ++} ++ ++type tomlDecoder struct { ++ r io.Reader ++} ++ ++func newTOMLDecoder(r io.Reader) Decoder { ++ return &tomlDecoder{ ++ r: r, ++ } ++} ++ ++func (d *tomlDecoder) Decode(v interface{}) error { ++ if _, err := toml.NewDecoder(d.r).Decode(v); err != nil { ++ return fmt.Errorf("failed to decode TOML: %w", err) ++ } ++ return nil ++} ++ ++type jsonEncoder struct { ++ e *json.Encoder ++} ++ ++func newJSONEncoder(w io.Writer) Encoder { ++ e := json.NewEncoder(w) ++ e.SetIndent("", " ") ++ return &jsonEncoder{ ++ e: e, ++ } ++} ++ ++func (e *jsonEncoder) Encode(v interface{}) error { ++ if err := e.e.Encode(v); err != nil { ++ return fmt.Errorf("failed to encode JSON: %w", err) ++ } ++ return nil ++} ++ ++type tomlEncoder struct { ++ w io.Writer ++} ++ ++func newTOMLEncoder(w io.Writer) Encoder { ++ return &tomlEncoder{ ++ w: w, ++ } ++} ++ ++func (e *tomlEncoder) Encode(v interface{}) error { ++ if err := toml.NewEncoder(e.w).Encode(v); err != nil { ++ return fmt.Errorf("failed to encode TOML: %w", err) ++ } ++ return nil ++} ++ + func LoadJSON[X any](inputPath string) (*X, error) { ++ return load[X](inputPath, newJSONDecoder) ++} ++ ++func LoadTOML[X any](inputPath string) (*X, error) { ++ return load[X](inputPath, newTOMLDecoder) ++} ++ ++func load[X any](inputPath string, dec DecoderFactory) (*X, error) { + if inputPath == "" { + return nil, errors.New("no path specified") + } +@@ -21,49 +115,37 @@ return nil, fmt.Errorf("failed to open file %q: %w", inputPath, err) + } + defer f.Close() + var state X +- decoder := json.NewDecoder(f) +- if err := decoder.Decode(&state); err != nil { ++ if err := dec(f).Decode(&state); err != nil { + return nil, fmt.Errorf("failed to decode file %q: %w", inputPath, err) + } +- // We are only expecting 1 JSON object - confirm there is no trailing data +- if _, err := decoder.Token(); err != io.EOF { +- return nil, fmt.Errorf("unexpected trailing data in file %q", inputPath) +- } + return &state, nil + } +  +-func WriteJSON[X any](outputPath string, value X, perm os.FileMode) error { +- if outputPath == "" { +- return nil ++func WriteJSON[X any](value X, target ioutil.OutputTarget) error { ++ return write(value, target, newJSONEncoder) ++} ++ ++func WriteTOML[X any](value X, target ioutil.OutputTarget) error { ++ return write(value, target, newTOMLEncoder) ++} ++ ++func write[X any](value X, target ioutil.OutputTarget, enc EncoderFactory) error { ++ out, closer, abort, err := target() ++ if err != nil { ++ return err + } +- var out io.Writer +- finish := func() error { return nil } +- if outputPath != "-" { +- f, err := ioutil.NewAtomicWriterCompressed(outputPath, perm) +- if err != nil { +- return fmt.Errorf("failed to open output file: %w", err) +- } +- // Ensure we close the stream without renaming even if failures occur. +- defer func() { +- _ = f.Abort() +- }() +- out = f +- // Closing the file causes it to be renamed to the final destination +- // so make sure we handle any errors it returns +- finish = f.Close +- } else { +- out = os.Stdout ++ if out == nil { ++ return nil // No output stream selected so skip generating the content entirely + } +- enc := json.NewEncoder(out) +- enc.SetIndent("", " ") +- if err := enc.Encode(value); err != nil { +- return fmt.Errorf("failed to encode to JSON: %w", err) ++ defer abort() ++ if err := enc(out).Encode(value); err != nil { ++ return fmt.Errorf("failed to encode: %w", err) + } +- _, err := out.Write([]byte{'\n'}) ++ _, err = out.Write([]byte{'\n'}) + if err != nil { + return fmt.Errorf("failed to append new-line: %w", err) + } +- if err := finish(); err != nil { ++ if err := closer.Close(); err != nil { + return fmt.Errorf("failed to finish write: %w", err) + } + return nil
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+6
+
-6
+ +
+ +
+
+
diff --git OP/op-service/jsonutil/json_test.go CELO/op-service/jsonutil/json_test.go +index 9a143d0c2579cf1ed47fe923d0c4615f2f27854f..36bda167491bf8b42036357d4c1c5aa0eea8f9b1 100644 +--- OP/op-service/jsonutil/json_test.go ++++ CELO/op-service/jsonutil/json_test.go +@@ -2,11 +2,11 @@ package jsonutil +  + import ( + "encoding/json" +- "fmt" + "os" + "path/filepath" + "testing" +  ++ "github.com/ethereum-optimism/optimism/op-service/ioutil" + "github.com/stretchr/testify/require" + ) +  +@@ -14,7 +14,7 @@ func TestRoundTripJSON(t *testing.T) { + dir := t.TempDir() + file := filepath.Join(dir, "test.json") + data := &jsonTestData{A: "yay", B: 3} +- err := WriteJSON(file, data, 0o755) ++ err := WriteJSON(data, ioutil.ToAtomicFile(file, 0o755)) + require.NoError(t, err) +  + // Confirm the file is uncompressed +@@ -33,7 +33,7 @@ func TestRoundTripJSONWithGzip(t *testing.T) { + dir := t.TempDir() + file := filepath.Join(dir, "test.json.gz") + data := &jsonTestData{A: "yay", B: 3} +- err := WriteJSON(file, data, 0o755) ++ err := WriteJSON(data, ioutil.ToAtomicFile(file, 0o755)) + require.NoError(t, err) +  + // Confirm the file isn't raw JSON +@@ -87,14 +87,14 @@ extraData, err := tc.extraData() + require.NoError(t, err) +  + // Write primary json payload + extra data to the file +- err = WriteJSON(file, data, 0o755) ++ err = WriteJSON(data, ioutil.ToAtomicFile(file, 0o755)) + require.NoError(t, err) + err = appendDataToFile(file, extraData) + require.NoError(t, err) +  + var result *jsonTestData + result, err = LoadJSON[jsonTestData](file) +- require.ErrorContains(t, err, fmt.Sprintf("unexpected trailing data in file %q", file)) ++ require.ErrorContains(t, err, "unexpected trailing data") + require.Nil(t, result) + }) + } +@@ -130,7 +130,7 @@ file := filepath.Join(dir, "test.json") + data := &jsonTestData{A: "yay", B: 3} +  + // Write primary json payload + extra data to the file +- err := WriteJSON(file, data, 0o755) ++ err := WriteJSON(data, ioutil.ToAtomicFile(file, 0o755)) + require.NoError(t, err) + err = appendDataToFile(file, tc.extraData) + require.NoError(t, err)
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+1
+
-1
+ +
+ +
+
+
diff --git OP/op-service/metrics/cli.go CELO/op-service/metrics/cli.go +index dcbe3d0af2edcc092c6711e01488a3399f777c9e..d5c8151b889a7c901257ce96c058c9bd32dad154 100644 +--- OP/op-service/metrics/cli.go ++++ CELO/op-service/metrics/cli.go +@@ -37,7 +37,7 @@ }, + &cli.StringFlag{ + Name: ListenAddrFlagName, + Usage: "Metrics listening address", +- Value: defaultListenAddr, // TODO(CLI-4159): Switch to 127.0.0.1 ++ Value: defaultListenAddr, // TODO: Switch to 127.0.0.1 + EnvVars: opservice.PrefixEnvVar(envPrefix, "METRICS_ADDR"), + }, + &cli.IntFlag{
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+2
+
-2
+ +
+ +
+
+
diff --git OP/op-service/metrics/http.go CELO/op-service/metrics/http.go +index 8640fe02a6f2020073055b91c6c9806ad99bfc44..60609c563dca94328bb0a7077487cce51b5a121a 100644 +--- OP/op-service/metrics/http.go ++++ CELO/op-service/metrics/http.go +@@ -65,7 +65,7 @@ var LatencyBuckets = []float64{.025, .05, .1, .25, .5, 1, 2.5, 5, 10, 25, 50, 100} +  + func NewPromHTTPRecorder(r *prometheus.Registry, ns string) HTTPRecorder { + return &PromHTTPRecorder{ +- // TODO(INF-509): remove this in the future when services opted in to HTTPRequestLatency ++ // TODO: remove this in the future when services opted in to HTTPRequestLatency + HTTPRequestDuration: promauto.With(r).NewHistogramVec(prometheus.HistogramOpts{ + Namespace: ns, + Name: "http_request_duration_ms", +@@ -104,7 +104,7 @@ } + } +  + func (p *PromHTTPRecorder) RecordHTTPRequestDuration(params *HTTPParams, dur time.Duration) { +- // TODO(INF-509): remove this in the future when services opted in to new metric ++ // TODO: remove this in the future when services opted in to new metric + p.HTTPRequestDuration.WithLabelValues(params.Method, strconv.Itoa(params.StatusCode)). + Observe(float64(dur.Milliseconds())) +
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+1
+
-1
+ +
+ +
+
+
diff --git OP/op-service/oppprof/cli.go CELO/op-service/oppprof/cli.go +index d6ccb8566960cba5d4558d8effaf4e02db442885..6c2c33a147114e2e76a806322e56e000b93b2255 100644 +--- OP/op-service/oppprof/cli.go ++++ CELO/op-service/oppprof/cli.go +@@ -76,7 +76,7 @@ }, + &cli.StringFlag{ + Name: ListenAddrFlagName, + Usage: "pprof listening address", +- Value: defaultListenAddr, // TODO(CLI-4159): Switch to 127.0.0.1 ++ Value: defaultListenAddr, // TODO: Switch to 127.0.0.1 + EnvVars: opservice.PrefixEnvVar(envPrefix, "PPROF_ADDR"), + Category: category, + },
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+41
+
-0
+ +
+ +
+
+
diff --git OP/op-service/predeploys/addresses.go CELO/op-service/predeploys/addresses.go +index a03fcf29188a5390aba3eb2437d31f14caf52522..53dc44500c06a815f7083145aefb725d1f61d93f 100644 +--- OP/op-service/predeploys/addresses.go ++++ CELO/op-service/predeploys/addresses.go +@@ -27,6 +27,8 @@ SchemaRegistry = "0x4200000000000000000000000000000000000020" + EAS = "0x4200000000000000000000000000000000000021" + CrossL2Inbox = "0x4200000000000000000000000000000000000022" + L2toL2CrossDomainMessenger = "0x4200000000000000000000000000000000000023" ++ SuperchainWETH = "0x4200000000000000000000000000000000000024" ++ ETHLiquidity = "0x4200000000000000000000000000000000000025" + Create2Deployer = "0x13b0D85CcB8bf860b6b79AF3029fCA081AE9beF2" + MultiCall3 = "0xcA11bde05977b3631167028862bE2a173976CA11" + Safe_v130 = "0x69f4D1788e39c87893C980c06EdF4b7f686e2938" +@@ -40,6 +42,16 @@ SenderCreator_v060 = "0x7fc98430eaedbb6070b35b39d798725049088348" + EntryPoint_v060 = "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789" + SenderCreator_v070 = "0xEFC2c1444eBCC4Db75e7613d20C6a62fF67A167C" + EntryPoint_v070 = "0x0000000071727De22E5E9d8BAf0edAc6f37da032" ++ ++ // Celo ++ CeloRegistry = "0x000000000000000000000000000000000000ce10" ++ GoldToken = "0x471ece3750da237f93b8e339c536989b8978a438" ++ FeeHandler = "0xcd437749e43a154c07f3553504c68fbfd56b8778" ++ MentoFeeHandlerSeller = "0x4efa274b7e33476c961065000d58ee09f7921a74" ++ UniswapFeeHandlerSeller = "0xd3aee28548dbb65df03981f0dc0713bfcbd10a97" ++ SortedOracles = "0xefb84935239dacdecf7c5ba76d8de40b077b7b33" ++ AddressSortedLinkedListWithMedian = "0xED477A99035d0c1e11369F1D7A4e587893cc002B" ++ FeeCurrency = "0x4200000000000000000000000000000000001022" + ) +  + var ( +@@ -64,6 +76,8 @@ SchemaRegistryAddr = common.HexToAddress(SchemaRegistry) + EASAddr = common.HexToAddress(EAS) + CrossL2InboxAddr = common.HexToAddress(CrossL2Inbox) + L2toL2CrossDomainMessengerAddr = common.HexToAddress(L2toL2CrossDomainMessenger) ++ SuperchainWETHAddr = common.HexToAddress(SuperchainWETH) ++ ETHLiquidityAddr = common.HexToAddress(ETHLiquidity) + Create2DeployerAddr = common.HexToAddress(Create2Deployer) + MultiCall3Addr = common.HexToAddress(MultiCall3) + Safe_v130Addr = common.HexToAddress(Safe_v130) +@@ -80,6 +94,18 @@ EntryPoint_v070Addr = common.HexToAddress(EntryPoint_v070) +  + Predeploys = make(map[string]*Predeploy) + PredeploysByAddress = make(map[common.Address]*Predeploy) ++ ++ // Celo ++ CeloRegistryAddr = common.HexToAddress(CeloRegistry) ++ GoldTokenAddr = common.HexToAddress(GoldToken) ++ FeeHandlerAddr = common.HexToAddress(FeeHandler) ++ MentoFeeHandlerSellerAddr = common.HexToAddress(MentoFeeHandlerSeller) ++ UniswapFeeHandlerSellerAddr = common.HexToAddress(UniswapFeeHandlerSeller) ++ SortedOraclesAddr = common.HexToAddress(SortedOracles) ++ AddressSortedLinkedListWithMedianAddr = common.HexToAddress(AddressSortedLinkedListWithMedian) ++ FeeCurrencyAddr = common.HexToAddress(FeeCurrency) ++ ++ CeloPredeploys = make(map[string]*Predeploy) + ) +  + func init() { +@@ -95,6 +121,8 @@ Predeploys["GasPriceOracle"] = &Predeploy{Address: GasPriceOracleAddr} + Predeploys["L1Block"] = &Predeploy{Address: L1BlockAddr} + Predeploys["CrossL2Inbox"] = &Predeploy{Address: CrossL2InboxAddr} + Predeploys["L2toL2CrossDomainMessenger"] = &Predeploy{Address: L2toL2CrossDomainMessengerAddr} ++ Predeploys["SuperchainWETH"] = &Predeploy{Address: SuperchainWETHAddr} ++ Predeploys["ETHLiquidity"] = &Predeploy{Address: ETHLiquidityAddr} + Predeploys["GovernanceToken"] = &Predeploy{ + Address: GovernanceTokenAddr, + ProxyDisabled: true, +@@ -161,6 +189,19 @@ } + Predeploys["EntryPoint_v070"] = &Predeploy{ + Address: EntryPoint_v070Addr, + ProxyDisabled: true, ++ } ++ ++ // Celo ++ CeloPredeploys["CeloRegistry"] = &Predeploy{Address: CeloRegistryAddr} ++ CeloPredeploys["GoldToken"] = &Predeploy{Address: GoldTokenAddr} ++ CeloPredeploys["FeeHandler"] = &Predeploy{Address: FeeHandlerAddr} ++ CeloPredeploys["MentoFeeHandlerSeller"] = &Predeploy{Address: MentoFeeHandlerSellerAddr} ++ CeloPredeploys["UniswapFeeHandlerSeller"] = &Predeploy{Address: UniswapFeeHandlerSellerAddr} ++ CeloPredeploys["SortedOracles"] = &Predeploy{Address: SortedOraclesAddr} ++ CeloPredeploys["AddressSortedLinkedListWithMedian"] = &Predeploy{Address: AddressSortedLinkedListWithMedianAddr} ++ CeloPredeploys["FeeCurrency"] = &Predeploy{Address: FeeCurrencyAddr} ++ for key, predeploy := range CeloPredeploys { ++ Predeploys[key] = predeploy + } +  + for _, predeploy := range Predeploys {
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+1
+
-1
+ +
+ +
+
+
diff --git OP/op-service/rpc/cli.go CELO/op-service/rpc/cli.go +index 99cb2dd6c9b225559b8bbbba18abf99089e2bbf6..ef957765e19f31889a95faa46eaa5427e138a9da 100644 +--- OP/op-service/rpc/cli.go ++++ CELO/op-service/rpc/cli.go +@@ -21,7 +21,7 @@ return []cli.Flag{ + &cli.StringFlag{ + Name: ListenAddrFlagName, + Usage: "rpc listening address", +- Value: "0.0.0.0", // TODO(CLI-4159): Switch to 127.0.0.1 ++ Value: "0.0.0.0", // TODO: Switch to 127.0.0.1 + EnvVars: opservice.PrefixEnvVar(envPrefix, "RPC_ADDR"), + }, + &cli.IntFlag{
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+1
+
-1
+ +
+ +
+
+
diff --git OP/op-service/solabi/util.go CELO/op-service/solabi/util.go +index ce26aaf76c58aada87fd5c6f01df33029f441338..41c01106a323c077bd3cb0fa99d3b44c46f7007b 100644 +--- OP/op-service/solabi/util.go ++++ CELO/op-service/solabi/util.go +@@ -69,7 +69,7 @@ } else if !bytes.Equal(readPadding[:], uint64EmptyPadding[:]) { + return n, fmt.Errorf("number padding was not empty: %x", readPadding[:]) + } + if err := binary.Read(r, binary.BigEndian, &n); err != nil { +- return 0, fmt.Errorf("expected number length to be 8 bytes") ++ return 0, errors.New("expected number length to be 8 bytes") + } + return n, nil + }
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+2
+
-1
+ +
+ +
+
+
diff --git OP/op-service/sources/batching/batching.go CELO/op-service/sources/batching/batching.go +index 0cf88f702704648c5d3ae157b65205ce16605bf1..50fd76da9452311678cf73f13cbfdc8a0ed6d532 100644 +--- OP/op-service/sources/batching/batching.go ++++ CELO/op-service/sources/batching/batching.go +@@ -2,6 +2,7 @@ package batching +  + import ( + "context" ++ "errors" + "fmt" + "io" + "sync" +@@ -176,7 +177,7 @@ func (ibc *IterativeBatchCall[K, V]) Result() ([]V, error) { + ibc.resetLock.RLock() + if atomic.LoadUint32(&ibc.completed) < uint32(len(ibc.requestsKeys)) { + ibc.resetLock.RUnlock() +- return nil, fmt.Errorf("results not available yet, Fetch more first") ++ return nil, errors.New("results not available yet, Fetch more first") + } + ibc.resetLock.RUnlock() + return ibc.requestsValues, nil
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+1
+
-1
+ +
+ +
+
+
diff --git OP/op-service/sources/batching/test/abi_stub.go CELO/op-service/sources/batching/test/abi_stub.go +index 12b9aecebf2d00306523a383d45b58a1e0cecfab..431c77c8dbd44f6f2527c7bd41abbb5bceacad5b 100644 +--- OP/op-service/sources/batching/test/abi_stub.go ++++ CELO/op-service/sources/batching/test/abi_stub.go +@@ -35,7 +35,7 @@ return fmt.Errorf("expected arg count 2 but was %v", len(args)) + } + callOpts, ok := args[0].(map[string]any) + if !ok { +- return fmt.Errorf("arg 0 is not a map[string]any") ++ return errors.New("arg 0 is not a map[string]any") + } + actualBlockRef := args[1] + to, ok := callOpts["to"].(*common.Address)
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+19
+
-8
+ +
+ +
+
+
diff --git OP/op-service/sources/engine_client.go CELO/op-service/sources/engine_client.go +index 07d7ecb9d27164410a851950ba30f5c3525eae33..79921192f9e75e72e6371f0f7600b9dab4ff5905 100644 +--- OP/op-service/sources/engine_client.go ++++ CELO/op-service/sources/engine_client.go +@@ -50,9 +50,10 @@ } +  + // EngineAPIClient is an RPC client for the Engine API functions. + type EngineAPIClient struct { +- RPC client.RPC +- log log.Logger +- evp EngineVersionProvider ++ RPC client.RPC ++ log log.Logger ++ evp EngineVersionProvider ++ timeout time.Duration + } +  + type EngineVersionProvider interface { +@@ -63,9 +64,19 @@ } +  + func NewEngineAPIClient(rpc client.RPC, l log.Logger, evp EngineVersionProvider) *EngineAPIClient { + return &EngineAPIClient{ +- RPC: rpc, +- log: l, +- evp: evp, ++ RPC: rpc, ++ log: l, ++ evp: evp, ++ timeout: time.Second * 5, ++ } ++} ++ ++func NewEngineAPIClientWithTimeout(rpc client.RPC, l log.Logger, evp EngineVersionProvider, timeout time.Duration) *EngineAPIClient { ++ return &EngineAPIClient{ ++ RPC: rpc, ++ log: l, ++ evp: evp, ++ timeout: timeout, + } + } +  +@@ -84,7 +95,7 @@ func (s *EngineAPIClient) ForkchoiceUpdate(ctx context.Context, fc *eth.ForkchoiceState, attributes *eth.PayloadAttributes) (*eth.ForkchoiceUpdatedResult, error) { + llog := s.log.New("state", fc) // local logger + tlog := llog.New("attr", attributes) // trace logger + tlog.Trace("Sharing forkchoice-updated signal") +- fcCtx, cancel := context.WithTimeout(ctx, time.Second*5) ++ fcCtx, cancel := context.WithTimeout(ctx, s.timeout) + defer cancel() + var result eth.ForkchoiceUpdatedResult + method := s.evp.ForkchoiceUpdatedVersion(attributes) +@@ -120,7 +131,7 @@ func (s *EngineAPIClient) NewPayload(ctx context.Context, payload *eth.ExecutionPayload, parentBeaconBlockRoot *common.Hash) (*eth.PayloadStatusV1, error) { + e := s.log.New("block_hash", payload.BlockHash) + e.Trace("sending payload for execution") +  +- execCtx, cancel := context.WithTimeout(ctx, time.Second*5) ++ execCtx, cancel := context.WithTimeout(ctx, s.timeout) + defer cancel() + var result eth.PayloadStatusV1 +
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+1
+
-1
+ +
+ +
+
+
diff --git OP/op-service/sources/l2_client.go CELO/op-service/sources/l2_client.go +index 304a94a0a2925afe03061ad83fb43a4416849f8f..078385d40510105c154b30b09566bf11902060e6 100644 +--- OP/op-service/sources/l2_client.go ++++ CELO/op-service/sources/l2_client.go +@@ -102,7 +102,7 @@ envelope, err := s.PayloadByLabel(ctx, label) + if err != nil { + // Both geth and erigon like to serve non-standard errors for the safe and finalized heads, correct that. + // This happens when the chain just started and nothing is marked as safe/finalized yet. +- if strings.Contains(err.Error(), "block not found") || strings.Contains(err.Error(), "Unknown block") || strings.Contains(err.Error(), "unknown block") { ++ if strings.Contains(err.Error(), "block not found") || strings.Contains(err.Error(), "Unknown block") || strings.Contains(err.Error(), "unknown block") || strings.Contains(err.Error(), "header not found") { + err = ethereum.NotFound + } + // w%: wrap to preserve ethereum.NotFound case
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+4
+
-4
+ +
+ +
+
+
diff --git OP/op-service/sources/limit_test.go CELO/op-service/sources/limit_test.go +index ed59e0287ec16fac8334cb303000ef6055d2f4af..5bea12046779a3bce09757850d917f7f1b6a53d9 100644 +--- OP/op-service/sources/limit_test.go ++++ CELO/op-service/sources/limit_test.go +@@ -2,7 +2,7 @@ package sources +  + import ( + "context" +- "fmt" ++ "errors" + "net" + "sync/atomic" + "testing" +@@ -97,10 +97,10 @@ case <-time.After(50 * time.Millisecond): + // None of the clients should return yet + } +  +- m.errC <- fmt.Errorf("fake-error") +- m.errC <- fmt.Errorf("fake-error") ++ m.errC <- errors.New("fake-error") ++ m.errC <- errors.New("fake-error") + require.Eventually(t, func() bool { return m.blockedCallers.Load() == 1 }, time.Second, 10*time.Millisecond) +- m.errC <- fmt.Errorf("fake-error") ++ m.errC <- errors.New("fake-error") +  + require.ErrorContains(t, <-errC1, "fake-error") + require.ErrorContains(t, <-errC2, "fake-error")
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+84
+
-0
+ +
+ +
+
+
diff --git OP/op-service/sources/supervisor_client.go CELO/op-service/sources/supervisor_client.go +new file mode 100644 +index 0000000000000000000000000000000000000000..db40e55ef4724d4f679058c56487cf5242caf5a9 +--- /dev/null ++++ CELO/op-service/sources/supervisor_client.go +@@ -0,0 +1,84 @@ ++package sources ++ ++import ( ++ "context" ++ "fmt" ++ ++ "github.com/ethereum/go-ethereum/common" ++ "github.com/ethereum/go-ethereum/common/hexutil" ++ ++ "github.com/ethereum-optimism/optimism/op-service/client" ++ "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" ++) ++ ++type SupervisorClient struct { ++ client client.RPC ++} ++ ++func NewSupervisorClient(client client.RPC) *SupervisorClient { ++ return &SupervisorClient{ ++ client: client, ++ } ++} ++ ++func (cl *SupervisorClient) Stop( ++ ctx context.Context, ++) error { ++ var result error ++ err := cl.client.CallContext( ++ ctx, ++ &result, ++ "admin_stop") ++ if err != nil { ++ return fmt.Errorf("failed to stop Supervisor: %w", err) ++ } ++ return result ++} ++ ++func (cl *SupervisorClient) Start( ++ ctx context.Context, ++) error { ++ var result error ++ err := cl.client.CallContext( ++ ctx, ++ &result, ++ "admin_start") ++ if err != nil { ++ return fmt.Errorf("failed to start Supervisor: %w", err) ++ } ++ return result ++} ++ ++func (cl *SupervisorClient) AddL2RPC( ++ ctx context.Context, ++ rpc string, ++) error { ++ var result error ++ err := cl.client.CallContext( ++ ctx, ++ &result, ++ "admin_addL2RPC", ++ rpc) ++ if err != nil { ++ return fmt.Errorf("failed to Add L2 to Supervisor (rpc: %s): %w", rpc, err) ++ } ++ return result ++} ++ ++func (cl *SupervisorClient) CheckBlock(ctx context.Context, ++ chainID types.ChainID, blockHash common.Hash, blockNumber uint64) (types.SafetyLevel, error) { ++ var result types.SafetyLevel ++ err := cl.client.CallContext( ++ ctx, ++ &result, ++ "supervisor_checkBlock", ++ (*hexutil.U256)(&chainID), blockHash, hexutil.Uint64(blockNumber)) ++ if err != nil { ++ return types.Unsafe, fmt.Errorf("failed to check Block %s:%d (chain %s): %w", blockHash, blockNumber, chainID, err) ++ } ++ return result, nil ++} ++ ++func (cl *SupervisorClient) Close() { ++ cl.client.Close() ++}
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+2
+
-1
+ +
+ +
+
+
diff --git OP/op-service/sources/types.go CELO/op-service/sources/types.go +index afb994bd7cc35ff7104e508d61031fadf851959e..f337beb0205877e49711b22e9c6f30bafb170e92 100644 +--- OP/op-service/sources/types.go ++++ CELO/op-service/sources/types.go +@@ -1,6 +1,7 @@ + package sources +  + import ( ++ "errors" + "fmt" + "math/big" + "strings" +@@ -229,7 +230,7 @@ return fmt.Errorf("failed to verify transactions list: computed %s but RPC said %s", computed, block.TxHash) + } + if block.WithdrawalsRoot != nil { + if block.Withdrawals == nil { +- return fmt.Errorf("expected withdrawals") ++ return errors.New("expected withdrawals") + } + for i, w := range *block.Withdrawals { + if w == nil {
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+2
+
-2
+ +
+ +
+
+
diff --git OP/op-service/testutils/fake_chain.go CELO/op-service/testutils/fake_chain.go +index 8110e37779f15e6f397bc81fad5415d4d97d2ddd..eca4de1160b688f2dd3a081f970fc7746fae564c 100644 +--- OP/op-service/testutils/fake_chain.go ++++ CELO/op-service/testutils/fake_chain.go +@@ -14,9 +14,9 @@ "github.com/ethereum-optimism/optimism/op-node/rollup" + "github.com/ethereum-optimism/optimism/op-service/eth" + ) +  +-func FakeGenesis(l1 rune, l2 rune, l1GenesisNumber int) rollup.Genesis { ++func FakeGenesis(l1 rune, l2 rune, l1GenesisNumber uint64) rollup.Genesis { + return rollup.Genesis{ +- L1: fakeID(l1, uint64(l1GenesisNumber)), ++ L1: fakeID(l1, l1GenesisNumber), + L2: fakeID(l2, 0), + } + }
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+12
+
-0
+ +
+ +
+
+
diff --git OP/op-service/testutils/kurtosisutil/kurtosis.go CELO/op-service/testutils/kurtosisutil/kurtosis.go +new file mode 100644 +index 0000000000000000000000000000000000000000..8be6c9b3f2c701822d4ae0bc139bba0f08003029 +--- /dev/null ++++ CELO/op-service/testutils/kurtosisutil/kurtosis.go +@@ -0,0 +1,12 @@ ++package kurtosisutil ++ ++import ( ++ "os" ++ "testing" ++) ++ ++func Test(t *testing.T) { ++ if os.Getenv("ENABLE_KURTOSIS") == "" { ++ t.Skip("skipping Kurtosis test") ++ } ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+64
+
-0
+ +
+ +
+
+
diff --git OP/op-service/testutils/kurtosisutil/runner.go CELO/op-service/testutils/kurtosisutil/runner.go +new file mode 100644 +index 0000000000000000000000000000000000000000..6440cedef681cdfa9bc94fcfd1631cef8f26bb86 +--- /dev/null ++++ CELO/op-service/testutils/kurtosisutil/runner.go +@@ -0,0 +1,64 @@ ++package kurtosisutil ++ ++import ( ++ "context" ++ "fmt" ++ "testing" ++ "time" ++ ++ "github.com/ethereum/go-ethereum/log" ++ "github.com/kurtosis-tech/kurtosis/api/golang/core/lib/enclaves" ++ "github.com/kurtosis-tech/kurtosis/api/golang/core/lib/starlark_run_config" ++ "github.com/kurtosis-tech/kurtosis/api/golang/engine/lib/kurtosis_context" ++ "github.com/stretchr/testify/require" ++) ++ ++func StartEnclave(t *testing.T, ctx context.Context, lgr log.Logger, pkg string, params string) *enclaves.EnclaveContext { ++ kurtosisCtx, err := kurtosis_context.NewKurtosisContextFromLocalEngine() ++ require.NoError(t, err) ++ ++ enclaveID := fmt.Sprintf("kurtosis-%s", t.Name()) ++ enclaveCtx, err := kurtosisCtx.CreateEnclave(ctx, enclaveID) ++ require.NoError(t, err) ++ ++ t.Cleanup(func() { ++ ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) ++ defer cancel() ++ err = kurtosisCtx.DestroyEnclave(ctx, enclaveID) ++ if err != nil { ++ lgr.Error("Error destroying enclave", "err", err) ++ } ++ }) ++ ++ stream, _, err := enclaveCtx.RunStarlarkRemotePackage( ++ ctx, ++ pkg, ++ &starlark_run_config.StarlarkRunConfig{ ++ SerializedParams: params, ++ }, ++ ) ++ require.NoError(t, err) ++ ++ logKurtosisOutput := func(msg string) { ++ lgr.Info(fmt.Sprintf("[KURTOSIS] %s", msg)) ++ } ++ ++ for responseLine := range stream { ++ if responseLine.GetProgressInfo() != nil { ++ stepInfo := responseLine.GetProgressInfo().CurrentStepInfo ++ logKurtosisOutput(stepInfo[len(stepInfo)-1]) ++ } else if responseLine.GetInstruction() != nil { ++ logKurtosisOutput(responseLine.GetInstruction().Description) ++ } else if responseLine.GetError() != nil { ++ if responseLine.GetError().GetInterpretationError() != nil { ++ t.Fatalf("interpretation error: %s", responseLine.GetError().GetInterpretationError().String()) ++ } else if responseLine.GetError().GetValidationError() != nil { ++ t.Fatalf("validation error: %s", responseLine.GetError().GetValidationError().String()) ++ } else if responseLine.GetError().GetExecutionError() != nil { ++ t.Fatalf("execution error: %s", responseLine.GetError().GetExecutionError().String()) ++ } ++ } ++ } ++ ++ return enclaveCtx ++}
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+4
+
-0
+ +
+ +
+
+
diff --git OP/op-service/testutils/metrics.go CELO/op-service/testutils/metrics.go +index 617d2ded3c03a80c98bb9a367c3c555ccfcd86c8..421d32f2109c545acb56ea0da1c3b2896af0e533 100644 +--- OP/op-service/testutils/metrics.go ++++ CELO/op-service/testutils/metrics.go +@@ -14,6 +14,7 @@ FnRecordL1Ref func(name string, ref eth.L1BlockRef) + FnRecordL2Ref func(name string, ref eth.L2BlockRef) + FnRecordUnsafePayloads func(length uint64, memSize uint64, next eth.BlockID) + FnRecordChannelInputBytes func(inputCompressedBytes int) ++ FnRecordChannelTimedOut func() + } +  + func (t *TestDerivationMetrics) CountSequencedTxs(count int) { +@@ -59,6 +60,9 @@ func (t *TestDerivationMetrics) RecordHeadChannelOpened() { + } +  + func (t *TestDerivationMetrics) RecordChannelTimedOut() { ++ if t.FnRecordChannelTimedOut != nil { ++ t.FnRecordChannelTimedOut() ++ } + } +  + func (t *TestDerivationMetrics) RecordFrame() {
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+28
+
-0
+ +
+ +
+
+
diff --git OP/op-service/testutils/mock_interop_backend.go CELO/op-service/testutils/mock_interop_backend.go +new file mode 100644 +index 0000000000000000000000000000000000000000..970627ff750f28e4fa42aab78490e1d2b52b7234 +--- /dev/null ++++ CELO/op-service/testutils/mock_interop_backend.go +@@ -0,0 +1,28 @@ ++package testutils ++ ++import ( ++ "context" ++ ++ "github.com/stretchr/testify/mock" ++ ++ "github.com/ethereum/go-ethereum/common" ++ ++ "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" ++) ++ ++type MockInteropBackend struct { ++ Mock mock.Mock ++} ++ ++func (m *MockInteropBackend) ExpectCheckBlock(chainID types.ChainID, blockNumber uint64, safety types.SafetyLevel, err error) { ++ m.Mock.On("CheckBlock", chainID, blockNumber).Once().Return(safety, &err) ++} ++ ++func (m *MockInteropBackend) CheckBlock(ctx context.Context, chainID types.ChainID, blockHash common.Hash, blockNumber uint64) (types.SafetyLevel, error) { ++ result := m.Mock.MethodCalled("CheckBlock", chainID, blockNumber) ++ return result.Get(0).(types.SafetyLevel), *result.Get(1).(*error) ++} ++ ++func (m *MockInteropBackend) AssertExpectations(t mock.TestingT) { ++ m.Mock.AssertExpectations(t) ++}
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+50
+
-0
+ +
+ +
+
+
diff --git OP/op-service/txmgr/mocks/TxManager.go CELO/op-service/txmgr/mocks/TxManager.go +index a6ea6b72a914aa782f15391502cb2051c714a799..ec805b74d004f39a140052ac4628bc4a34e6526e 100644 +--- OP/op-service/txmgr/mocks/TxManager.go ++++ CELO/op-service/txmgr/mocks/TxManager.go +@@ -4,6 +4,7 @@ package mocks +  + import ( + context "context" ++ big "math/big" +  + common "github.com/ethereum/go-ethereum/common" +  +@@ -118,6 +119,55 @@ r1 = ret.Error(1) + } +  + return r0, r1 ++} ++ ++// SendAsync provides a mock function with given fields: ctx, candidate, ch ++func (_m *TxManager) SendAsync(ctx context.Context, candidate txmgr.TxCandidate, ch chan txmgr.SendResponse) { ++ _m.Called(ctx, candidate, ch) ++} ++ ++// SuggestGasPriceCaps provides a mock function with given fields: ctx ++func (_m *TxManager) SuggestGasPriceCaps(ctx context.Context) (*big.Int, *big.Int, *big.Int, error) { ++ ret := _m.Called(ctx) ++ ++ var r0 *big.Int ++ var r1 *big.Int ++ var r2 *big.Int ++ var r3 error ++ if rf, ok := ret.Get(0).(func(context.Context) (*big.Int, *big.Int, *big.Int, error)); ok { ++ return rf(ctx) ++ } ++ if rf, ok := ret.Get(0).(func(context.Context) *big.Int); ok { ++ r0 = rf(ctx) ++ } else { ++ if ret.Get(0) != nil { ++ r0 = ret.Get(0).(*big.Int) ++ } ++ } ++ ++ if rf, ok := ret.Get(1).(func(context.Context) *big.Int); ok { ++ r1 = rf(ctx) ++ } else { ++ if ret.Get(1) != nil { ++ r1 = ret.Get(1).(*big.Int) ++ } ++ } ++ ++ if rf, ok := ret.Get(2).(func(context.Context) *big.Int); ok { ++ r2 = rf(ctx) ++ } else { ++ if ret.Get(2) != nil { ++ r2 = ret.Get(2).(*big.Int) ++ } ++ } ++ ++ if rf, ok := ret.Get(3).(func(context.Context) error); ok { ++ r3 = rf(ctx) ++ } else { ++ r3 = ret.Error(3) ++ } ++ ++ return r0, r1, r2, r3 + } +  + type mockConstructorTestingTNewTxManager interface {
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+3
+
-3
+ +
+ +
+
+
diff --git OP/op-service/txmgr/queue.go CELO/op-service/txmgr/queue.go +index cf83b00d5f8a0f7984e3f878545a4a2a4f92769f..ee7a03ffa92880cd20c0ef9e1e0d13eea0167be5 100644 +--- OP/op-service/txmgr/queue.go ++++ CELO/op-service/txmgr/queue.go +@@ -44,11 +44,11 @@ } + } +  + // Wait waits for all pending txs to complete (or fail). +-func (q *Queue[T]) Wait() { ++func (q *Queue[T]) Wait() error { + if q.group == nil { +- return ++ return nil + } +- _ = q.group.Wait() ++ return q.group.Wait() + } +  + // Send will wait until the number of pending txs is below the max pending,
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+1
+
-1
+ +
+ +
+
+
diff --git OP/op-service/txmgr/queue_test.go CELO/op-service/txmgr/queue_test.go +index 678de8dbb28c3a7ee975edfbbe8a2c0825758686..549142c8592ac87ddc7c8d3f5e4634da9f162beb 100644 +--- OP/op-service/txmgr/queue_test.go ++++ CELO/op-service/txmgr/queue_test.go +@@ -222,7 +222,7 @@ queued := c.call(i, candidate, receiptChs[i], queue) + require.Equal(t, c.queued, queued, msg) + } + // wait for the queue to drain (all txs complete or failed) +- queue.Wait() ++ _ = queue.Wait() + duration := time.Since(start) + // expect the execution time within a certain window + now := time.Now()
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+97
+
-20
+ +
+ +
+
+
diff --git OP/op-service/txmgr/txmgr.go CELO/op-service/txmgr/txmgr.go +index 1093d72209570247301b620f7894f2dd689b66fb..6fa0ea5dc15adba13cb0bf6d1c4475094fea0028 100644 +--- OP/op-service/txmgr/txmgr.go ++++ CELO/op-service/txmgr/txmgr.go +@@ -46,6 +46,12 @@ ErrBlobFeeLimit = errors.New("blob fee limit reached") + ErrClosed = errors.New("transaction manager is closed") + ) +  ++type SendResponse struct { ++ Receipt *types.Receipt ++ Nonce uint64 ++ Err error ++} ++ + // TxManager is an interface that allows callers to reliably publish txs, + // bumping the gas price if needed, and obtain the receipt of the resulting tx. + // +@@ -63,6 +69,14 @@ // is ErrAlreadyReserved, which indicates an incompatible transaction may be stuck in the + // mempool and is in need of replacement or cancellation. + Send(ctx context.Context, candidate TxCandidate) (*types.Receipt, error) +  ++ // SendAsync is used to create & send a transaction asynchronously. It has similar internal ++ // semantics to Send, however it returns a channel that will receive the result of the ++ // send operation once it completes. Transactions crafted synchronously - that is, nonce ++ // management and gas estimation happen prior to the method returning. This allows callers ++ // that rely on predictable nonces to send multiple transactions in parallel while preserving ++ // the order of nonce increments. ++ SendAsync(ctx context.Context, candidate TxCandidate, ch chan SendResponse) ++ + // From returns the sending address associated with the instance of the transaction manager. + // It is static for a single instance of a TxManager. + From() common.Address +@@ -76,6 +90,10 @@ + // Close the underlying connection + Close() + IsClosed() bool ++ ++ // SuggestGasPriceCaps suggests what the new tip, base fee, and blob base fee should be based on ++ // the current L1 conditions. `blobBaseFee` will be nil if 4844 is not yet active. ++ SuggestGasPriceCaps(ctx context.Context) (tipCap *big.Int, baseFee *big.Int, blobBaseFee *big.Int, err error) + } +  + // ETHBackend is the set of methods that the transaction manager uses to resubmit gas & determine +@@ -96,7 +114,7 @@ // SendTransaction submits a signed transaction to L1. + SendTransaction(ctx context.Context, tx *types.Transaction) error +  + // These functions are used to estimate what the base fee & priority fee should be set to. +- // TODO(CLI-3318): Maybe need a generic interface to support different RPC providers ++ // TODO: Maybe need a generic interface to support different RPC providers + HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) + SuggestGasTipCap(ctx context.Context) (*big.Int, error) + // NonceAt returns the account nonce of the given account. +@@ -222,24 +240,83 @@ // refuse new requests if the tx manager is closed + if m.closed.Load() { + return nil, ErrClosed + } ++ + m.metr.RecordPendingTx(m.pending.Add(1)) +- defer func() { +- m.metr.RecordPendingTx(m.pending.Add(-1)) +- }() +- receipt, err := m.send(ctx, candidate) ++ defer m.metr.RecordPendingTx(m.pending.Add(-1)) ++ ++ var cancel context.CancelFunc ++ if m.cfg.TxSendTimeout == 0 { ++ ctx, cancel = context.WithCancel(ctx) ++ } else { ++ ctx, cancel = context.WithTimeout(ctx, m.cfg.TxSendTimeout) ++ } ++ defer cancel() ++ ++ tx, err := m.prepare(ctx, candidate) ++ if err != nil { ++ m.resetNonce() ++ return nil, err ++ } ++ receipt, err := m.sendTx(ctx, tx) + if err != nil { + m.resetNonce() ++ return nil, err + } + return receipt, err + } +  +-// send performs the actual transaction creation and sending. +-func (m *SimpleTxManager) send(ctx context.Context, candidate TxCandidate) (*types.Receipt, error) { +- if m.cfg.TxSendTimeout != 0 { +- var cancel context.CancelFunc ++func (m *SimpleTxManager) SendAsync(ctx context.Context, candidate TxCandidate, ch chan SendResponse) { ++ if cap(ch) == 0 { ++ panic("SendAsync: channel must be buffered") ++ } ++ ++ // refuse new requests if the tx manager is closed ++ if m.closed.Load() { ++ ch <- SendResponse{ ++ Receipt: nil, ++ Err: ErrClosed, ++ } ++ return ++ } ++ ++ m.metr.RecordPendingTx(m.pending.Add(1)) ++ ++ var cancel context.CancelFunc ++ if m.cfg.TxSendTimeout == 0 { ++ ctx, cancel = context.WithCancel(ctx) ++ } else { + ctx, cancel = context.WithTimeout(ctx, m.cfg.TxSendTimeout) +- defer cancel() ++ } ++ ++ tx, err := m.prepare(ctx, candidate) ++ if err != nil { ++ m.resetNonce() ++ cancel() ++ m.metr.RecordPendingTx(m.pending.Add(-1)) ++ ch <- SendResponse{ ++ Receipt: nil, ++ Err: err, ++ } ++ return + } ++ ++ go func() { ++ defer m.metr.RecordPendingTx(m.pending.Add(-1)) ++ defer cancel() ++ receipt, err := m.sendTx(ctx, tx) ++ if err != nil { ++ m.resetNonce() ++ } ++ ch <- SendResponse{ ++ Receipt: receipt, ++ Nonce: tx.Nonce(), ++ Err: err, ++ } ++ }() ++} ++ ++// prepare prepares the transaction for sending. ++func (m *SimpleTxManager) prepare(ctx context.Context, candidate TxCandidate) (*types.Transaction, error) { + tx, err := retry.Do(ctx, 30, retry.Fixed(2*time.Second), func() (*types.Transaction, error) { + if m.closed.Load() { + return nil, ErrClosed +@@ -253,7 +330,7 @@ }) + if err != nil { + return nil, fmt.Errorf("failed to create the tx: %w", err) + } +- return m.sendTx(ctx, tx) ++ return tx, nil + } +  + // craftTx creates the signed transaction +@@ -303,7 +380,7 @@ + var txMessage types.TxData + if sidecar != nil { + if blobBaseFee == nil { +- return nil, fmt.Errorf("expected non-nil blobBaseFee") ++ return nil, errors.New("expected non-nil blobBaseFee") + } + blobFeeCap := m.calcBlobFeeCap(blobBaseFee) + message := &types.BlobTx{ +@@ -784,7 +861,7 @@ return signedTx, nil + } +  + // SuggestGasPriceCaps suggests what the new tip, base fee, and blob base fee should be based on +-// the current L1 conditions. blobfee will be nil if 4844 is not yet active. ++// the current L1 conditions. `blobBaseFee` will be nil if 4844 is not yet active. + func (m *SimpleTxManager) SuggestGasPriceCaps(ctx context.Context) (*big.Int, *big.Int, *big.Int, error) { + cCtx, cancel := context.WithTimeout(ctx, m.cfg.NetworkTimeout) + defer cancel() +@@ -910,7 +987,7 @@ lgr.Debug("Using new tip and feecap") + return newTip, newFeeCap + } else if newTip.Cmp(thresholdTip) >= 0 && newFeeCap.Cmp(thresholdFeeCap) < 0 { + // Tip has gone up, but base fee is flat or down. +- // TODO(CLI-3714): Do we need to recalculate the FC here? ++ // TODO: Do we need to recalculate the FC here? + lgr.Debug("Using new tip and threshold feecap") + return newTip, thresholdFeeCap + } else if newTip.Cmp(thresholdTip) < 0 && newFeeCap.Cmp(thresholdFeeCap) >= 0 { +@@ -920,7 +997,7 @@ lgr.Debug("Using threshold tip and recalculated feecap") + return thresholdTip, calcGasFeeCap(newBaseFee, thresholdTip) +  + } else { +- // TODO(CLI-3713): Should we skip the bump in this case? ++ // TODO: Should we skip the bump in this case? + lgr.Debug("Using threshold tip and threshold feecap") + return thresholdTip, thresholdFeeCap + } +@@ -963,19 +1040,19 @@ // finishBlobTx finishes creating a blob tx message by safely converting bigints to uint256 + func finishBlobTx(message *types.BlobTx, chainID, tip, fee, blobFee, value *big.Int) error { + var o bool + if message.ChainID, o = uint256.FromBig(chainID); o { +- return fmt.Errorf("ChainID overflow") ++ return errors.New("ChainID overflow") + } + if message.GasTipCap, o = uint256.FromBig(tip); o { +- return fmt.Errorf("GasTipCap overflow") ++ return errors.New("GasTipCap overflow") + } + if message.GasFeeCap, o = uint256.FromBig(fee); o { +- return fmt.Errorf("GasFeeCap overflow") ++ return errors.New("GasFeeCap overflow") + } + if message.BlobFeeCap, o = uint256.FromBig(blobFee); o { +- return fmt.Errorf("BlobFeeCap overflow") ++ return errors.New("BlobFeeCap overflow") + } + if message.Value, o = uint256.FromBig(value); o { +- return fmt.Errorf("Value overflow") ++ return errors.New("Value overflow") + } + return nil + }
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+179
+
-143
+ +
+ +
+
+
diff --git OP/op-service/txmgr/txmgr_test.go CELO/op-service/txmgr/txmgr_test.go +index c5cf4bca40e594c7533cd8a4a173500ce483635d..6bafa69464b6297d2e010c6659ca438249dc446d 100644 +--- OP/op-service/txmgr/txmgr_test.go ++++ CELO/op-service/txmgr/txmgr_test.go +@@ -338,6 +338,27 @@ + func (b *mockBackend) Close() { + } +  ++type testSendVariantsFn func(ctx context.Context, h *testHarness, tx TxCandidate) (*types.Receipt, error) ++ ++func testSendVariants(t *testing.T, testFn func(t *testing.T, send testSendVariantsFn)) { ++ t.Parallel() ++ ++ t.Run("Send", func(t *testing.T) { ++ testFn(t, func(ctx context.Context, h *testHarness, tx TxCandidate) (*types.Receipt, error) { ++ return h.mgr.Send(ctx, tx) ++ }) ++ }) ++ ++ t.Run("SendAsync", func(t *testing.T) { ++ testFn(t, func(ctx context.Context, h *testHarness, tx TxCandidate) (*types.Receipt, error) { ++ ch := make(chan SendResponse, 1) ++ h.mgr.SendAsync(ctx, tx, ch) ++ res := <-ch ++ return res.Receipt, res.Err ++ }) ++ }) ++} ++ + // TestTxMgrConfirmAtMinGasPrice asserts that Send returns the min gas price tx + // if the tx is mined instantly. + func TestTxMgrConfirmAtMinGasPrice(t *testing.T) { +@@ -400,32 +421,32 @@ + // TestTxMgrTxSendTimeout tests that the TxSendTimeout is respected when trying to send a + // transaction, even if NetworkTimeout expires first. + func TestTxMgrTxSendTimeout(t *testing.T) { +- t.Parallel() ++ testSendVariants(t, func(t *testing.T, send testSendVariantsFn) { ++ conf := configWithNumConfs(1) ++ conf.TxSendTimeout = 3 * time.Second ++ conf.NetworkTimeout = 1 * time.Second +  +- conf := configWithNumConfs(1) +- conf.TxSendTimeout = 3 * time.Second +- conf.NetworkTimeout = 1 * time.Second +- +- h := newTestHarnessWithConfig(t, conf) ++ h := newTestHarnessWithConfig(t, conf) +  +- txCandidate := h.createTxCandidate() +- sendCount := 0 +- sendTx := func(ctx context.Context, tx *types.Transaction) error { +- sendCount++ +- <-ctx.Done() +- return context.DeadlineExceeded +- } +- h.backend.setTxSender(sendTx) ++ txCandidate := h.createTxCandidate() ++ sendCount := 0 ++ sendTx := func(ctx context.Context, tx *types.Transaction) error { ++ sendCount++ ++ <-ctx.Done() ++ return context.DeadlineExceeded ++ } ++ h.backend.setTxSender(sendTx) +  +- ctx, cancel := context.WithTimeout(context.Background(), time.Hour) +- defer cancel() ++ ctx, cancel := context.WithTimeout(context.Background(), time.Hour) ++ defer cancel() +  +- receipt, err := h.mgr.send(ctx, txCandidate) +- require.ErrorIs(t, err, context.DeadlineExceeded) +- // Because network timeout is much shorter than send timeout, we should see multiple send attempts +- // before the overall send fails. +- require.Greater(t, sendCount, 1) +- require.Nil(t, receipt) ++ receipt, err := send(ctx, h, txCandidate) ++ require.ErrorIs(t, err, context.DeadlineExceeded) ++ // Because network timeout is much shorter than send timeout, we should see multiple send attempts ++ // before the overall send fails. ++ require.Greater(t, sendCount, 1) ++ require.Nil(t, receipt) ++ }) + } +  + // TestAlreadyReserved tests that AlreadyReserved error results in immediate abort of transaction +@@ -648,7 +669,7 @@ require.Nil(t, err) + lastNonce := tx.Nonce() +  + // Mock gas estimation failure. +- h.gasPricer.err = fmt.Errorf("execution error") ++ h.gasPricer.err = errors.New("execution error") + _, err = h.mgr.craftTx(context.Background(), candidate) + require.ErrorContains(t, err, "failed to estimate gas") +  +@@ -665,7 +686,7 @@ errorSigning := false + cfg := configWithNumConfs(1) + cfg.Signer = func(ctx context.Context, from common.Address, tx *types.Transaction) (*types.Transaction, error) { + if errorSigning { +- return nil, fmt.Errorf("signer error") ++ return nil, errors.New("signer error") + } else { + return tx, nil + } +@@ -1326,40 +1347,42 @@ } + } +  + func TestNonceReset(t *testing.T) { +- conf := configWithNumConfs(1) +- conf.SafeAbortNonceTooLowCount = 1 +- h := newTestHarnessWithConfig(t, conf) ++ testSendVariants(t, func(t *testing.T, send testSendVariantsFn) { ++ conf := configWithNumConfs(1) ++ conf.SafeAbortNonceTooLowCount = 1 ++ h := newTestHarnessWithConfig(t, conf) +  +- index := -1 +- var nonces []uint64 +- sendTx := func(ctx context.Context, tx *types.Transaction) error { +- index++ +- nonces = append(nonces, tx.Nonce()) +- // fail every 3rd tx +- if index%3 == 0 { +- return core.ErrNonceTooLow ++ index := -1 ++ var nonces []uint64 ++ sendTx := func(ctx context.Context, tx *types.Transaction) error { ++ index++ ++ nonces = append(nonces, tx.Nonce()) ++ // fail every 3rd tx ++ if index%3 == 0 { ++ return core.ErrNonceTooLow ++ } ++ txHash := tx.Hash() ++ h.backend.mine(&txHash, tx.GasFeeCap(), nil) ++ return nil + } +- txHash := tx.Hash() +- h.backend.mine(&txHash, tx.GasFeeCap(), nil) +- return nil +- } +- h.backend.setTxSender(sendTx) ++ h.backend.setTxSender(sendTx) +  +- ctx := context.Background() +- for i := 0; i < 8; i++ { +- _, err := h.mgr.Send(ctx, TxCandidate{ +- To: &common.Address{}, +- }) +- // expect every 3rd tx to fail +- if i%3 == 0 { +- require.Error(t, err) +- } else { +- require.NoError(t, err) ++ ctx := context.Background() ++ for i := 0; i < 8; i++ { ++ _, err := send(ctx, h, TxCandidate{ ++ To: &common.Address{}, ++ }) ++ // expect every 3rd tx to fail ++ if i%3 == 0 { ++ require.Error(t, err) ++ } else { ++ require.NoError(t, err) ++ } + } +- } +  +- // internal nonce tracking should be reset to startingNonce value every 3rd tx +- require.Equal(t, []uint64{1, 1, 2, 3, 1, 2, 3, 1}, nonces) ++ // internal nonce tracking should be reset to startingNonce value every 3rd tx ++ require.Equal(t, []uint64{1, 1, 2, 3, 1, 2, 3, 1}, nonces) ++ }) + } +  + func TestMinFees(t *testing.T) { +@@ -1431,114 +1454,118 @@ } +  + // TestClose ensures that the tx manager will refuse new work and cancel any in progress + func TestClose(t *testing.T) { +- conf := configWithNumConfs(1) +- h := newTestHarnessWithConfig(t, conf) ++ testSendVariants(t, func(t *testing.T, send testSendVariantsFn) { ++ conf := configWithNumConfs(1) ++ h := newTestHarnessWithConfig(t, conf) +  +- sendingSignal := make(chan struct{}) ++ sendingSignal := make(chan struct{}) +  +- // Ensure the manager is not closed +- require.False(t, h.mgr.closed.Load()) ++ // Ensure the manager is not closed ++ require.False(t, h.mgr.closed.Load()) +  +- // sendTx will fail until it is called a retry-number of times +- called := 0 +- const retries = 4 +- sendTx := func(ctx context.Context, tx *types.Transaction) (err error) { +- called += 1 +- // sendingSignal is used when the tx begins to be sent +- if called == 1 { +- sendingSignal <- struct{}{} ++ // sendTx will fail until it is called a retry-number of times ++ called := 0 ++ const retries = 4 ++ sendTx := func(ctx context.Context, tx *types.Transaction) (err error) { ++ called += 1 ++ // sendingSignal is used when the tx begins to be sent ++ if called == 1 { ++ sendingSignal <- struct{}{} ++ } ++ if called%retries == 0 { ++ txHash := tx.Hash() ++ h.backend.mine(&txHash, tx.GasFeeCap(), big.NewInt(1)) ++ } else { ++ time.Sleep(10 * time.Millisecond) ++ err = errRpcFailure ++ } ++ return + } +- if called%retries == 0 { +- txHash := tx.Hash() +- h.backend.mine(&txHash, tx.GasFeeCap(), big.NewInt(1)) +- } else { +- time.Sleep(10 * time.Millisecond) +- err = errRpcFailure +- } +- return +- } +- h.backend.setTxSender(sendTx) ++ h.backend.setTxSender(sendTx) +  +- // on the first call, we don't use the sending signal but we still need to drain it +- go func() { +- <-sendingSignal +- }() +- // demonstrate that a tx is sent, even when it must retry repeatedly +- ctx := context.Background() +- _, err := h.mgr.Send(ctx, TxCandidate{ +- To: &common.Address{}, +- }) +- require.NoError(t, err) +- require.Equal(t, retries, called) +- called = 0 +- // Ensure the manager is *still* not closed +- require.False(t, h.mgr.closed.Load()) ++ // on the first call, we don't use the sending signal but we still need to drain it ++ go func() { ++ <-sendingSignal ++ }() ++ // demonstrate that a tx is sent, even when it must retry repeatedly ++ ctx := context.Background() ++ _, err := send(ctx, h, TxCandidate{ ++ To: &common.Address{}, ++ }) ++ require.NoError(t, err) ++ require.Equal(t, retries, called) ++ called = 0 ++ // Ensure the manager is *still* not closed ++ require.False(t, h.mgr.closed.Load()) +  +- // on the second call, we close the manager while the tx is in progress by consuming the sending signal +- go func() { +- <-sendingSignal +- h.mgr.Close() +- }() +- // demonstrate that a tx will cancel if it is in progress when the manager is closed +- _, err = h.mgr.Send(ctx, TxCandidate{ +- To: &common.Address{}, +- }) +- require.ErrorIs(t, err, ErrClosed) +- // confirm that the tx was canceled before it retried to completion +- require.Less(t, called, retries) +- require.True(t, h.mgr.closed.Load()) +- called = 0 ++ // on the second call, we close the manager while the tx is in progress by consuming the sending signal ++ go func() { ++ <-sendingSignal ++ h.mgr.Close() ++ }() ++ // demonstrate that a tx will cancel if it is in progress when the manager is closed ++ _, err = send(ctx, h, TxCandidate{ ++ To: &common.Address{}, ++ }) ++ require.ErrorIs(t, err, ErrClosed) ++ // confirm that the tx was canceled before it retried to completion ++ require.Less(t, called, retries) ++ require.True(t, h.mgr.closed.Load()) ++ called = 0 +  +- // demonstrate that new calls to Send will also fail when the manager is closed +- // there should be no need to capture the sending signal here because the manager is already closed and will return immediately +- _, err = h.mgr.Send(ctx, TxCandidate{ +- To: &common.Address{}, ++ // demonstrate that new calls to Send will also fail when the manager is closed ++ // there should be no need to capture the sending signal here because the manager is already closed and will return immediately ++ _, err = send(ctx, h, TxCandidate{ ++ To: &common.Address{}, ++ }) ++ require.ErrorIs(t, err, ErrClosed) ++ // confirm that the tx was canceled before it ever made it to the backend ++ require.Equal(t, 0, called) + }) +- require.ErrorIs(t, err, ErrClosed) +- // confirm that the tx was canceled before it ever made it to the backend +- require.Equal(t, 0, called) + } +  + // TestCloseWaitingForConfirmation ensures that the tx manager will wait for confirmation of a tx in flight, even when closed + func TestCloseWaitingForConfirmation(t *testing.T) { +- // two confirmations required so that we can mine and not yet be fully confirmed +- conf := configWithNumConfs(2) +- h := newTestHarnessWithConfig(t, conf) ++ testSendVariants(t, func(t *testing.T, send testSendVariantsFn) { ++ // two confirmations required so that we can mine and not yet be fully confirmed ++ conf := configWithNumConfs(2) ++ h := newTestHarnessWithConfig(t, conf) +  +- // sendDone is a signal that the tx has been sent from the sendTx function +- sendDone := make(chan struct{}) +- // closeDone is a signal that the txmanager has closed +- closeDone := make(chan struct{}) ++ // sendDone is a signal that the tx has been sent from the sendTx function ++ sendDone := make(chan struct{}) ++ // closeDone is a signal that the txmanager has closed ++ closeDone := make(chan struct{}) +  +- sendTx := func(ctx context.Context, tx *types.Transaction) error { +- txHash := tx.Hash() +- h.backend.mine(&txHash, tx.GasFeeCap(), big.NewInt(1)) +- close(sendDone) +- return nil +- } +- h.backend.setTxSender(sendTx) ++ sendTx := func(ctx context.Context, tx *types.Transaction) error { ++ txHash := tx.Hash() ++ h.backend.mine(&txHash, tx.GasFeeCap(), big.NewInt(1)) ++ close(sendDone) ++ return nil ++ } ++ h.backend.setTxSender(sendTx) +  +- // this goroutine will close the manager when the tx sending is complete +- // the transaction is not yet confirmed, so the manager will wait for confirmation +- go func() { +- <-sendDone +- h.mgr.Close() +- close(closeDone) +- }() ++ // this goroutine will close the manager when the tx sending is complete ++ // the transaction is not yet confirmed, so the manager will wait for confirmation ++ go func() { ++ <-sendDone ++ h.mgr.Close() ++ close(closeDone) ++ }() +  +- // this goroutine will complete confirmation of the tx when the manager is closed +- // by forcing this to happen after close, we are able to observe a closing manager waiting for confirmation +- go func() { +- <-closeDone +- h.backend.mine(nil, nil, big.NewInt(1)) +- }() ++ // this goroutine will complete confirmation of the tx when the manager is closed ++ // by forcing this to happen after close, we are able to observe a closing manager waiting for confirmation ++ go func() { ++ <-closeDone ++ h.backend.mine(nil, nil, big.NewInt(1)) ++ }() +  +- ctx := context.Background() +- _, err := h.mgr.Send(ctx, TxCandidate{ +- To: &common.Address{}, ++ ctx := context.Background() ++ _, err := send(ctx, h, TxCandidate{ ++ To: &common.Address{}, ++ }) ++ require.True(t, h.mgr.closed.Load()) ++ require.NoError(t, err) + }) +- require.True(t, h.mgr.closed.Load()) +- require.NoError(t, err) + } +  + func TestMakeSidecar(t *testing.T) { +@@ -1561,3 +1588,12 @@ require.NoError(t, eth.VerifyBlobProof((*eth.Blob)(&sidecar.Blobs[i]), commit, sidecar.Proofs[i]), "proof must be valid") + require.Equal(t, hashes[i], eth.KZGToVersionedHash(commit)) + } + } ++ ++func TestSendAsyncUnbufferedChan(t *testing.T) { ++ conf := configWithNumConfs(2) ++ h := newTestHarnessWithConfig(t, conf) ++ ++ require.Panics(t, func() { ++ h.mgr.SendAsync(context.Background(), TxCandidate{}, make(chan SendResponse)) ++ }) ++}
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+109
+
-48
+ +
+ +
+
+
diff --git OP/op-supervisor/supervisor/backend/backend.go CELO/op-supervisor/supervisor/backend/backend.go +index 9270300e5385225d9c512c98774acc1c596d7955..54b2f2eae20a093cc90fa42151af014e0ddf69e2 100644 +--- OP/op-supervisor/supervisor/backend/backend.go ++++ CELO/op-supervisor/supervisor/backend/backend.go +@@ -9,27 +9,32 @@ "path/filepath" + "sync/atomic" + "time" +  ++ "github.com/ethereum/go-ethereum/common" ++ "github.com/ethereum/go-ethereum/common/hexutil" ++ "github.com/ethereum/go-ethereum/log" ++ + "github.com/ethereum-optimism/optimism/op-service/client" + "github.com/ethereum-optimism/optimism/op-service/dial" ++ "github.com/ethereum-optimism/optimism/op-service/eth" + "github.com/ethereum-optimism/optimism/op-supervisor/config" + "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/db" + "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/db/heads" + "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/db/logs" + "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/source" +- backendTypes "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/types" + "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/frontend" + "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" +- "github.com/ethereum/go-ethereum/common" +- "github.com/ethereum/go-ethereum/common/hexutil" +- "github.com/ethereum/go-ethereum/log" + ) +  + type SupervisorBackend struct { + started atomic.Bool + logger log.Logger ++ m Metrics ++ dataDir string +  +- chainMonitors []*source.ChainMonitor ++ chainMonitors map[types.ChainID]*source.ChainMonitor + db *db.ChainsDB ++ ++ maintenanceCancel context.CancelFunc + } +  + var _ frontend.Backend = (*SupervisorBackend)(nil) +@@ -37,53 +42,79 @@ + var _ io.Closer = (*SupervisorBackend)(nil) +  + func NewSupervisorBackend(ctx context.Context, logger log.Logger, m Metrics, cfg *config.Config) (*SupervisorBackend, error) { ++ // attempt to prepare the data directory + if err := prepDataDir(cfg.Datadir); err != nil { + return nil, err + } ++ ++ // create the head tracker + headTracker, err := heads.NewHeadTracker(filepath.Join(cfg.Datadir, "heads.json")) + if err != nil { + return nil, fmt.Errorf("failed to load existing heads: %w", err) + } +- logDBs := make(map[types.ChainID]db.LogStorage) +- chainRPCs := make(map[types.ChainID]string) +- chainClients := make(map[types.ChainID]client.RPC) ++ ++ // create the chains db ++ db := db.NewChainsDB(map[types.ChainID]db.LogStorage{}, headTracker, logger) ++ ++ // create an empty map of chain monitors ++ chainMonitors := make(map[types.ChainID]*source.ChainMonitor, len(cfg.L2RPCs)) ++ ++ // create the supervisor backend ++ super := &SupervisorBackend{ ++ logger: logger, ++ m: m, ++ dataDir: cfg.Datadir, ++ chainMonitors: chainMonitors, ++ db: db, ++ } ++ ++ // from the RPC strings, have the supervisor backend create a chain monitor ++ // don't start the monitor yet, as we will start all monitors at once when Start is called + for _, rpc := range cfg.L2RPCs { +- rpcClient, chainID, err := createRpcClient(ctx, logger, rpc) ++ err := super.addFromRPC(ctx, logger, rpc, false) + if err != nil { +- return nil, err ++ return nil, fmt.Errorf("failed to add chain monitor for rpc %v: %w", rpc, err) + } +- cm := newChainMetrics(chainID, m) +- path, err := prepLogDBPath(chainID, cfg.Datadir) +- if err != nil { +- return nil, fmt.Errorf("failed to create datadir for chain %v: %w", chainID, err) +- } +- logDB, err := logs.NewFromFile(logger, cm, path) +- if err != nil { +- return nil, fmt.Errorf("failed to create logdb for chain %v at %v: %w", chainID, path, err) +- } +- logDBs[chainID] = logDB +- chainRPCs[chainID] = rpc +- chainClients[chainID] = rpcClient ++ } ++ return super, nil ++} ++ ++// addFromRPC adds a chain monitor to the supervisor backend from an rpc endpoint ++// it does not expect to be called after the backend has been started ++// it will start the monitor if shouldStart is true ++func (su *SupervisorBackend) addFromRPC(ctx context.Context, logger log.Logger, rpc string, shouldStart bool) error { ++ // create the rpc client, which yields the chain id ++ rpcClient, chainID, err := createRpcClient(ctx, logger, rpc) ++ if err != nil { ++ return err ++ } ++ su.logger.Info("adding from rpc connection", "rpc", rpc, "chainID", chainID) ++ // create metrics and a logdb for the chain ++ cm := newChainMetrics(chainID, su.m) ++ path, err := prepLogDBPath(chainID, su.dataDir) ++ if err != nil { ++ return fmt.Errorf("failed to create datadir for chain %v: %w", chainID, err) ++ } ++ logDB, err := logs.NewFromFile(logger, cm, path, true) ++ if err != nil { ++ return fmt.Errorf("failed to create logdb for chain %v at %v: %w", chainID, path, err) ++ } ++ if su.chainMonitors[chainID] != nil { ++ return fmt.Errorf("chain monitor for chain %v already exists", chainID) + } +- chainsDB := db.NewChainsDB(logDBs, headTracker) +- if err := chainsDB.Resume(); err != nil { +- return nil, fmt.Errorf("failed to resume chains db: %w", err) ++ monitor, err := source.NewChainMonitor(ctx, logger, cm, chainID, rpc, rpcClient, su.db) ++ if err != nil { ++ return fmt.Errorf("failed to create monitor for rpc %v: %w", rpc, err) + } +- +- chainMonitors := make([]*source.ChainMonitor, 0, len(cfg.L2RPCs)) +- for chainID, rpc := range chainRPCs { +- cm := newChainMetrics(chainID, m) +- monitor, err := source.NewChainMonitor(ctx, logger, cm, chainID, rpc, chainClients[chainID], chainsDB) +- if err != nil { +- return nil, fmt.Errorf("failed to create monitor for rpc %v: %w", rpc, err) ++ // start the monitor if requested ++ if shouldStart { ++ if err := monitor.Start(); err != nil { ++ return fmt.Errorf("failed to start monitor for rpc %v: %w", rpc, err) + } +- chainMonitors = append(chainMonitors, monitor) + } +- return &SupervisorBackend{ +- logger: logger, +- chainMonitors: chainMonitors, +- db: chainsDB, +- }, nil ++ su.chainMonitors[chainID] = monitor ++ su.db.AddLogDB(chainID, logDB) ++ return nil + } +  + func createRpcClient(ctx context.Context, logger log.Logger, rpc string) (client.RPC, types.ChainID, error) { +@@ -99,9 +130,15 @@ return client.NewBaseRPCClient(ethClient.Client()), types.ChainIDFromBig(chainID), nil + } +  + func (su *SupervisorBackend) Start(ctx context.Context) error { ++ // ensure we only start once + if !su.started.CompareAndSwap(false, true) { + return errors.New("already started") + } ++ // initiate "ResumeFromLastSealedBlock" on the chains db, ++ // which rewinds the database to the last block that is guaranteed to have been fully recorded ++ if err := su.db.ResumeFromLastSealedBlock(); err != nil { ++ return fmt.Errorf("failed to resume chains db: %w", err) ++ } + // start chain monitors + for _, monitor := range su.chainMonitors { + if err := monitor.Start(); err != nil { +@@ -109,20 +146,28 @@ return fmt.Errorf("failed to start chain monitor: %w", err) + } + } + // start db maintenance loop +- su.db.StartCrossHeadMaintenance(ctx) ++ maintenanceCtx, cancel := context.WithCancel(context.Background()) ++ su.db.StartCrossHeadMaintenance(maintenanceCtx) ++ su.maintenanceCancel = cancel + return nil + } +  ++var errAlreadyStopped = errors.New("already stopped") ++ + func (su *SupervisorBackend) Stop(ctx context.Context) error { + if !su.started.CompareAndSwap(true, false) { +- return errors.New("already stopped") ++ return errAlreadyStopped + } ++ // signal the maintenance loop to stop ++ su.maintenanceCancel() ++ // collect errors from stopping chain monitors + var errs error + for _, monitor := range su.chainMonitors { + if err := monitor.Stop(); err != nil { + errs = errors.Join(errs, fmt.Errorf("failed to stop chain monitor: %w", err)) + } + } ++ // close the database + if err := su.db.Close(); err != nil { + errs = errors.Join(errs, fmt.Errorf("failed to close database: %w", err)) + } +@@ -134,16 +179,26 @@ // TODO(protocol-quest#288): close logdb of all chains + return nil + } +  ++// AddL2RPC adds a new L2 chain to the supervisor backend ++// it stops and restarts the backend to add the new chain ++func (su *SupervisorBackend) AddL2RPC(ctx context.Context, rpc string) error { ++ // start the monitor immediately, as the backend is assumed to already be running ++ return su.addFromRPC(ctx, su.logger, rpc, true) ++} ++ + func (su *SupervisorBackend) CheckMessage(identifier types.Identifier, payloadHash common.Hash) (types.SafetyLevel, error) { + chainID := identifier.ChainID + blockNum := identifier.BlockNumber + logIdx := identifier.LogIndex +- ok, i, err := su.db.Check(chainID, blockNum, uint32(logIdx), backendTypes.TruncateHash(payloadHash)) ++ i, err := su.db.Check(chainID, blockNum, uint32(logIdx), payloadHash) ++ if errors.Is(err, logs.ErrFuture) { ++ return types.Unsafe, nil ++ } ++ if errors.Is(err, logs.ErrConflict) { ++ return types.Invalid, nil ++ } + if err != nil { + return types.Invalid, fmt.Errorf("failed to check log: %w", err) +- } +- if !ok { +- return types.Invalid, nil + } + safest := types.CrossUnsafe + // at this point we have the log entry, and we can check if it is safe by various criteria +@@ -181,13 +236,19 @@ // CheckBlock checks if the block is safe according to the safety level + // The block is considered safe if all logs in the block are safe + // this is decided by finding the last log in the block and + func (su *SupervisorBackend) CheckBlock(chainID *hexutil.U256, blockHash common.Hash, blockNumber hexutil.Uint64) (types.SafetyLevel, error) { +- // TODO(#11612): this function ignores blockHash and assumes that the block in the db is the one we are looking for +- // In order to check block hash, the database must *always* insert a block hash checkpoint, which is not currently done + safest := types.CrossUnsafe + // find the last log index in the block +- i, err := su.db.LastLogInBlock(types.ChainID(*chainID), uint64(blockNumber)) ++ id := eth.BlockID{Hash: blockHash, Number: uint64(blockNumber)} ++ i, err := su.db.FindSealedBlock(types.ChainID(*chainID), id) ++ if errors.Is(err, logs.ErrFuture) { ++ return types.Unsafe, nil ++ } ++ if errors.Is(err, logs.ErrConflict) { ++ return types.Invalid, nil ++ } + if err != nil { +- return types.Invalid, fmt.Errorf("failed to scan block: %w", err) ++ su.logger.Error("failed to scan block", "err", err) ++ return "", err + } + // at this point we have the extent of the block, and we can check if it is safe by various criteria + for _, checker := range []db.SafetyChecker{
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+136
+
-92
+ +
+ +
+
+
diff --git OP/op-supervisor/supervisor/backend/db/db.go CELO/op-supervisor/supervisor/backend/db/db.go +index c5948dde0b0cbef5f44485fcf49ed590897b715e..184be4df76c1861061b79b7ba12351df5ecfbf5f 100644 +--- OP/op-supervisor/supervisor/backend/db/db.go ++++ CELO/op-supervisor/supervisor/backend/db/db.go +@@ -7,13 +7,14 @@ "fmt" + "io" + "time" +  ++ "github.com/ethereum/go-ethereum/common" ++ "github.com/ethereum/go-ethereum/log" ++ + "github.com/ethereum-optimism/optimism/op-service/eth" + "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/db/entrydb" + "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/db/heads" + "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/db/logs" +- backendTypes "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/types" + "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" +- "github.com/ethereum/go-ethereum/log" + ) +  + var ( +@@ -22,15 +23,31 @@ ) +  + type LogStorage interface { + io.Closer +- AddLog(logHash backendTypes.TruncatedHash, block eth.BlockID, timestamp uint64, logIdx uint32, execMsg *backendTypes.ExecutingMessage) error ++ ++ AddLog(logHash common.Hash, parentBlock eth.BlockID, ++ logIdx uint32, execMsg *types.ExecutingMessage) error ++ ++ SealBlock(parentHash common.Hash, block eth.BlockID, timestamp uint64) error ++ + Rewind(newHeadBlockNum uint64) error +- LatestBlockNum() uint64 +- ClosestBlockInfo(blockNum uint64) (uint64, backendTypes.TruncatedHash, error) +- ClosestBlockIterator(blockNum uint64) (logs.Iterator, error) +- Contains(blockNum uint64, logIdx uint32, loghash backendTypes.TruncatedHash) (bool, entrydb.EntryIdx, error) +- LastCheckpointBehind(entrydb.EntryIdx) (logs.Iterator, error) +- NextExecutingMessage(logs.Iterator) (backendTypes.ExecutingMessage, error) ++ ++ LatestSealedBlockNum() (n uint64, ok bool) ++ ++ // FindSealedBlock finds the requested block, to check if it exists, ++ // returning the next index after it where things continue from. ++ // returns ErrFuture if the block is too new to be able to tell ++ // returns ErrDifferent if the known block does not match ++ FindSealedBlock(block eth.BlockID) (nextEntry entrydb.EntryIdx, err error) ++ ++ IteratorStartingAt(i entrydb.EntryIdx) (logs.Iterator, error) ++ ++ // returns ErrConflict if the log does not match the canonical chain. ++ // returns ErrFuture if the log is out of reach. ++ // returns nil if the log is known and matches the canonical chain. ++ Contains(blockNum uint64, logIdx uint32, logHash common.Hash) (nextIndex entrydb.EntryIdx, err error) + } ++ ++var _ LogStorage = (*logs.DB)(nil) +  + type HeadsStorage interface { + Current() *heads.Heads +@@ -40,24 +57,42 @@ + // ChainsDB is a database that stores logs and heads for multiple chains. + // it implements the ChainsStorage interface. + type ChainsDB struct { +- logDBs map[types.ChainID]LogStorage +- heads HeadsStorage ++ logDBs map[types.ChainID]LogStorage ++ heads HeadsStorage ++ maintenanceReady chan struct{} ++ logger log.Logger + } +  +-func NewChainsDB(logDBs map[types.ChainID]LogStorage, heads HeadsStorage) *ChainsDB { ++func NewChainsDB(logDBs map[types.ChainID]LogStorage, heads HeadsStorage, l log.Logger) *ChainsDB { + return &ChainsDB{ +- logDBs: logDBs, +- heads: heads, ++ logDBs: logDBs, ++ heads: heads, ++ logger: l, ++ maintenanceReady: make(chan struct{}, 1), + } + } +  +-// Resume prepares the chains db to resume recording events after a restart. +-// It rewinds the database to the last block that is guaranteed to have been fully recorded to the database ++func (db *ChainsDB) AddLogDB(chain types.ChainID, logDB LogStorage) { ++ if db.logDBs[chain] != nil { ++ log.Warn("overwriting existing logDB for chain", "chain", chain) ++ } ++ db.logDBs[chain] = logDB ++} ++ ++// ResumeFromLastSealedBlock prepares the chains db to resume recording events after a restart. ++// It rewinds the database to the last block that is guaranteed to have been fully recorded to the database, + // to ensure it can resume recording from the first log of the next block. +-func (db *ChainsDB) Resume() error { ++func (db *ChainsDB) ResumeFromLastSealedBlock() error { + for chain, logStore := range db.logDBs { +- if err := Resume(logStore); err != nil { +- return fmt.Errorf("failed to resume chain %v: %w", chain, err) ++ headNum, ok := logStore.LatestSealedBlockNum() ++ if ok { ++ // db must be empty, nothing to rewind to ++ db.logger.Info("Resuming, but found no DB contents", "chain", chain) ++ continue ++ } ++ db.logger.Info("Resuming, starting from last sealed block", "head", headNum) ++ if err := logStore.Rewind(headNum); err != nil { ++ return fmt.Errorf("failed to rewind chain %s to sealed block %d", chain, headNum) + } + } + return nil +@@ -67,25 +102,21 @@ // StartCrossHeadMaintenance starts a background process that maintains the cross-heads of the chains + // for now it does not prevent multiple instances of this process from running + func (db *ChainsDB) StartCrossHeadMaintenance(ctx context.Context) { + go func() { +- // create three safety checkers, one for each safety level +- unsafeChecker := NewSafetyChecker(Unsafe, db) +- safeChecker := NewSafetyChecker(Safe, db) +- finalizedChecker := NewSafetyChecker(Finalized, db) +- // run the maintenance loop every 10 seconds for now +- ticker := time.NewTicker(time.Second * 10) ++ db.logger.Info("cross-head maintenance loop started") ++ // run the maintenance loop every 1 seconds for now ++ ticker := time.NewTicker(time.Second * 1) + for { + select { + case <-ctx.Done(): ++ db.logger.Warn("context cancelled, stopping maintenance loop") + return + case <-ticker.C: +- for _, checker := range []SafetyChecker{ +- unsafeChecker, +- safeChecker, +- finalizedChecker} { +- if err := db.UpdateCrossHeads(checker); err != nil { +- log.Error("failed to update cross-heads", "err", err, "safety", checker.Name()) +- // we should consider exiting if an error is encountered, as the path forward is unclear +- } ++ db.logger.Debug("regular maintenance requested") ++ db.RequestMaintenance() ++ case <-db.maintenanceReady: ++ db.logger.Debug("running maintenance") ++ if err := db.updateAllHeads(); err != nil { ++ db.logger.Error("failed to update cross-heads", "err", err) + } + } + } +@@ -93,51 +124,78 @@ }() + } +  + // Check calls the underlying logDB to determine if the given log entry is safe with respect to the checker's criteria. +-func (db *ChainsDB) Check(chain types.ChainID, blockNum uint64, logIdx uint32, logHash backendTypes.TruncatedHash) (bool, entrydb.EntryIdx, error) { ++func (db *ChainsDB) Check(chain types.ChainID, blockNum uint64, logIdx uint32, logHash common.Hash) (entrydb.EntryIdx, error) { + logDB, ok := db.logDBs[chain] + if !ok { +- return false, 0, fmt.Errorf("%w: %v", ErrUnknownChain, chain) ++ return 0, fmt.Errorf("%w: %v", ErrUnknownChain, chain) + } + return logDB.Contains(blockNum, logIdx, logHash) + } +  +-// UpdateCrossSafeHeads updates the cross-heads of all chains +-// this is an example of how to use the SafetyChecker to update the cross-heads +-func (db *ChainsDB) UpdateCrossSafeHeads() error { +- checker := NewSafetyChecker(Safe, db) +- return db.UpdateCrossHeads(checker) ++// RequestMaintenance requests that the maintenance loop update the cross-heads ++// it does not block if maintenance is already scheduled ++func (db *ChainsDB) RequestMaintenance() { ++ select { ++ case db.maintenanceReady <- struct{}{}: ++ return ++ default: ++ return ++ } ++} ++ ++// updateAllHeads updates the cross-heads of all safety levels ++// it is called by the maintenance loop ++func (db *ChainsDB) updateAllHeads() error { ++ // create three safety checkers, one for each safety level ++ unsafeChecker := NewSafetyChecker(Unsafe, db) ++ safeChecker := NewSafetyChecker(Safe, db) ++ finalizedChecker := NewSafetyChecker(Finalized, db) ++ for _, checker := range []SafetyChecker{ ++ unsafeChecker, ++ safeChecker, ++ finalizedChecker} { ++ if err := db.UpdateCrossHeads(checker); err != nil { ++ return fmt.Errorf("failed to update cross-heads for safety level %v: %w", checker.Name(), err) ++ } ++ } ++ return nil + } +  + // UpdateCrossHeadsForChain updates the cross-head for a single chain. + // the provided checker controls which heads are considered. +-// TODO: we should invert control and have the underlying logDB call their own update +-// for now, monolithic control is fine. There may be a stronger reason to refactor if the API needs it. + func (db *ChainsDB) UpdateCrossHeadsForChain(chainID types.ChainID, checker SafetyChecker) error { + // start with the xsafe head of the chain + xHead := checker.CrossHeadForChain(chainID) + // advance as far as the local head + localHead := checker.LocalHeadForChain(chainID) + // get an iterator for the last checkpoint behind the x-head +- i, err := db.logDBs[chainID].LastCheckpointBehind(xHead) ++ iter, err := db.logDBs[chainID].IteratorStartingAt(xHead) + if err != nil { + return fmt.Errorf("failed to rewind cross-safe head for chain %v: %w", chainID, err) + } ++ // track if we updated the cross-head ++ updated := false + // advance the logDB through all executing messages we can + // this loop will break: + // - when we reach the local head + // - when we reach a message that is not safe + // - if an error occurs + for { +- exec, err := db.logDBs[chainID].NextExecutingMessage(i) +- if err == io.EOF { ++ if err := iter.NextExecMsg(); err == io.EOF { + break + } else if err != nil { + return fmt.Errorf("failed to read next executing message for chain %v: %w", chainID, err) + } +- // if we are now beyond the local head, stop +- if i.Index() > localHead { ++ // if we would exceed the local head, then abort ++ if iter.NextIndex() > localHead { ++ xHead = localHead // clip to local head ++ updated = localHead != xHead + break + } ++ exec := iter.ExecMessage() ++ if exec == nil { ++ panic("expected executing message after traversing to one without error") ++ } + // use the checker to determine if this message is safe + safe := checker.Check( + types.ChainIDFromUInt64(uint64(exec.Chain)), +@@ -148,14 +206,23 @@ if !safe { + break + } + // if all is well, prepare the x-head update to this point +- xHead = i.Index() ++ xHead = iter.NextIndex() ++ updated = true + } +- + // have the checker create an update to the x-head in question, and apply that update + err = db.heads.Apply(checker.Update(chainID, xHead)) + if err != nil { + return fmt.Errorf("failed to update cross-head for chain %v: %w", chainID, err) + } ++ // if any chain was updated, we can trigger a maintenance request ++ // this allows for the maintenance loop to handle cascading updates ++ // instead of waiting for the next scheduled update ++ if updated { ++ db.logger.Info("Promoting cross-head", "head", xHead, "safety-level", checker.SafetyLevel()) ++ db.RequestMaintenance() ++ } else { ++ db.logger.Info("No cross-head update", "head", xHead, "safety-level", checker.SafetyLevel()) ++ } + return nil + } +  +@@ -163,71 +230,48 @@ // UpdateCrossHeads updates the cross-heads of all chains + // based on the provided SafetyChecker. The SafetyChecker is used to determine + // the safety of each log entry in the database, and the cross-head associated with it. + func (db *ChainsDB) UpdateCrossHeads(checker SafetyChecker) error { +- currentHeads := db.heads.Current() +- for chainID := range currentHeads.Chains { +- if err := db.UpdateCrossHeadsForChain(chainID, checker); err != nil { ++ for chainID := range db.logDBs { ++ err := db.UpdateCrossHeadsForChain(chainID, checker) ++ if err != nil { + return err + } + } + return nil + } +  +-// LastLogInBlock scans through the logs of the given chain starting from the given block number, +-// and returns the index of the last log entry in that block. +-func (db *ChainsDB) LastLogInBlock(chain types.ChainID, blockNum uint64) (entrydb.EntryIdx, error) { ++func (db *ChainsDB) FindSealedBlock(chain types.ChainID, block eth.BlockID) (nextEntry entrydb.EntryIdx, err error) { + logDB, ok := db.logDBs[chain] + if !ok { + return 0, fmt.Errorf("%w: %v", ErrUnknownChain, chain) + } +- iter, err := logDB.ClosestBlockIterator(blockNum) +- if err != nil { +- return 0, fmt.Errorf("failed to get block iterator for chain %v: %w", chain, err) ++ return logDB.FindSealedBlock(block) ++} ++ ++// LatestBlockNum returns the latest fully-sealed block number that has been recorded to the logs db ++// for the given chain. It does not contain safety guarantees. ++// The block number might not be available (empty database, or non-existent chain). ++func (db *ChainsDB) LatestBlockNum(chain types.ChainID) (num uint64, ok bool) { ++ logDB, knownChain := db.logDBs[chain] ++ if !knownChain { ++ return 0, false + } +- ret := entrydb.EntryIdx(0) +- // scan through using the iterator until the block number exceeds the target +- for { +- bn, index, _, err := iter.NextLog() +- // if we have reached the end of the database, stop +- if err == io.EOF { +- break +- } +- // all other errors are fatal +- if err != nil { +- return 0, fmt.Errorf("failed to read next log entry for chain %v: %w", chain, err) +- } +- // if we are now beyond the target block, stop withour updating the return value +- if bn > blockNum { +- break +- } +- // only update the return value if the block number is the same +- // it is possible the iterator started before the target block, or that the target block is not in the db +- if bn == blockNum { +- ret = entrydb.EntryIdx(index) +- } +- } +- // if we never found the block, return an error +- if ret == 0 { +- return 0, fmt.Errorf("block %v not found in chain %v", blockNum, chain) +- } +- return ret, nil ++ return logDB.LatestSealedBlockNum() + } +  +-// LatestBlockNum returns the latest block number that has been recorded to the logs db +-// for the given chain. It does not contain safety guarantees. +-func (db *ChainsDB) LatestBlockNum(chain types.ChainID) uint64 { ++func (db *ChainsDB) SealBlock(chain types.ChainID, parentHash common.Hash, block eth.BlockID, timestamp uint64) error { + logDB, ok := db.logDBs[chain] + if !ok { +- return 0 ++ return fmt.Errorf("%w: %v", ErrUnknownChain, chain) + } +- return logDB.LatestBlockNum() ++ return logDB.SealBlock(parentHash, block, timestamp) + } +  +-func (db *ChainsDB) AddLog(chain types.ChainID, logHash backendTypes.TruncatedHash, block eth.BlockID, timestamp uint64, logIdx uint32, execMsg *backendTypes.ExecutingMessage) error { ++func (db *ChainsDB) AddLog(chain types.ChainID, logHash common.Hash, parentBlock eth.BlockID, logIdx uint32, execMsg *types.ExecutingMessage) error { + logDB, ok := db.logDBs[chain] + if !ok { + return fmt.Errorf("%w: %v", ErrUnknownChain, chain) + } +- return logDB.AddLog(logHash, block, timestamp, logIdx, execMsg) ++ return logDB.AddLog(logHash, parentBlock, logIdx, execMsg) + } +  + func (db *ChainsDB) Rewind(chain types.ChainID, headBlockNum uint64) error {
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+187
+
-207
+ +
+ +
+
+
diff --git OP/op-supervisor/supervisor/backend/db/db_test.go CELO/op-supervisor/supervisor/backend/db/db_test.go +index 4f74fe473d72354dfdfb40140243b3e004381d25..e1da3c177b108d5e6cd4e97d8bbe82d8d93f6f12 100644 +--- OP/op-supervisor/supervisor/backend/db/db_test.go ++++ CELO/op-supervisor/supervisor/backend/db/db_test.go +@@ -1,23 +1,28 @@ + package db +  + import ( +- "fmt" ++ "errors" + "io" ++ "math/rand" // nosemgrep + "testing" +  ++ "github.com/stretchr/testify/require" ++ ++ "github.com/ethereum/go-ethereum/common" ++ "github.com/ethereum/go-ethereum/log" ++ + "github.com/ethereum-optimism/optimism/op-service/eth" ++ "github.com/ethereum-optimism/optimism/op-service/testlog" + "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/db/entrydb" + "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/db/heads" + "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/db/logs" +- backendTypes "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/types" + "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" +- "github.com/stretchr/testify/require" + ) +  + func TestChainsDB_AddLog(t *testing.T) { + t.Run("UnknownChain", func(t *testing.T) { +- db := NewChainsDB(nil, &stubHeadStorage{}) +- err := db.AddLog(types.ChainIDFromUInt64(2), backendTypes.TruncatedHash{}, eth.BlockID{}, 1234, 33, nil) ++ db := NewChainsDB(nil, &stubHeadStorage{}, testlog.Logger(t, log.LevelDebug)) ++ err := db.AddLog(types.ChainIDFromUInt64(2), common.Hash{}, eth.BlockID{}, 33, nil) + require.ErrorIs(t, err, ErrUnknownChain) + }) +  +@@ -26,16 +31,20 @@ chainID := types.ChainIDFromUInt64(1) + logDB := &stubLogDB{} + db := NewChainsDB(map[types.ChainID]LogStorage{ + chainID: logDB, +- }, &stubHeadStorage{}) +- err := db.AddLog(chainID, backendTypes.TruncatedHash{}, eth.BlockID{}, 1234, 33, nil) ++ }, &stubHeadStorage{}, testlog.Logger(t, log.LevelDebug)) ++ bl10 := eth.BlockID{Hash: common.Hash{0x10}, Number: 10} ++ err := db.SealBlock(chainID, common.Hash{0x9}, bl10, 1234) ++ require.NoError(t, err, err) ++ err = db.AddLog(chainID, common.Hash{}, bl10, 0, nil) + require.NoError(t, err, err) + require.Equal(t, 1, logDB.addLogCalls) ++ require.Equal(t, 1, logDB.sealBlockCalls) + }) + } +  + func TestChainsDB_Rewind(t *testing.T) { + t.Run("UnknownChain", func(t *testing.T) { +- db := NewChainsDB(nil, &stubHeadStorage{}) ++ db := NewChainsDB(nil, &stubHeadStorage{}, testlog.Logger(t, log.LevelDebug)) + err := db.Rewind(types.ChainIDFromUInt64(2), 42) + require.ErrorIs(t, err, ErrUnknownChain) + }) +@@ -45,145 +54,34 @@ chainID := types.ChainIDFromUInt64(1) + logDB := &stubLogDB{} + db := NewChainsDB(map[types.ChainID]LogStorage{ + chainID: logDB, +- }, &stubHeadStorage{}) ++ }, &stubHeadStorage{}, ++ testlog.Logger(t, log.LevelDebug)) + err := db.Rewind(chainID, 23) + require.NoError(t, err, err) + require.EqualValues(t, 23, logDB.headBlockNum) + }) + } +  +-func TestChainsDB_LastLogInBlock(t *testing.T) { +- // using a chainID of 1 for simplicity +- chainID := types.ChainIDFromUInt64(1) +- // get default stubbed components +- logDB, _, h := setupStubbedForUpdateHeads(chainID) +- logDB.nextLogs = []nextLogResponse{ +- {10, 1, backendTypes.TruncatedHash{}, nil}, +- {10, 2, backendTypes.TruncatedHash{}, nil}, +- {10, 3, backendTypes.TruncatedHash{}, nil}, +- {10, 4, backendTypes.TruncatedHash{}, nil}, +- {11, 5, backendTypes.TruncatedHash{}, nil}, +- } +- +- // The ChainsDB is real, but uses only stubbed components +- db := NewChainsDB( +- map[types.ChainID]LogStorage{ +- chainID: logDB}, +- &stubHeadStorage{h}) +- +- // LastLogInBlock is expected to: +- // 1. get a block iterator for block 10 (stubbed) +- // 2. scan through the iterator until the block number exceeds the target (10) +- // 3. return the index of the last log in the block (4) +- index, err := db.LastLogInBlock(chainID, 10) +- require.NoError(t, err) +- require.Equal(t, entrydb.EntryIdx(4), index) +-} +- +-func TestChainsDB_LastLogInBlockEOF(t *testing.T) { +- // using a chainID of 1 for simplicity +- chainID := types.ChainIDFromUInt64(1) +- // get default stubbed components +- logDB, _, h := setupStubbedForUpdateHeads(chainID) +- logDB.nextLogs = []nextLogResponse{ +- {10, 5, backendTypes.TruncatedHash{}, nil}, +- {10, 6, backendTypes.TruncatedHash{}, nil}, +- {10, 7, backendTypes.TruncatedHash{}, nil}, +- {10, 8, backendTypes.TruncatedHash{}, nil}, +- {10, 9, backendTypes.TruncatedHash{}, nil}, +- {10, 10, backendTypes.TruncatedHash{}, nil}, +- } +- +- // The ChainsDB is real, but uses only stubbed components +- db := NewChainsDB( +- map[types.ChainID]LogStorage{ +- chainID: logDB}, +- &stubHeadStorage{h}) +- +- // LastLogInBlock is expected to: +- // 1. get a block iterator for block 10 (stubbed) +- // 2. scan through the iterator and never find the target block +- // return an error +- index, err := db.LastLogInBlock(chainID, 10) +- require.NoError(t, err) +- require.Equal(t, entrydb.EntryIdx(10), index) +-} +- +-func TestChainsDB_LastLogInBlockNotFound(t *testing.T) { +- // using a chainID of 1 for simplicity +- chainID := types.ChainIDFromUInt64(1) +- // get default stubbed components +- logDB, _, h := setupStubbedForUpdateHeads(chainID) +- logDB.nextLogs = []nextLogResponse{ +- {100, 5, backendTypes.TruncatedHash{}, nil}, +- {100, 6, backendTypes.TruncatedHash{}, nil}, +- {100, 7, backendTypes.TruncatedHash{}, nil}, +- {101, 8, backendTypes.TruncatedHash{}, nil}, +- {101, 9, backendTypes.TruncatedHash{}, nil}, +- {101, 10, backendTypes.TruncatedHash{}, nil}, +- } +- +- // The ChainsDB is real, but uses only stubbed components +- db := NewChainsDB( +- map[types.ChainID]LogStorage{ +- chainID: logDB}, +- &stubHeadStorage{h}) +- +- // LastLogInBlock is expected to: +- // 1. get a block iterator for block 10 (stubbed) +- // 2. scan through the iterator and never find the target block +- // return an error +- _, err := db.LastLogInBlock(chainID, 10) +- require.ErrorContains(t, err, "block 10 not found") +-} +- +-func TestChainsDB_LastLogInBlockError(t *testing.T) { +- // using a chainID of 1 for simplicity +- chainID := types.ChainIDFromUInt64(1) +- // get default stubbed components +- logDB, _, h := setupStubbedForUpdateHeads(chainID) +- logDB.nextLogs = []nextLogResponse{ +- {10, 1, backendTypes.TruncatedHash{}, nil}, +- {10, 2, backendTypes.TruncatedHash{}, nil}, +- {10, 3, backendTypes.TruncatedHash{}, nil}, +- {0, 0, backendTypes.TruncatedHash{}, fmt.Errorf("some error")}, +- {11, 5, backendTypes.TruncatedHash{}, nil}, +- } +- +- // The ChainsDB is real, but uses only stubbed components +- db := NewChainsDB( +- map[types.ChainID]LogStorage{ +- chainID: logDB}, +- &stubHeadStorage{h}) +- +- // LastLogInBlock is expected to: +- // 1. get a block iterator for block 10 (stubbed) +- // 2. scan through the iterator and encounter an error +- // return an error +- _, err := db.LastLogInBlock(chainID, 10) +- require.ErrorContains(t, err, "some error") +-} +- + func TestChainsDB_UpdateCrossHeads(t *testing.T) { + // using a chainID of 1 for simplicity + chainID := types.ChainIDFromUInt64(1) + // get default stubbed components + logDB, checker, h := setupStubbedForUpdateHeads(chainID) +  ++ checker.numSafe = 1 ++ xSafe := checker.crossHeadForChain ++ + // The ChainsDB is real, but uses only stubbed components + db := NewChainsDB( + map[types.ChainID]LogStorage{ + chainID: logDB}, +- &stubHeadStorage{h}) ++ &stubHeadStorage{h}, ++ testlog.Logger(t, log.LevelDebug)) +  +- // Update cross-heads is expected to: +- // 1. get a last checkpoint iterator from the logDB (stubbed to be at 15) +- // 2. progress the iterator to the next log (16) because the first safety check will pass +- // 3. fail the second safety check +- // 4. update the cross-heads to the last successful safety check (16) + err := db.UpdateCrossHeads(checker) + require.NoError(t, err) +- require.Equal(t, entrydb.EntryIdx(16), checker.updated) ++ // found a safe executing message, and no new initiating messages ++ require.Equal(t, xSafe+1, checker.updated) + } +  + func TestChainsDB_UpdateCrossHeadsBeyondLocal(t *testing.T) { +@@ -191,14 +89,17 @@ // using a chainID of 1 for simplicity + chainID := types.ChainIDFromUInt64(1) + // get default stubbed components + logDB, checker, h := setupStubbedForUpdateHeads(chainID) +- // set the safety checker to pass 99 times, effeciively allowing all messages to be safe ++ // set the safety checker to pass 99 times, effectively allowing all messages to be safe + checker.numSafe = 99 ++ ++ startLocalSafe := checker.localHeadForChain +  + // The ChainsDB is real, but uses only stubbed components + db := NewChainsDB( + map[types.ChainID]LogStorage{ + chainID: logDB}, +- &stubHeadStorage{h}) ++ &stubHeadStorage{h}, ++ testlog.Logger(t, log.LevelDebug)) +  + // Update cross-heads is expected to: + // 1. get a last checkpoint iterator from the logDB (stubbed to be at 15) +@@ -206,7 +107,7 @@ // 2. progress the iterator to repeatedly, as the safety check will pass 99 times. + // 3. exceed the local head, and update the cross-head to the local head (40) + err := db.UpdateCrossHeads(checker) + require.NoError(t, err) +- require.Equal(t, entrydb.EntryIdx(40), checker.updated) ++ require.Equal(t, startLocalSafe, checker.updated) + } +  + func TestChainsDB_UpdateCrossHeadsEOF(t *testing.T) { +@@ -215,24 +116,25 @@ chainID := types.ChainIDFromUInt64(1) + // get default stubbed components + logDB, checker, h := setupStubbedForUpdateHeads(chainID) + // set the log DB to return an EOF error when trying to get the next executing message +- // after processing 10 messages as safe (with more messages available to be safe) +- logDB.errOverload = io.EOF +- logDB.errAfter = 10 ++ // after processing 10 message (with more messages available to be safe) ++ logDB.nextLogs = logDB.nextLogs[:checker.crossHeadForChain+11] ++ // This is a legacy test, the local head is further than the DB content... ++ + checker.numSafe = 99 +  + // The ChainsDB is real, but uses only stubbed components + db := NewChainsDB( + map[types.ChainID]LogStorage{ + chainID: logDB}, +- &stubHeadStorage{h}) ++ &stubHeadStorage{h}, ++ testlog.Logger(t, log.LevelDebug)) +  + // Update cross-heads is expected to: +- // 1. get a last checkpoint iterator from the logDB (stubbed to be at 15) +- // 2. after processing 10 messages as safe, fail to find any executing messages (EOF) +- // 3. update to the last successful safety check (25) without returning an error ++ // - process 10 logs as safe, 5 of which execute something ++ // - update cross-safe to what was there + err := db.UpdateCrossHeads(checker) + require.NoError(t, err) +- require.Equal(t, entrydb.EntryIdx(25), checker.updated) ++ require.Equal(t, checker.crossHeadForChain+11, checker.updated) + } +  + func TestChainsDB_UpdateCrossHeadsError(t *testing.T) { +@@ -242,15 +144,26 @@ // get default stubbed components + logDB, checker, h := setupStubbedForUpdateHeads(chainID) + // set the log DB to return an error when trying to get the next executing message + // after processing 3 messages as safe (with more messages available to be safe) +- logDB.errOverload = fmt.Errorf("some error") +- logDB.errAfter = 3 ++ ++ executed := 0 ++ for i, e := range logDB.nextLogs { ++ if executed == 3 { ++ logDB.nextLogs[i].err = errors.New("some error") ++ } ++ if entrydb.EntryIdx(i) > checker.crossHeadForChain && e.execIdx >= 0 { ++ executed++ ++ } ++ } ++ ++ // everything is safe until error + checker.numSafe = 99 +  + // The ChainsDB is real, but uses only stubbed components + db := NewChainsDB( + map[types.ChainID]LogStorage{ + chainID: logDB}, +- &stubHeadStorage{h}) ++ &stubHeadStorage{h}, ++ testlog.Logger(t, log.LevelDebug)) +  + // Update cross-heads is expected to: + // 1. get a last checkpoint iterator from the logDB (stubbed to be at 10) +@@ -268,8 +181,6 @@ // TODO: the variables at the top of this function should be configurable by the caller. + // this isn't an issue for now, as all tests can modify the stubbed components directly after calling this function. + // but readability and maintainability would be improved by making this function more configurable. + func setupStubbedForUpdateHeads(chainID types.ChainID) (*stubLogDB, *stubChecker, *heads.Heads) { +- // the checkpoint starts somewhere behind the last known cross-safe head +- checkpoint := entrydb.EntryIdx(15) + // the last known cross-safe head is at 20 + cross := entrydb.EntryIdx(20) + // the local head (the limit of the update) is at 40 +@@ -278,23 +189,43 @@ // the number of executing messages to make available (this should be more than the number of safety checks performed) + numExecutingMessages := 30 + // number of safety checks that will pass before returning false + numSafe := 1 +- // number of calls to nextExecutingMessage before potentially returning an error +- errAfter := 4 +  + // set up stubbed logDB + logDB := &stubLogDB{} +- // the log DB will start the iterator at the checkpoint index +- logDB.lastCheckpointBehind = &stubIterator{checkpoint, 0, nil} +- // rig the log DB to return an error after a certain number of calls to NextExecutingMessage +- logDB.errAfter = errAfter ++ + // set up stubbed executing messages that the ChainsDB can pass to the checker +- logDB.executingMessages = []*backendTypes.ExecutingMessage{} ++ logDB.executingMessages = []*types.ExecutingMessage{} + for i := 0; i < numExecutingMessages; i++ { + // executing messages are packed in groups of 3, with block numbers increasing by 1 +- logDB.executingMessages = append(logDB.executingMessages, &backendTypes.ExecutingMessage{ ++ logDB.executingMessages = append(logDB.executingMessages, &types.ExecutingMessage{ + BlockNum: uint64(100 + int(i/3)), + LogIdx: uint32(i), +- Hash: backendTypes.TruncatedHash{}, ++ Hash: common.Hash{}, ++ }) ++ } ++ ++ rng := rand.New(rand.NewSource(123)) ++ blockNum := uint64(100) ++ logIndex := uint32(0) ++ executedCount := 0 ++ for i := entrydb.EntryIdx(0); i <= local; i++ { ++ var logHash common.Hash ++ rng.Read(logHash[:]) ++ ++ execIndex := -1 ++ // All the even messages have an executing message ++ if i%2 == 0 { ++ execIndex = rng.Intn(len(logDB.executingMessages)) ++ executedCount += 1 ++ } ++ var msgErr error ++ ++ logDB.nextLogs = append(logDB.nextLogs, nextLogResponse{ ++ blockNum: blockNum, ++ logIdx: logIndex, ++ evtHash: logHash, ++ err: msgErr, ++ execIdx: execIndex, + }) + } +  +@@ -334,7 +265,7 @@ return s.crossHeadForChain + } +  + // stubbed Check returns true for the first numSafe calls, and false thereafter +-func (s *stubChecker) Check(chain types.ChainID, blockNum uint64, logIdx uint32, logHash backendTypes.TruncatedHash) bool { ++func (s *stubChecker) Check(chain types.ChainID, blockNum uint64, logIdx uint32, logHash common.Hash) bool { + if s.checkCalls >= s.numSafe { + return false + } +@@ -370,89 +301,138 @@ } +  + type nextLogResponse struct { + blockNum uint64 +- logIdx uint32 +- evtHash backendTypes.TruncatedHash +- err error ++ ++ logIdx uint32 ++ ++ evtHash common.Hash ++ ++ err error ++ ++ // -1 if not executing ++ execIdx int + } ++ + type stubIterator struct { +- index entrydb.EntryIdx +- nextLogIndex int +- nextLogs []nextLogResponse ++ index entrydb.EntryIdx ++ ++ db *stubLogDB ++} ++ ++func (s *stubIterator) End() error { ++ return nil // only used for DB-loading. The stub is already loaded + } +  +-func (s *stubIterator) NextLog() (uint64, uint32, backendTypes.TruncatedHash, error) { +- if s.nextLogIndex >= len(s.nextLogs) { +- return 0, 0, backendTypes.TruncatedHash{}, io.EOF ++func (s *stubIterator) NextInitMsg() error { ++ s.index += 1 ++ if s.index >= entrydb.EntryIdx(len(s.db.nextLogs)) { ++ return io.EOF + } +- r := s.nextLogs[s.nextLogIndex] +- s.nextLogIndex++ +- return r.blockNum, r.logIdx, r.evtHash, r.err ++ e := s.db.nextLogs[s.index] ++ return e.err + } +  +-func (s *stubIterator) Index() entrydb.EntryIdx { +- return s.index ++func (s *stubIterator) NextExecMsg() error { ++ for { ++ s.index += 1 ++ if s.index >= entrydb.EntryIdx(len(s.db.nextLogs)) { ++ return io.EOF ++ } ++ e := s.db.nextLogs[s.index] ++ if e.err != nil { ++ return e.err ++ } ++ if e.execIdx >= 0 { ++ return nil ++ } ++ } + } +-func (s *stubIterator) ExecMessage() (backendTypes.ExecutingMessage, error) { +- panic("not implemented") ++ ++func (s *stubIterator) NextBlock() error { ++ panic("not yet supported") + } +  +-type stubLogDB struct { +- addLogCalls int +- headBlockNum uint64 +- emIndex int +- executingMessages []*backendTypes.ExecutingMessage +- nextLogs []nextLogResponse +- lastCheckpointBehind *stubIterator +- errOverload error +- errAfter int +- containsResponse containsResponse ++func (s *stubIterator) NextIndex() entrydb.EntryIdx { ++ return s.index + 1 + } +  +-// stubbed LastCheckpointBehind returns a stubbed iterator which was passed in to the struct +-func (s *stubLogDB) LastCheckpointBehind(entrydb.EntryIdx) (logs.Iterator, error) { +- return s.lastCheckpointBehind, nil ++func (s *stubIterator) SealedBlock() (hash common.Hash, num uint64, ok bool) { ++ panic("not yet supported") + } +  +-func (s *stubLogDB) ClosestBlockIterator(blockNum uint64) (logs.Iterator, error) { +- return &stubIterator{ +- index: entrydb.EntryIdx(99), +- nextLogs: s.nextLogs, +- }, nil ++func (s *stubIterator) InitMessage() (hash common.Hash, logIndex uint32, ok bool) { ++ if s.index < 0 { ++ return common.Hash{}, 0, false ++ } ++ if s.index >= entrydb.EntryIdx(len(s.db.nextLogs)) { ++ return common.Hash{}, 0, false ++ } ++ e := s.db.nextLogs[s.index] ++ return e.evtHash, e.logIdx, true + } +  +-func (s *stubLogDB) NextExecutingMessage(i logs.Iterator) (backendTypes.ExecutingMessage, error) { +- // if error overload is set, return it to simulate a failure condition +- if s.errOverload != nil && s.emIndex >= s.errAfter { +- return backendTypes.ExecutingMessage{}, s.errOverload ++func (s *stubIterator) ExecMessage() *types.ExecutingMessage { ++ if s.index < 0 { ++ return nil + } +- // increment the iterator to mark advancement +- i.(*stubIterator).index += 1 +- // return the next executing message +- m := *s.executingMessages[s.emIndex] +- // and increment to the next message for the next call +- s.emIndex++ +- return m, nil ++ if s.index >= entrydb.EntryIdx(len(s.db.nextLogs)) { ++ return nil ++ } ++ e := s.db.nextLogs[s.index] ++ if e.execIdx < 0 { ++ return nil ++ } ++ return s.db.executingMessages[e.execIdx] + } +  +-func (s *stubLogDB) ClosestBlockInfo(_ uint64) (uint64, backendTypes.TruncatedHash, error) { +- panic("not implemented") ++var _ logs.Iterator = (*stubIterator)(nil) ++ ++type stubLogDB struct { ++ addLogCalls int ++ sealBlockCalls int ++ headBlockNum uint64 ++ ++ executingMessages []*types.ExecutingMessage ++ nextLogs []nextLogResponse ++ ++ containsResponse containsResponse + } +  +-func (s *stubLogDB) AddLog(logHash backendTypes.TruncatedHash, block eth.BlockID, timestamp uint64, logIdx uint32, execMsg *backendTypes.ExecutingMessage) error { ++func (s *stubLogDB) AddLog(logHash common.Hash, parentBlock eth.BlockID, logIdx uint32, execMsg *types.ExecutingMessage) error { + s.addLogCalls++ + return nil + } +  ++func (s *stubLogDB) SealBlock(parentHash common.Hash, block eth.BlockID, timestamp uint64) error { ++ s.sealBlockCalls++ ++ return nil ++} ++ ++func (s *stubLogDB) LatestSealedBlockNum() (n uint64, ok bool) { ++ return s.headBlockNum, true ++} ++ ++func (s *stubLogDB) FindSealedBlock(block eth.BlockID) (nextEntry entrydb.EntryIdx, err error) { ++ panic("not implemented") ++} ++ ++func (s *stubLogDB) IteratorStartingAt(i entrydb.EntryIdx) (logs.Iterator, error) { ++ return &stubIterator{ ++ index: i - 1, ++ db: s, ++ }, nil ++} ++ ++var _ LogStorage = (*stubLogDB)(nil) ++ + type containsResponse struct { +- contains bool +- index entrydb.EntryIdx +- err error ++ index entrydb.EntryIdx ++ err error + } +  + // stubbed Contains records the arguments passed to it + // it returns the response set in the struct, or an empty response +-func (s *stubLogDB) Contains(blockNum uint64, logIdx uint32, loghash backendTypes.TruncatedHash) (bool, entrydb.EntryIdx, error) { +- return s.containsResponse.contains, s.containsResponse.index, s.containsResponse.err ++func (s *stubLogDB) Contains(blockNum uint64, logIdx uint32, logHash common.Hash) (nextIndex entrydb.EntryIdx, err error) { ++ return s.containsResponse.index, s.containsResponse.err + } +  + func (s *stubLogDB) Rewind(newHeadBlockNum uint64) error {
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+61
+
-2
+ +
+ +
+
+
diff --git OP/op-supervisor/supervisor/backend/db/entrydb/entry_db.go CELO/op-supervisor/supervisor/backend/db/entrydb/entry_db.go +index 9d0ffc729efdeaa75f8bd85fb0b4b52a0b2a273c..a260d143ddb5971644c149b156c00ad8208279e7 100644 +--- OP/op-supervisor/supervisor/backend/db/entrydb/entry_db.go ++++ CELO/op-supervisor/supervisor/backend/db/entrydb/entry_db.go +@@ -10,13 +10,72 @@ "github.com/ethereum/go-ethereum/log" + ) +  + const ( +- EntrySize = 24 ++ EntrySize = 34 + ) +  + type EntryIdx int64 +  + type Entry [EntrySize]byte +  ++func (entry Entry) Type() EntryType { ++ return EntryType(entry[0]) ++} ++ ++type EntryTypeFlag uint8 ++ ++const ( ++ FlagSearchCheckpoint EntryTypeFlag = 1 << TypeSearchCheckpoint ++ FlagCanonicalHash EntryTypeFlag = 1 << TypeCanonicalHash ++ FlagInitiatingEvent EntryTypeFlag = 1 << TypeInitiatingEvent ++ FlagExecutingLink EntryTypeFlag = 1 << TypeExecutingLink ++ FlagExecutingCheck EntryTypeFlag = 1 << TypeExecutingCheck ++ FlagPadding EntryTypeFlag = 1 << TypePadding ++ // for additional padding ++ FlagPadding2 EntryTypeFlag = FlagPadding << 1 ++) ++ ++func (ex EntryTypeFlag) Any(v EntryTypeFlag) bool { ++ return ex&v != 0 ++} ++ ++func (ex *EntryTypeFlag) Add(v EntryTypeFlag) { ++ *ex = *ex | v ++} ++ ++func (ex *EntryTypeFlag) Remove(v EntryTypeFlag) { ++ *ex = *ex &^ v ++} ++ ++type EntryType uint8 ++ ++const ( ++ TypeSearchCheckpoint EntryType = iota ++ TypeCanonicalHash ++ TypeInitiatingEvent ++ TypeExecutingLink ++ TypeExecutingCheck ++ TypePadding ++) ++ ++func (d EntryType) String() string { ++ switch d { ++ case TypeSearchCheckpoint: ++ return "searchCheckpoint" ++ case TypeCanonicalHash: ++ return "canonicalHash" ++ case TypeInitiatingEvent: ++ return "initiatingEvent" ++ case TypeExecutingLink: ++ return "executingLink" ++ case TypeExecutingCheck: ++ return "executingCheck" ++ case TypePadding: ++ return "padding" ++ default: ++ return fmt.Sprintf("unknown-%d", uint8(d)) ++ } ++} ++ + // dataAccess defines a minimal API required to manipulate the actual stored data. + // It is a subset of the os.File API but could (theoretically) be satisfied by an in-memory implementation for testing. + type dataAccess interface { +@@ -54,7 +113,7 @@ data: file, + lastEntryIdx: EntryIdx(size - 1), + } + if size*EntrySize != info.Size() { +- logger.Warn("File size is nut a multiple of entry size. Truncating to last complete entry", "fileSize", size, "entrySize", EntrySize) ++ logger.Warn("File size is not a multiple of entry size. Truncating to last complete entry", "fileSize", size, "entrySize", EntrySize) + if err := db.recover(); err != nil { + return nil, fmt.Errorf("failed to recover database at %v: %w", path, err) + }
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+2
+
-1
+ +
+ +
+
+
diff --git OP/op-supervisor/supervisor/backend/db/heads/heads.go CELO/op-supervisor/supervisor/backend/db/heads/heads.go +index 65d1cb42abccff63de908cad7a928b1981c14d45..7504806c0435257b099081c67b26e853f3e41df5 100644 +--- OP/op-supervisor/supervisor/backend/db/heads/heads.go ++++ CELO/op-supervisor/supervisor/backend/db/heads/heads.go +@@ -7,6 +7,7 @@ "fmt" + "os" + "sync" +  ++ "github.com/ethereum-optimism/optimism/op-service/ioutil" + "github.com/ethereum-optimism/optimism/op-service/jsonutil" + ) +  +@@ -58,7 +59,7 @@ return t.current.Copy() + } +  + func (t *HeadTracker) write(heads *Heads) error { +- if err := jsonutil.WriteJSON(t.path, heads, 0o644); err != nil { ++ if err := jsonutil.WriteJSON(heads, ioutil.ToAtomicFile(t.path, 0o644)); err != nil { + return fmt.Errorf("failed to write new heads: %w", err) + } + return nil
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + (deleted) + +
+
+
+ +
+ +
+ +
+0
+
-34
+ +
+ +
+
+
diff --git OP/op-supervisor/supervisor/backend/db/init.go CELO/op-supervisor/supervisor/backend/db/init.go +deleted file mode 100644 +index fe6b51e5c21fe4408782b84889e752422834255a..0000000000000000000000000000000000000000 +--- OP/op-supervisor/supervisor/backend/db/init.go ++++ /dev/null +@@ -1,34 +0,0 @@ +-package db +- +-import ( +- "errors" +- "fmt" +- "io" +- "math" +-) +- +-// Resume prepares the given LogStore to resume recording events. +-// It returns the block number of the last block that is guaranteed to have been fully recorded to the database +-// and rewinds the database to ensure it can resume recording from the first log of the next block. +-func Resume(logDB LogStorage) error { +- // Get the last checkpoint that was written then Rewind the db +- // to the block prior to that block and start from there. +- // Guarantees we will always roll back at least one block +- // so we know we're always starting from a fully written block. +- checkPointBlock, _, err := logDB.ClosestBlockInfo(math.MaxUint64) +- if errors.Is(err, io.EOF) { +- // No blocks recorded in the database, start from genesis +- return nil +- } else if err != nil { +- return fmt.Errorf("failed to get block from checkpoint: %w", err) +- } +- if checkPointBlock == 0 { +- return nil +- } +- block := checkPointBlock - 1 +- err = logDB.Rewind(block) +- if err != nil { +- return fmt.Errorf("failed to rewind the database: %w", err) +- } +- return nil +-}
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + (deleted) + +
+
+
+ +
+ +
+ +
+0
+
-91
+ +
+ +
+
+
diff --git OP/op-supervisor/supervisor/backend/db/init_test.go CELO/op-supervisor/supervisor/backend/db/init_test.go +deleted file mode 100644 +index 5ff44c524e5b5b48efb1d145c3891281bcb0bc5e..0000000000000000000000000000000000000000 +--- OP/op-supervisor/supervisor/backend/db/init_test.go ++++ /dev/null +@@ -1,91 +0,0 @@ +-package db +- +-import ( +- "fmt" +- "io" +- "testing" +- +- "github.com/ethereum-optimism/optimism/op-service/eth" +- "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/db/entrydb" +- "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/db/logs" +- "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/types" +- "github.com/stretchr/testify/require" +-) +- +-func TestRecover(t *testing.T) { +- tests := []struct { +- name string +- stubDB *stubLogStore +- expectRewoundTo uint64 +- }{ +- { +- name: "emptydb", +- stubDB: &stubLogStore{closestBlockErr: fmt.Errorf("no entries: %w", io.EOF)}, +- expectRewoundTo: 0, +- }, +- { +- name: "genesis", +- stubDB: &stubLogStore{}, +- expectRewoundTo: 0, +- }, +- { +- name: "with_blocks", +- stubDB: &stubLogStore{closestBlockNumber: 15}, +- expectRewoundTo: 14, +- }, +- } +- for _, test := range tests { +- test := test +- t.Run(test.name, func(t *testing.T) { +- err := Resume(test.stubDB) +- require.NoError(t, err) +- require.Equal(t, test.expectRewoundTo, test.stubDB.rewoundTo) +- }) +- } +-} +- +-type stubLogStore struct { +- closestBlockNumber uint64 +- closestBlockErr error +- rewoundTo uint64 +-} +- +-func (s *stubLogStore) Contains(blockNum uint64, logIdx uint32, loghash types.TruncatedHash) (bool, entrydb.EntryIdx, error) { +- panic("not supported") +-} +- +-func (s *stubLogStore) ClosestBlockIterator(blockNum uint64) (logs.Iterator, error) { +- panic("not supported") +-} +- +-func (s *stubLogStore) LastCheckpointBehind(entrydb.EntryIdx) (logs.Iterator, error) { +- panic("not supported") +-} +- +-func (s *stubLogStore) ClosestBlockInfo(blockNum uint64) (uint64, types.TruncatedHash, error) { +- if s.closestBlockErr != nil { +- return 0, types.TruncatedHash{}, s.closestBlockErr +- } +- return s.closestBlockNumber, types.TruncatedHash{}, nil +-} +- +-func (s *stubLogStore) NextExecutingMessage(logs.Iterator) (types.ExecutingMessage, error) { +- panic("not supported") +-} +- +-func (s *stubLogStore) Rewind(headBlockNum uint64) error { +- s.rewoundTo = headBlockNum +- return nil +-} +- +-func (s *stubLogStore) AddLog(logHash types.TruncatedHash, block eth.BlockID, timestamp uint64, logIdx uint32, execMsg *types.ExecutingMessage) error { +- panic("not supported") +-} +- +-func (s *stubLogStore) LatestBlockNum() uint64 { +- panic("not supported") +-} +- +-func (s *stubLogStore) Close() error { +- return nil +-}
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+303
+
-370
+ +
+ +
+
+
diff --git OP/op-supervisor/supervisor/backend/db/logs/db.go CELO/op-supervisor/supervisor/backend/db/logs/db.go +index 0f757f5254cd0746611c44ffce7c556a2e6f2f89..996a5c68d712c3a84fd377b044a1cace9f8e6f29 100644 +--- OP/op-supervisor/supervisor/backend/db/logs/db.go ++++ CELO/op-supervisor/supervisor/backend/db/logs/db.go +@@ -4,44 +4,40 @@ import ( + "errors" + "fmt" + "io" +- "math" + "sync" +  +- "github.com/ethereum-optimism/optimism/op-service/eth" +- "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/db/entrydb" +- "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/types" ++ "github.com/ethereum/go-ethereum/common" ++ "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/log" +-) +  +-const ( +- searchCheckpointFrequency = 256 +- +- eventFlagIncrementLogIdx = byte(1) +- eventFlagHasExecutingMessage = byte(1) << 1 ++ "github.com/ethereum-optimism/optimism/op-service/eth" ++ "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/db/entrydb" ++ "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" + ) +  + const ( +- typeSearchCheckpoint byte = iota +- typeCanonicalHash +- typeInitiatingEvent +- typeExecutingLink +- typeExecutingCheck ++ searchCheckpointFrequency = 256 ++ eventFlagHasExecutingMessage = byte(1) + ) +  + var ( +- ErrLogOutOfOrder = errors.New("log out of order") ++ // ErrLogOutOfOrder happens when you try to add a log to the DB, ++ // but it does not actually fit onto the latest data (by being too old or new). ++ ErrLogOutOfOrder = errors.New("log out of order") ++ // ErrDataCorruption happens when the underlying DB has some I/O issue + ErrDataCorruption = errors.New("data corruption") +- ErrNotFound = errors.New("not found") ++ // ErrSkipped happens when we try to retrieve data that is not available (pruned) ++ // It may also happen if we erroneously skip data, that was not considered a conflict, if the DB is corrupted. ++ ErrSkipped = errors.New("skipped data") ++ // ErrFuture happens when data is just not yet available ++ ErrFuture = errors.New("future data") ++ // ErrConflict happens when we know for sure that there is different canonical data ++ ErrConflict = errors.New("conflicting data") + ) +  + type Metrics interface { + RecordDBEntryCount(count int64) + RecordDBSearchEntriesRead(count int64) +-} +- +-type logContext struct { +- blockNum uint64 +- logIdx uint32 + } +  + type EntryStore interface { +@@ -60,28 +56,6 @@ // + // Use a fixed 24 bytes per entry. + // + // Data is an append-only log, that can be binary searched for any necessary event data. +-// +-// Rules: +-// if entry_index % 256 == 0: must be type 0. For easy binary search. +-// type 1 always adjacent to type 0 +-// type 2 "diff" values are offsets from type 0 values (always within 256 entries range) +-// type 3 always after type 2 +-// type 4 always after type 3 +-// +-// Types (<type> = 1 byte): +-// type 0: "search checkpoint" <type><uint64 block number: 8 bytes><uint32 event index offset: 4 bytes><uint64 timestamp: 8 bytes> = 20 bytes +-// type 1: "canonical hash" <type><parent blockhash truncated: 20 bytes> = 21 bytes +-// type 2: "initiating event" <type><blocknum diff: 1 byte><event flags: 1 byte><event-hash: 20 bytes> = 23 bytes +-// type 3: "executing link" <type><chain: 4 bytes><blocknum: 8 bytes><event index: 3 bytes><uint64 timestamp: 8 bytes> = 24 bytes +-// type 4: "executing check" <type><event-hash: 20 bytes> = 21 bytes +-// other types: future compat. E.g. for linking to L1, registering block-headers as a kind of initiating-event, tracking safe-head progression, etc. +-// +-// Right-pad each entry that is not 24 bytes. +-// +-// event-flags: each bit represents a boolean value, currently only two are defined +-// * event-flags & 0x01 - true if the log index should increment. Should only be false when the event is immediately after a search checkpoint and canonical hash +-// * event-flags & 0x02 - true if the initiating event has an executing link that should follow. Allows detecting when the executing link failed to write. +-// event-hash: H(origin, timestamp, payloadhash); enough to check identifier matches & payload matches. + type DB struct { + log log.Logger + m Metrics +@@ -91,21 +65,21 @@ + lastEntryContext logContext + } +  +-func NewFromFile(logger log.Logger, m Metrics, path string) (*DB, error) { ++func NewFromFile(logger log.Logger, m Metrics, path string, trimToLastSealed bool) (*DB, error) { + store, err := entrydb.NewEntryDB(logger, path) + if err != nil { + return nil, fmt.Errorf("failed to open DB: %w", err) + } +- return NewFromEntryStore(logger, m, store) ++ return NewFromEntryStore(logger, m, store, trimToLastSealed) + } +  +-func NewFromEntryStore(logger log.Logger, m Metrics, store EntryStore) (*DB, error) { ++func NewFromEntryStore(logger log.Logger, m Metrics, store EntryStore, trimToLastSealed bool) (*DB, error) { + db := &DB{ + log: logger, + m: m, + store: store, + } +- if err := db.init(); err != nil { ++ if err := db.init(trimToLastSealed); err != nil { + return nil, fmt.Errorf("failed to init database: %w", err) + } + return db, nil +@@ -115,59 +89,57 @@ func (db *DB) lastEntryIdx() entrydb.EntryIdx { + return db.store.LastEntryIdx() + } +  +-func (db *DB) init() error { ++func (db *DB) init(trimToLastSealed bool) error { + defer db.updateEntryCountMetric() // Always update the entry count metric after init completes +- if err := db.trimInvalidTrailingEntries(); err != nil { +- return fmt.Errorf("failed to trim invalid trailing entries: %w", err) ++ if trimToLastSealed { ++ if err := db.trimToLastSealed(); err != nil { ++ return fmt.Errorf("failed to trim invalid trailing entries: %w", err) ++ } + } + if db.lastEntryIdx() < 0 { +- // Database is empty so no context to load ++ // Database is empty. ++ // Make a state that is ready to apply the genesis block on top of as first entry. ++ // This will infer into a checkpoint (half of the block seal here) ++ // and is then followed up with canonical-hash entry of genesis. ++ db.lastEntryContext = logContext{ ++ nextEntryIndex: 0, ++ blockHash: common.Hash{}, ++ blockNum: 0, ++ timestamp: 0, ++ logsSince: 0, ++ logHash: common.Hash{}, ++ execMsg: nil, ++ out: nil, ++ } + return nil + } +- ++ // start at the last checkpoint, ++ // and then apply any remaining changes on top, to hydrate the state. + lastCheckpoint := (db.lastEntryIdx() / searchCheckpointFrequency) * searchCheckpointFrequency +- i, err := db.newIterator(lastCheckpoint) +- if err != nil { +- return fmt.Errorf("failed to create iterator at last search checkpoint: %w", err) +- } +- // Read all entries until the end of the file +- for { +- _, _, _, err := i.NextLog() +- if errors.Is(err, io.EOF) { +- break +- } else if err != nil { +- return fmt.Errorf("failed to init from existing entries: %w", err) +- } ++ i := db.newIterator(lastCheckpoint) ++ i.current.need.Add(entrydb.FlagCanonicalHash) ++ if err := i.End(); err != nil { ++ return fmt.Errorf("failed to init from remaining trailing data: %w", err) + } + db.lastEntryContext = i.current + return nil + } +  +-func (db *DB) trimInvalidTrailingEntries() error { ++func (db *DB) trimToLastSealed() error { + i := db.lastEntryIdx() + for ; i >= 0; i-- { + entry, err := db.store.Read(i) + if err != nil { + return fmt.Errorf("failed to read %v to check for trailing entries: %w", i, err) + } +- if entry[0] == typeExecutingCheck { +- // executing check is a valid final entry ++ if entry.Type() == entrydb.TypeCanonicalHash { ++ // only an executing hash, indicating a sealed block, is a valid point for restart + break + } +- if entry[0] == typeInitiatingEvent { +- evt, err := newInitiatingEventFromEntry(entry) +- if err != nil { +- // Entry is invalid, keep walking backwards +- continue +- } +- if !evt.hasExecMsg { +- // init event with no exec msg is a valid final entry +- break +- } +- } + } + if i < db.lastEntryIdx() { + db.log.Warn("Truncating unexpected trailing entries", "prev", db.lastEntryIdx(), "new", i) ++ // trim such that the last entry is the canonical-hash we identified + return db.store.Truncate(i) + } + return nil +@@ -177,397 +149,358 @@ func (db *DB) updateEntryCountMetric() { + db.m.RecordDBEntryCount(db.store.Size()) + } +  +-func (db *DB) LatestBlockNum() uint64 { +- return db.lastEntryContext.blockNum ++func (db *DB) IteratorStartingAt(i entrydb.EntryIdx) (Iterator, error) { ++ db.rwLock.RLock() ++ defer db.rwLock.RUnlock() ++ if i > db.lastEntryContext.nextEntryIndex { ++ return nil, ErrFuture ++ } ++ // TODO(#12031): Workaround while we not have IteratorStartingAt(heads.HeadPointer): ++ // scroll back from the index, to find block info. ++ idx := i ++ for ; idx >= 0; i-- { ++ entry, err := db.store.Read(idx) ++ if err != nil { ++ if errors.Is(err, io.EOF) { ++ continue // traverse to when we did have blocks ++ } ++ return nil, err ++ } ++ if entry.Type() == entrydb.TypeSearchCheckpoint { ++ break ++ } ++ if idx == 0 { ++ return nil, fmt.Errorf("empty DB, no block entry, cannot start at %d", i) ++ } ++ } ++ iter := db.newIterator(idx) ++ for iter.NextIndex() < i { ++ if _, err := iter.next(); err != nil { ++ return nil, errors.New("failed to process back up to the head pointer") ++ } ++ } ++ return iter, nil + } +  +-// ClosestBlockInfo returns the block number and hash of the highest recorded block at or before blockNum. +-// Since block data is only recorded in search checkpoints, this may return an earlier block even if log data is +-// recorded for the requested block. +-func (db *DB) ClosestBlockInfo(blockNum uint64) (uint64, types.TruncatedHash, error) { ++// FindSealedBlock finds the requested block, to check if it exists, ++// returning the next index after it where things continue from. ++// returns ErrFuture if the block is too new to be able to tell ++// returns ErrDifferent if the known block does not match ++func (db *DB) FindSealedBlock(block eth.BlockID) (nextEntry entrydb.EntryIdx, err error) { + db.rwLock.RLock() + defer db.rwLock.RUnlock() +- checkpointIdx, err := db.searchCheckpoint(blockNum, math.MaxUint32) +- if err != nil { +- return 0, types.TruncatedHash{}, fmt.Errorf("no checkpoint at or before block %v found: %w", blockNum, err) ++ iter, err := db.newIteratorAt(block.Number, 0) ++ if errors.Is(err, ErrFuture) { ++ return 0, fmt.Errorf("block %d is not known yet: %w", block.Number, ErrFuture) ++ } else if err != nil { ++ return 0, fmt.Errorf("failed to find sealed block %d: %w", block.Number, err) + } +- checkpoint, err := db.readSearchCheckpoint(checkpointIdx) +- if err != nil { +- return 0, types.TruncatedHash{}, fmt.Errorf("failed to reach checkpoint: %w", err) ++ h, _, ok := iter.SealedBlock() ++ if !ok { ++ panic("expected block") + } +- entry, err := db.readCanonicalHash(checkpointIdx + 1) +- if err != nil { +- return 0, types.TruncatedHash{}, fmt.Errorf("failed to read canonical hash: %w", err) ++ if block.Hash != h { ++ return 0, fmt.Errorf("queried %s but got %s at number %d: %w", block.Hash, h, block.Number, ErrConflict) + } +- return checkpoint.blockNum, entry.hash, nil ++ return iter.NextIndex(), nil + } +  +-// ClosestBlockIterator returns an iterator for the block closest to the specified blockNum. +-// The iterator will start at the search checkpoint for the block, or the first checkpoint before it. +-func (db *DB) ClosestBlockIterator(blockNum uint64) (Iterator, error) { ++// LatestSealedBlockNum returns the block number of the block that was last sealed, ++// or ok=false if there is no sealed block (i.e. empty DB) ++func (db *DB) LatestSealedBlockNum() (n uint64, ok bool) { + db.rwLock.RLock() + defer db.rwLock.RUnlock() +- checkpointIdx, err := db.searchCheckpoint(blockNum, math.MaxUint32) +- if err != nil { +- return nil, fmt.Errorf("no checkpoint at or before block %v found: %w", blockNum, err) ++ if db.lastEntryContext.nextEntryIndex == 0 { ++ return 0, false // empty DB, time to add the first seal + } +- return db.newIterator(checkpointIdx) ++ if !db.lastEntryContext.hasCompleteBlock() { ++ db.log.Debug("New block is already in progress", "num", db.lastEntryContext.blockNum) ++ } ++ return db.lastEntryContext.blockNum, true + } +  +-// Get returns the truncated hash of the log at the specified blockNum and logIdx, +-// or an error if the log is not found. +-func (db *DB) Get(blockNum uint64, logiIdx uint32) (types.TruncatedHash, error) { ++// Get returns the hash of the log at the specified blockNum (of the sealed block) ++// and logIdx (of the log after the block), or an error if the log is not found. ++func (db *DB) Get(blockNum uint64, logIdx uint32) (common.Hash, error) { + db.rwLock.RLock() + defer db.rwLock.RUnlock() +- hash, _, err := db.findLogInfo(blockNum, logiIdx) ++ hash, _, err := db.findLogInfo(blockNum, logIdx) + return hash, err + } +  +-// Contains return true iff the specified logHash is recorded in the specified blockNum and logIdx. +-// If the log is found, the entry index of the log is returned, too. ++// Contains returns no error iff the specified logHash is recorded in the specified blockNum and logIdx. ++// If the log is out of reach, then ErrFuture is returned. ++// If the log is determined to conflict with the canonical chain, then ErrConflict is returned. + // logIdx is the index of the log in the array of all logs in the block. + // This can be used to check the validity of cross-chain interop events. +-func (db *DB) Contains(blockNum uint64, logIdx uint32, logHash types.TruncatedHash) (bool, entrydb.EntryIdx, error) { ++func (db *DB) Contains(blockNum uint64, logIdx uint32, logHash common.Hash) (entrydb.EntryIdx, error) { + db.rwLock.RLock() + defer db.rwLock.RUnlock() + db.log.Trace("Checking for log", "blockNum", blockNum, "logIdx", logIdx, "hash", logHash) +  + evtHash, iter, err := db.findLogInfo(blockNum, logIdx) +- if errors.Is(err, ErrNotFound) { +- // Did not find a log at blockNum and logIdx +- return false, 0, nil +- } else if err != nil { +- return false, 0, err ++ if err != nil { ++ return 0, err // may be ErrConflict if the block does not have as many logs + } + db.log.Trace("Found initiatingEvent", "blockNum", blockNum, "logIdx", logIdx, "hash", evtHash) + // Found the requested block and log index, check if the hash matches +- if evtHash == logHash { +- return true, iter.Index(), nil ++ if evtHash != logHash { ++ return 0, fmt.Errorf("payload hash mismatch: expected %s, got %s", logHash, evtHash) + } +- return false, 0, nil ++ return iter.NextIndex(), nil + } +  +-// Executes checks if the log identified by the specific block number and log index, has an ExecutingMessage associated +-// with it that needs to be checked as part of interop validation. +-// logIdx is the index of the log in the array of all logs in the block. +-// Returns the ExecutingMessage if it exists, or ExecutingMessage{} if the log is found but has no ExecutingMessage. +-// Returns ErrNotFound if the specified log does not exist in the database. +-func (db *DB) Executes(blockNum uint64, logIdx uint32) (types.ExecutingMessage, error) { +- db.rwLock.RLock() +- defer db.rwLock.RUnlock() +- _, iter, err := db.findLogInfo(blockNum, logIdx) +- if err != nil { +- return types.ExecutingMessage{}, err ++func (db *DB) findLogInfo(blockNum uint64, logIdx uint32) (common.Hash, Iterator, error) { ++ if blockNum == 0 { ++ return common.Hash{}, nil, ErrConflict // no logs in block 0 + } +- execMsg, err := iter.ExecMessage() +- if err != nil { +- return types.ExecutingMessage{}, fmt.Errorf("failed to read executing message: %w", err) ++ // blockNum-1, such that we find a log that came after the parent num-1 was sealed. ++ // logIdx, such that all entries before logIdx can be skipped, but logIdx itself is still readable. ++ iter, err := db.newIteratorAt(blockNum-1, logIdx) ++ if errors.Is(err, ErrFuture) { ++ db.log.Trace("Could not find log yet", "blockNum", blockNum, "logIdx", logIdx) ++ return common.Hash{}, nil, err ++ } else if err != nil { ++ db.log.Error("Failed searching for log", "blockNum", blockNum, "logIdx", logIdx) ++ return common.Hash{}, nil, err ++ } ++ if err := iter.NextInitMsg(); err != nil { ++ return common.Hash{}, nil, fmt.Errorf("failed to read initiating message %d, on top of block %d: %w", logIdx, blockNum, err) + } +- return execMsg, nil ++ if _, x, ok := iter.SealedBlock(); !ok { ++ panic("expected block") ++ } else if x < blockNum-1 { ++ panic(fmt.Errorf("bug in newIteratorAt, expected to have found parent block %d but got %d", blockNum-1, x)) ++ } else if x > blockNum-1 { ++ return common.Hash{}, nil, fmt.Errorf("log does not exist, found next block already: %w", ErrConflict) ++ } ++ logHash, x, ok := iter.InitMessage() ++ if !ok { ++ panic("expected init message") ++ } else if x != logIdx { ++ panic(fmt.Errorf("bug in newIteratorAt, expected to have found log %d but got %d", logIdx, x)) ++ } ++ return logHash, iter, nil + } +  +-func (db *DB) findLogInfo(blockNum uint64, logIdx uint32) (types.TruncatedHash, Iterator, error) { +- entryIdx, err := db.searchCheckpoint(blockNum, logIdx) ++// newIteratorAt returns an iterator ready after the given sealed block number, ++// and positioned such that the next log-read on the iterator return the log with logIndex, if any. ++// It may return an ErrNotFound if the block number is unknown, ++// or if there are just not that many seen log events after the block as requested. ++func (db *DB) newIteratorAt(blockNum uint64, logIndex uint32) (*iterator, error) { ++ // find a checkpoint before or exactly when blockNum was sealed, ++ // and have processed up to but not including [logIndex] number of logs (i.e. all prior logs, if any). ++ searchCheckpointIndex, err := db.searchCheckpoint(blockNum, logIndex) + if errors.Is(err, io.EOF) { + // Did not find a checkpoint to start reading from so the log cannot be present. +- return types.TruncatedHash{}, nil, ErrNotFound ++ return nil, ErrFuture + } else if err != nil { +- return types.TruncatedHash{}, nil, err ++ return nil, err + } +- +- i, err := db.newIterator(entryIdx) ++ // The iterator did not consume the checkpoint yet, it's positioned right at it. ++ // So we can call NextBlock() and get the checkpoint itself as first entry. ++ iter := db.newIterator(searchCheckpointIndex) + if err != nil { +- return types.TruncatedHash{}, nil, fmt.Errorf("failed to create iterator: %w", err) ++ return nil, err + } +- db.log.Trace("Starting search", "entry", entryIdx, "blockNum", i.current.blockNum, "logIdx", i.current.logIdx) ++ iter.current.need.Add(entrydb.FlagCanonicalHash) + defer func() { +- db.m.RecordDBSearchEntriesRead(i.entriesRead) ++ db.m.RecordDBSearchEntriesRead(iter.entriesRead) + }() ++ // First walk up to the block that we are sealed up to (incl.) + for { +- evtBlockNum, evtLogIdx, evtHash, err := i.NextLog() +- if errors.Is(err, io.EOF) { +- // Reached end of log without finding the event +- return types.TruncatedHash{}, nil, ErrNotFound ++ if _, n, _ := iter.SealedBlock(); n == blockNum { // we may already have it exactly ++ break ++ } ++ if err := iter.NextBlock(); errors.Is(err, ErrFuture) { ++ db.log.Trace("ran out of data, could not find block", "nextIndex", iter.NextIndex(), "target", blockNum) ++ return nil, ErrFuture + } else if err != nil { +- return types.TruncatedHash{}, nil, fmt.Errorf("failed to read next log: %w", err) ++ db.log.Error("failed to read next block", "nextIndex", iter.NextIndex(), "target", blockNum, "err", err) ++ return nil, err ++ } ++ h, num, ok := iter.SealedBlock() ++ if !ok { ++ panic("expected sealed block") + } +- if evtBlockNum == blockNum && evtLogIdx == logIdx { +- db.log.Trace("Found initiatingEvent", "blockNum", evtBlockNum, "logIdx", evtLogIdx, "hash", evtHash) +- return evtHash, i, nil ++ db.log.Trace("found sealed block", "num", num, "hash", h) ++ if num < blockNum { ++ continue + } +- if evtBlockNum > blockNum || (evtBlockNum == blockNum && evtLogIdx > logIdx) { +- // Progressed past the requested log without finding it. +- return types.TruncatedHash{}, nil, ErrNotFound ++ if num != blockNum { // block does not contain ++ return nil, fmt.Errorf("looking for %d, but already at %d: %w", blockNum, num, ErrConflict) + } ++ break + } +-} +- +-func (db *DB) newIterator(startCheckpointEntry entrydb.EntryIdx) (*iterator, error) { +- checkpoint, err := db.readSearchCheckpoint(startCheckpointEntry) +- if err != nil { +- return nil, fmt.Errorf("failed to read search checkpoint entry %v: %w", startCheckpointEntry, err) +- } +- startIdx := startCheckpointEntry + 2 +- firstEntry, err := db.store.Read(startIdx) +- if errors.Is(err, io.EOF) { +- // There should always be an entry after a checkpoint and canonical hash so an EOF here is data corruption +- return nil, fmt.Errorf("%w: no entry after checkpoint and canonical hash at %v", ErrDataCorruption, startCheckpointEntry) +- } else if err != nil { +- return nil, fmt.Errorf("failed to read first entry to iterate %v: %w", startCheckpointEntry+2, err) +- } +- startLogCtx := logContext{ +- blockNum: checkpoint.blockNum, +- logIdx: checkpoint.logIdx, +- } +- // Handle starting from a checkpoint after initiating-event but before its executing-link or executing-check +- if firstEntry[0] == typeExecutingLink || firstEntry[0] == typeExecutingCheck { +- if firstEntry[0] == typeExecutingLink { +- // The start checkpoint was between the initiating event and the executing link +- // Step back to read the initiating event. The checkpoint block data will be for the initiating event +- startIdx = startCheckpointEntry - 1 +- } else { +- // The start checkpoint was between the executing link and the executing check +- // Step back to read the initiating event. The checkpoint block data will be for the initiating event +- startIdx = startCheckpointEntry - 2 ++ // Now walk up to the number of seen logs that we want to have processed. ++ // E.g. logIndex == 2, need to have processed index 0 and 1, ++ // so two logs before quiting (and not 3 to then quit after). ++ for iter.current.logsSince < logIndex { ++ if err := iter.NextInitMsg(); err == io.EOF { ++ return nil, ErrFuture ++ } else if err != nil { ++ return nil, err + } +- initEntry, err := db.store.Read(startIdx) +- if err != nil { +- return nil, fmt.Errorf("failed to read prior initiating event: %w", err) ++ _, num, ok := iter.SealedBlock() ++ if !ok { ++ panic("expected sealed block") + } +- initEvt, err := newInitiatingEventFromEntry(initEntry) +- if err != nil { +- return nil, fmt.Errorf("invalid initiating event at idx %v: %w", startIdx, err) ++ if num > blockNum { ++ // we overshot, the block did not contain as many seen log events as requested ++ return nil, ErrConflict ++ } ++ _, idx, ok := iter.InitMessage() ++ if !ok { ++ panic("expected initializing message") ++ } ++ if idx+1 < logIndex { ++ continue ++ } ++ if idx+1 == logIndex { ++ break // the NextInitMsg call will position the iterator at the re + } +- startLogCtx = initEvt.preContext(startLogCtx) ++ return nil, fmt.Errorf("unexpected log-skip at block %d log %d", blockNum, idx) + } +- i := &iterator{ ++ return iter, nil ++} ++ ++// newIterator creates an iterator at the given index. ++// None of the iterator attributes will be ready for reads, ++// but the entry at the given index will be first read when using the iterator. ++func (db *DB) newIterator(index entrydb.EntryIdx) *iterator { ++ return &iterator{ + db: db, +- // +2 to skip the initial search checkpoint and the canonical hash event after it +- nextEntryIdx: startIdx, +- current: startLogCtx, ++ current: logContext{ ++ nextEntryIndex: index, ++ }, + } +- return i, nil + } +  +-// searchCheckpoint performs a binary search of the searchCheckpoint entries to find the closest one at or before +-// the requested log. +-// Returns the index of the searchCheckpoint to begin reading from or an error +-func (db *DB) searchCheckpoint(blockNum uint64, logIdx uint32) (entrydb.EntryIdx, error) { ++// searchCheckpoint performs a binary search of the searchCheckpoint entries ++// to find the closest one with an equal or lower block number and equal or lower amount of seen logs. ++// Returns the index of the searchCheckpoint to begin reading from or an error. ++func (db *DB) searchCheckpoint(sealedBlockNum uint64, logsSince uint32) (entrydb.EntryIdx, error) { ++ if db.lastEntryContext.nextEntryIndex == 0 { ++ return 0, ErrFuture // empty DB, everything is in the future ++ } + n := (db.lastEntryIdx() / searchCheckpointFrequency) + 1 +- // Define x[-1] < target and x[n] >= target. +- // Invariant: x[i-1] < target, x[j] >= target. ++ // Define: x is the array of known checkpoints ++ // Invariant: x[i] <= target, x[j] > target. + i, j := entrydb.EntryIdx(0), n +- for i < j { +- h := entrydb.EntryIdx(uint64(i+j) >> 1) // avoid overflow when computing h ++ for i+1 < j { // i is inclusive, j is exclusive. ++ // Get the checkpoint exactly in-between, ++ // bias towards a higher value if an even number of checkpoints. ++ // E.g. i=3 and j=4 would not run, since i + 1 < j ++ // E.g. i=3 and j=5 leaves checkpoints 3, 4, and we pick 4 as pivot ++ // E.g. i=3 and j=6 leaves checkpoints 3, 4, 5, and we pick 4 as pivot ++ // ++ // The following holds: i ≤ h < j ++ h := entrydb.EntryIdx((uint64(i) + uint64(j)) >> 1) + checkpoint, err := db.readSearchCheckpoint(h * searchCheckpointFrequency) + if err != nil { + return 0, fmt.Errorf("failed to read entry %v: %w", h, err) + } +- // i ≤ h < j +- if checkpoint.blockNum < blockNum || (checkpoint.blockNum == blockNum && checkpoint.logIdx < logIdx) { +- i = h + 1 // preserves x[i-1] < target ++ if checkpoint.blockNum < sealedBlockNum || ++ (checkpoint.blockNum == sealedBlockNum && checkpoint.logsSince < logsSince) { ++ i = h + } else { +- j = h // preserves x[j] >= target ++ j = h + } + } +- if i < n { +- checkpoint, err := db.readSearchCheckpoint(i * searchCheckpointFrequency) +- if err != nil { +- return 0, fmt.Errorf("failed to read entry %v: %w", i, err) +- } +- if checkpoint.blockNum == blockNum && checkpoint.logIdx == logIdx { +- // Found entry at requested block number and log index +- return i * searchCheckpointFrequency, nil +- } ++ if i+1 != j { ++ panic("expected to have 1 checkpoint left") + } +- if i == 0 { +- // There are no checkpoints before the requested blocks +- return 0, io.EOF ++ result := i * searchCheckpointFrequency ++ checkpoint, err := db.readSearchCheckpoint(result) ++ if err != nil { ++ return 0, fmt.Errorf("failed to read final search checkpoint result: %w", err) + } +- // Not found, need to start reading from the entry prior +- return (i - 1) * searchCheckpointFrequency, nil ++ if checkpoint.blockNum > sealedBlockNum || ++ (checkpoint.blockNum == sealedBlockNum && checkpoint.logsSince > logsSince) { ++ return 0, fmt.Errorf("missing data, earliest search checkpoint is %d with %d logs, cannot find something before or at %d with %d logs: %w", ++ checkpoint.blockNum, checkpoint.logsSince, sealedBlockNum, logsSince, ErrSkipped) ++ } ++ return result, nil + } +  +-func (db *DB) AddLog(logHash types.TruncatedHash, block eth.BlockID, timestamp uint64, logIdx uint32, execMsg *types.ExecutingMessage) error { +- db.rwLock.Lock() +- defer db.rwLock.Unlock() +- postState := logContext{ +- blockNum: block.Number, +- logIdx: logIdx, +- } +- if block.Number == 0 { +- return fmt.Errorf("%w: should not have logs in block 0", ErrLogOutOfOrder) +- } +- if db.lastEntryContext.blockNum > block.Number { +- return fmt.Errorf("%w: adding block %v, head block: %v", ErrLogOutOfOrder, block.Number, db.lastEntryContext.blockNum) ++// debug util to log the last 10 entries of the chain ++func (db *DB) debugTip() { ++ for x := 0; x < 10; x++ { ++ index := db.lastEntryIdx() - entrydb.EntryIdx(x) ++ if index < 0 { ++ continue ++ } ++ e, err := db.store.Read(index) ++ if err == nil { ++ db.log.Debug("tip", "index", index, "type", e.Type()) ++ } + } +- if db.lastEntryContext.blockNum == block.Number && db.lastEntryContext.logIdx+1 != logIdx { +- return fmt.Errorf("%w: adding log %v in block %v, but currently at log %v", ErrLogOutOfOrder, logIdx, block.Number, db.lastEntryContext.logIdx) +- } +- if db.lastEntryContext.blockNum < block.Number && logIdx != 0 { +- return fmt.Errorf("%w: adding log %v as first log in block %v", ErrLogOutOfOrder, logIdx, block.Number) +- } +- var entriesToAdd []entrydb.Entry +- newContext := db.lastEntryContext +- lastEntryIdx := db.lastEntryIdx() ++} +  +- addEntry := func(entry entrydb.Entry) { +- entriesToAdd = append(entriesToAdd, entry) +- lastEntryIdx++ ++func (db *DB) flush() error { ++ for i, e := range db.lastEntryContext.out { ++ db.log.Trace("appending entry", "type", e.Type(), "entry", hexutil.Bytes(e[:]), ++ "next", int(db.lastEntryContext.nextEntryIndex)-len(db.lastEntryContext.out)+i) + } +- maybeAddCheckpoint := func() { +- if (lastEntryIdx+1)%searchCheckpointFrequency == 0 { +- addEntry(newSearchCheckpoint(block.Number, logIdx, timestamp).encode()) +- addEntry(newCanonicalHash(types.TruncateHash(block.Hash)).encode()) +- newContext = postState +- } ++ if err := db.store.Append(db.lastEntryContext.out...); err != nil { ++ return fmt.Errorf("failed to append entries: %w", err) + } +- maybeAddCheckpoint() ++ db.lastEntryContext.out = db.lastEntryContext.out[:0] ++ db.updateEntryCountMetric() ++ return nil ++} +  +- evt, err := newInitiatingEvent(newContext, postState.blockNum, postState.logIdx, logHash, execMsg != nil) +- if err != nil { +- return fmt.Errorf("failed to create initiating event: %w", err) ++func (db *DB) SealBlock(parentHash common.Hash, block eth.BlockID, timestamp uint64) error { ++ db.rwLock.Lock() ++ defer db.rwLock.Unlock() ++ ++ if err := db.lastEntryContext.SealBlock(parentHash, block, timestamp); err != nil { ++ return fmt.Errorf("failed to seal block: %w", err) + } +- addEntry(evt.encode()) ++ db.log.Trace("Sealed block", "parent", parentHash, "block", block, "timestamp", timestamp) ++ return db.flush() ++} +  +- if execMsg != nil { +- maybeAddCheckpoint() +- link, err := newExecutingLink(*execMsg) +- if err != nil { +- return fmt.Errorf("failed to create executing link: %w", err) +- } +- addEntry(link.encode()) ++func (db *DB) AddLog(logHash common.Hash, parentBlock eth.BlockID, logIdx uint32, execMsg *types.ExecutingMessage) error { ++ db.rwLock.Lock() ++ defer db.rwLock.Unlock() +  +- maybeAddCheckpoint() +- addEntry(newExecutingCheck(execMsg.Hash).encode()) ++ if err := db.lastEntryContext.ApplyLog(parentBlock, logIdx, logHash, execMsg); err != nil { ++ return fmt.Errorf("failed to apply log: %w", err) + } +- if err := db.store.Append(entriesToAdd...); err != nil { +- return fmt.Errorf("failed to append entries: %w", err) +- } +- db.lastEntryContext = postState +- db.updateEntryCountMetric() +- return nil ++ db.log.Trace("Applied log", "parentBlock", parentBlock, "logIndex", logIdx, "logHash", logHash, "executing", execMsg != nil) ++ return db.flush() + } +  + // Rewind the database to remove any blocks after headBlockNum + // The block at headBlockNum itself is not removed. +-func (db *DB) Rewind(headBlockNum uint64) error { ++func (db *DB) Rewind(newHeadBlockNum uint64) error { + db.rwLock.Lock() + defer db.rwLock.Unlock() +- if headBlockNum >= db.lastEntryContext.blockNum { +- // Nothing to do +- return nil +- } +- // Find the last checkpoint before the block to remove +- idx, err := db.searchCheckpoint(headBlockNum+1, 0) +- if errors.Is(err, io.EOF) { +- // Requested a block prior to the first checkpoint +- // Delete everything without scanning forward +- idx = -1 +- } else if err != nil { +- return fmt.Errorf("failed to find checkpoint prior to block %v: %w", headBlockNum, err) +- } else { +- // Scan forward from the checkpoint to find the first entry about a block after headBlockNum +- i, err := db.newIterator(idx) +- if err != nil { +- return fmt.Errorf("failed to create iterator when searching for rewind point: %w", err) +- } +- // If we don't find any useful logs after the checkpoint, we should delete the checkpoint itself +- // So move our delete marker back to include it as a starting point +- idx-- +- for { +- blockNum, _, _, err := i.NextLog() +- if errors.Is(err, io.EOF) { +- // Reached end of file, we need to keep everything +- return nil +- } else if err != nil { +- return fmt.Errorf("failed to find rewind point: %w", err) +- } +- if blockNum > headBlockNum { +- // Found the first entry we don't need, so stop searching and delete everything after idx +- break +- } +- // Otherwise we need all of the entries the iterator just read +- idx = i.nextEntryIdx - 1 +- } ++ // Even if the last fully-processed block matches headBlockNum, ++ // we might still have trailing log events to get rid of. ++ iter, err := db.newIteratorAt(newHeadBlockNum, 0) ++ if err != nil { ++ return err + } +- // Truncate to contain idx+1 entries, since indices are 0 based, this deletes everything after idx +- if err := db.store.Truncate(idx); err != nil { +- return fmt.Errorf("failed to truncate to block %v: %w", headBlockNum, err) ++ // Truncate to contain idx+1 entries, since indices are 0 based, ++ // this deletes everything after idx ++ if err := db.store.Truncate(iter.NextIndex()); err != nil { ++ return fmt.Errorf("failed to truncate to block %v: %w", newHeadBlockNum, err) + } + // Use db.init() to find the log context for the new latest log entry +- if err := db.init(); err != nil { ++ if err := db.init(true); err != nil { + return fmt.Errorf("failed to find new last entry context: %w", err) + } + return nil + } +  +-// NextExecutingMessage returns the next executing message in the log database. +-// it skips over any non-executing messages, and will return an error if encountered. +-// the iterator is modified in the process. +-func (db *DB) NextExecutingMessage(iter Iterator) (types.ExecutingMessage, error) { +- db.rwLock.RLock() +- defer db.rwLock.RUnlock() +- // this for-loop will break: +- // - when the iterator reaches the end of the log +- // - when the iterator reaches an executing message +- // - if an error occurs +- for { +- _, _, _, err := iter.NextLog() +- if err != nil { +- return types.ExecutingMessage{}, err +- } +- // if the log is not an executing message, both exec and err are empty +- exec, err := iter.ExecMessage() +- if err != nil { +- return types.ExecutingMessage{}, fmt.Errorf("failed to get executing message: %w", err) +- } +- if exec != (types.ExecutingMessage{}) { +- return exec, nil +- } +- } +-} +- +-// LastCheckpointBehind returns an iterator for the last checkpoint behind the specified entry index. +-// If the entry index is a search checkpoint, the iterator will start at that checkpoint. +-// After searching back long enough (the searchCheckpointFrequency), an error is returned, +-// as checkpoints are expected to be found within the frequency. +-func (db *DB) LastCheckpointBehind(entryIdx entrydb.EntryIdx) (Iterator, error) { +- for attempts := 0; attempts < searchCheckpointFrequency; attempts++ { +- // attempt to read the index entry as a search checkpoint +- _, err := db.readSearchCheckpoint(entryIdx) +- if err == nil { +- return db.newIterator(entryIdx) +- } +- // ErrDataCorruption is the return value if the entry is not a search checkpoint +- // if it's not that type of error, we should return it instead of continuing +- if !errors.Is(err, ErrDataCorruption) { +- return nil, err +- } +- // don't attempt to read behind the start of the data +- if entryIdx == 0 { +- break +- } +- // reverse if we haven't found it yet +- entryIdx -= 1 +- } +- return nil, fmt.Errorf("failed to find a search checkpoint in the last %v entries", searchCheckpointFrequency) +-} +- + func (db *DB) readSearchCheckpoint(entryIdx entrydb.EntryIdx) (searchCheckpoint, error) { + data, err := db.store.Read(entryIdx) + if err != nil { + return searchCheckpoint{}, fmt.Errorf("failed to read entry %v: %w", entryIdx, err) + } + return newSearchCheckpointFromEntry(data) +-} +- +-func (db *DB) readCanonicalHash(entryIdx entrydb.EntryIdx) (canonicalHash, error) { +- data, err := db.store.Read(entryIdx) +- if err != nil { +- return canonicalHash{}, fmt.Errorf("failed to read entry %v: %w", entryIdx, err) +- } +- return newCanonicalHashFromEntry(data) + } +  + func (db *DB) Close() error {
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+19
+
-77
+ +
+ +
+
+
diff --git OP/op-supervisor/supervisor/backend/db/logs/db_invariants_test.go CELO/op-supervisor/supervisor/backend/db/logs/db_invariants_test.go +index e0837e8c57bf4ad0b64f1b7230264ca8d48f286a..04c004f3d0966305fb4bda1fcb726edec396d0bc 100644 +--- OP/op-supervisor/supervisor/backend/db/logs/db_invariants_test.go ++++ CELO/op-supervisor/supervisor/backend/db/logs/db_invariants_test.go +@@ -38,16 +38,13 @@ require.EqualValuesf(t, entrydb.EntrySize, n, "read wrong length for entry %v", i) + } +  + entryInvariants := []entryInvariant{ +- invariantSearchCheckpointOnlyAtFrequency, + invariantSearchCheckpointAtEverySearchCheckpointFrequency, +- invariantCanonicalHashAfterEverySearchCheckpoint, ++ invariantCanonicalHashOrCheckpointAfterEverySearchCheckpoint, + invariantSearchCheckpointBeforeEveryCanonicalHash, +- invariantIncrementLogIdxIfNotImmediatelyAfterCanonicalHash, + invariantExecLinkAfterInitEventWithFlagSet, + invariantExecLinkOnlyAfterInitiatingEventWithFlagSet, + invariantExecCheckAfterExecLink, + invariantExecCheckOnlyAfterExecLink, +- invariantValidLastEntry, + } + for i, entry := range entries { + for _, invariant := range entryInvariants { +@@ -83,81 +80,47 @@ } + return nil + } +  +-func invariantSearchCheckpointOnlyAtFrequency(entryIdx int, entry entrydb.Entry, entries []entrydb.Entry, m *stubMetrics) error { +- if entry[0] != typeSearchCheckpoint { +- return nil +- } +- if entryIdx%searchCheckpointFrequency != 0 { +- return fmt.Errorf("should only have search checkpoints every %v entries but found at entry %v", searchCheckpointFrequency, entryIdx) +- } +- return nil +-} +- + func invariantSearchCheckpointAtEverySearchCheckpointFrequency(entryIdx int, entry entrydb.Entry, entries []entrydb.Entry, m *stubMetrics) error { +- if entryIdx%searchCheckpointFrequency == 0 && entry[0] != typeSearchCheckpoint { ++ if entryIdx%searchCheckpointFrequency == 0 && entry.Type() != entrydb.TypeSearchCheckpoint { + return fmt.Errorf("should have search checkpoints every %v entries but entry %v was %x", searchCheckpointFrequency, entryIdx, entry) + } + return nil + } +  +-func invariantCanonicalHashAfterEverySearchCheckpoint(entryIdx int, entry entrydb.Entry, entries []entrydb.Entry, m *stubMetrics) error { +- if entry[0] != typeSearchCheckpoint { ++func invariantCanonicalHashOrCheckpointAfterEverySearchCheckpoint(entryIdx int, entry entrydb.Entry, entries []entrydb.Entry, m *stubMetrics) error { ++ if entry.Type() != entrydb.TypeSearchCheckpoint { + return nil + } + if entryIdx+1 >= len(entries) { +- return fmt.Errorf("expected canonical hash after search checkpoint at entry %v but no further entries found", entryIdx) ++ return fmt.Errorf("expected canonical hash or checkpoint after search checkpoint at entry %v but no further entries found", entryIdx) + } + nextEntry := entries[entryIdx+1] +- if nextEntry[0] != typeCanonicalHash { +- return fmt.Errorf("expected canonical hash after search checkpoint at entry %v but got %x", entryIdx, nextEntry) ++ if nextEntry.Type() != entrydb.TypeCanonicalHash && nextEntry.Type() != entrydb.TypeSearchCheckpoint { ++ return fmt.Errorf("expected canonical hash or checkpoint after search checkpoint at entry %v but got %x", entryIdx, nextEntry) + } + return nil + } +  + // invariantSearchCheckpointBeforeEveryCanonicalHash ensures we don't have extra canonical-hash entries + func invariantSearchCheckpointBeforeEveryCanonicalHash(entryIdx int, entry entrydb.Entry, entries []entrydb.Entry, m *stubMetrics) error { +- if entry[0] != typeCanonicalHash { ++ if entry.Type() != entrydb.TypeCanonicalHash { + return nil + } + if entryIdx == 0 { + return fmt.Errorf("expected search checkpoint before canonical hash at entry %v but no previous entries present", entryIdx) + } + prevEntry := entries[entryIdx-1] +- if prevEntry[0] != typeSearchCheckpoint { ++ if prevEntry.Type() != entrydb.TypeSearchCheckpoint { + return fmt.Errorf("expected search checkpoint before canonical hash at entry %v but got %x", entryIdx, prevEntry) + } + return nil + } +  +-func invariantIncrementLogIdxIfNotImmediatelyAfterCanonicalHash(entryIdx int, entry entrydb.Entry, entries []entrydb.Entry, m *stubMetrics) error { +- if entry[0] != typeInitiatingEvent { +- return nil +- } +- if entryIdx == 0 { +- return fmt.Errorf("found initiating event at index %v before any search checkpoint", entryIdx) +- } +- blockDiff := entry[1] +- flags := entry[2] +- incrementsLogIdx := flags&eventFlagIncrementLogIdx != 0 +- prevEntry := entries[entryIdx-1] +- prevEntryIsCanonicalHash := prevEntry[0] == typeCanonicalHash +- if incrementsLogIdx && prevEntryIsCanonicalHash { +- return fmt.Errorf("initiating event at index %v increments logIdx despite being immediately after canonical hash (prev entry %x)", entryIdx, prevEntry) +- } +- if incrementsLogIdx && blockDiff > 0 { +- return fmt.Errorf("initiating event at index %v increments logIdx despite starting a new block", entryIdx) +- } +- if !incrementsLogIdx && !prevEntryIsCanonicalHash && blockDiff == 0 { +- return fmt.Errorf("initiating event at index %v does not increment logIdx when block unchanged and not after canonical hash (prev entry %x)", entryIdx, prevEntry) +- } +- return nil +-} +- + func invariantExecLinkAfterInitEventWithFlagSet(entryIdx int, entry entrydb.Entry, entries []entrydb.Entry, m *stubMetrics) error { +- if entry[0] != typeInitiatingEvent { ++ if entry.Type() != entrydb.TypeInitiatingEvent { + return nil + } +- hasExecMessage := entry[2]&eventFlagHasExecutingMessage != 0 ++ hasExecMessage := entry[1]&eventFlagHasExecutingMessage != 0 + if !hasExecMessage { + return nil + } +@@ -168,14 +131,14 @@ } + if len(entries) <= linkIdx { + return fmt.Errorf("expected executing link after initiating event with exec msg flag set at entry %v but there were no more events", entryIdx) + } +- if entries[linkIdx][0] != typeExecutingLink { ++ if entries[linkIdx].Type() != entrydb.TypeExecutingLink { + return fmt.Errorf("expected executing link at idx %v after initiating event with exec msg flag set at entry %v but got type %v", linkIdx, entryIdx, entries[linkIdx][0]) + } + return nil + } +  + func invariantExecLinkOnlyAfterInitiatingEventWithFlagSet(entryIdx int, entry entrydb.Entry, entries []entrydb.Entry, m *stubMetrics) error { +- if entry[0] != typeExecutingLink { ++ if entry.Type() != entrydb.TypeExecutingLink { + return nil + } + if entryIdx == 0 { +@@ -189,10 +152,10 @@ if initIdx < 0 { + return fmt.Errorf("found executing link without a preceding initiating event at entry %v", entryIdx) + } + initEntry := entries[initIdx] +- if initEntry[0] != typeInitiatingEvent { ++ if initEntry.Type() != entrydb.TypeInitiatingEvent { + return fmt.Errorf("expected initiating event at entry %v prior to executing link at %v but got %x", initIdx, entryIdx, initEntry[0]) + } +- flags := initEntry[2] ++ flags := initEntry[1] + if flags&eventFlagHasExecutingMessage == 0 { + return fmt.Errorf("initiating event at %v prior to executing link at %v does not have flag set to indicate needing a executing event: %x", initIdx, entryIdx, initEntry) + } +@@ -200,7 +163,7 @@ return nil + } +  + func invariantExecCheckAfterExecLink(entryIdx int, entry entrydb.Entry, entries []entrydb.Entry, m *stubMetrics) error { +- if entry[0] != typeExecutingLink { ++ if entry.Type() != entrydb.TypeExecutingLink { + return nil + } + checkIdx := entryIdx + 1 +@@ -211,14 +174,14 @@ if checkIdx >= len(entries) { + return fmt.Errorf("expected executing link at %v to be followed by executing check at %v but ran out of entries", entryIdx, checkIdx) + } + checkEntry := entries[checkIdx] +- if checkEntry[0] != typeExecutingCheck { ++ if checkEntry.Type() != entrydb.TypeExecutingCheck { + return fmt.Errorf("expected executing link at %v to be followed by executing check at %v but got type %v", entryIdx, checkIdx, checkEntry[0]) + } + return nil + } +  + func invariantExecCheckOnlyAfterExecLink(entryIdx int, entry entrydb.Entry, entries []entrydb.Entry, m *stubMetrics) error { +- if entry[0] != typeExecutingCheck { ++ if entry.Type() != entrydb.TypeExecutingCheck { + return nil + } + if entryIdx == 0 { +@@ -232,29 +195,8 @@ if linkIdx < 0 { + return fmt.Errorf("found executing link without a preceding initiating event at entry %v", entryIdx) + } + linkEntry := entries[linkIdx] +- if linkEntry[0] != typeExecutingLink { ++ if linkEntry.Type() != entrydb.TypeExecutingLink { + return fmt.Errorf("expected executing link at entry %v prior to executing check at %v but got %x", linkIdx, entryIdx, linkEntry[0]) + } + return nil + } +- +-// invariantValidLastEntry checks that the last entry is either a executing check or initiating event with no exec message +-func invariantValidLastEntry(entryIdx int, entry entrydb.Entry, entries []entrydb.Entry, m *stubMetrics) error { +- if entryIdx+1 < len(entries) { +- return nil +- } +- if entry[0] == typeExecutingCheck { +- return nil +- } +- if entry[0] != typeInitiatingEvent { +- return fmt.Errorf("invalid final event type: %v", entry[0]) +- } +- evt, err := newInitiatingEventFromEntry(entry) +- if err != nil { +- return fmt.Errorf("final event was invalid: %w", err) +- } +- if evt.hasExecMsg { +- return errors.New("ends with init event that should have exec msg but no exec msg follows") +- } +- return nil +-}
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+668
+
-442
+ +
+ +
+
+
diff --git OP/op-supervisor/supervisor/backend/db/logs/db_test.go CELO/op-supervisor/supervisor/backend/db/logs/db_test.go +index 91caa2fe3e5da8b9424820edccb2b592abbf053e..31067b05808d556970b4f9971d8fad89a88ab657 100644 +--- OP/op-supervisor/supervisor/backend/db/logs/db_test.go ++++ CELO/op-supervisor/supervisor/backend/db/logs/db_test.go +@@ -1,44 +1,47 @@ + package logs +  + import ( +- "bytes" +- "fmt" ++ "encoding/binary" + "io" + "io/fs" + "os" + "path/filepath" + "testing" ++ ++ "github.com/stretchr/testify/require" ++ ++ "github.com/ethereum/go-ethereum/common" ++ "github.com/ethereum/go-ethereum/crypto" ++ "github.com/ethereum/go-ethereum/log" +  + "github.com/ethereum-optimism/optimism/op-service/eth" + "github.com/ethereum-optimism/optimism/op-service/testlog" + "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/db/entrydb" +- "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/types" +- "github.com/ethereum/go-ethereum/common" +- "github.com/ethereum/go-ethereum/log" +- "github.com/stretchr/testify/require" ++ "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" + ) +- +-func createTruncatedHash(i int) types.TruncatedHash { +- return types.TruncateHash(createHash(i)) +-} +  + func createHash(i int) common.Hash { +- data := bytes.Repeat([]byte{byte(i)}, common.HashLength) +- return common.BytesToHash(data) ++ if i == -1 { // parent-hash of genesis is zero ++ return common.Hash{} ++ } ++ var data [9]byte ++ data[0] = 0xff ++ binary.BigEndian.PutUint64(data[1:], uint64(i)) ++ return crypto.Keccak256Hash(data[:]) + } +  + func TestErrorOpeningDatabase(t *testing.T) { + dir := t.TempDir() +- _, err := NewFromFile(testlog.Logger(t, log.LvlInfo), &stubMetrics{}, filepath.Join(dir, "missing-dir", "file.db")) ++ _, err := NewFromFile(testlog.Logger(t, log.LvlInfo), &stubMetrics{}, filepath.Join(dir, "missing-dir", "file.db"), false) + require.ErrorIs(t, err, os.ErrNotExist) + } +  + func runDBTest(t *testing.T, setup func(t *testing.T, db *DB, m *stubMetrics), assert func(t *testing.T, db *DB, m *stubMetrics)) { + createDb := func(t *testing.T, dir string) (*DB, *stubMetrics, string) { +- logger := testlog.Logger(t, log.LvlInfo) ++ logger := testlog.Logger(t, log.LvlTrace) + path := filepath.Join(dir, "test.db") + m := &stubMetrics{} +- db, err := NewFromFile(logger, m, path) ++ db, err := NewFromFile(logger, m, path, false) + require.NoError(t, err, "Failed to create database") + t.Cleanup(func() { + err := db.Close() +@@ -73,122 +76,243 @@ func TestEmptyDbDoesNotFindEntry(t *testing.T) { + runDBTest(t, + func(t *testing.T, db *DB, m *stubMetrics) {}, + func(t *testing.T, db *DB, m *stubMetrics) { +- requireNotContains(t, db, 0, 0, createHash(1)) +- requireNotContains(t, db, 0, 0, common.Hash{}) ++ requireFuture(t, db, 1, 0, createHash(1)) ++ requireFuture(t, db, 1, 0, common.Hash{}) + }) + } +  ++func TestLatestSealedBlockNum(t *testing.T) { ++ t.Run("Empty case", func(t *testing.T) { ++ runDBTest(t, ++ func(t *testing.T, db *DB, m *stubMetrics) {}, ++ func(t *testing.T, db *DB, m *stubMetrics) { ++ n, ok := db.LatestSealedBlockNum() ++ require.False(t, ok, "empty db expected") ++ require.Zero(t, n) ++ idx, err := db.searchCheckpoint(0, 0) ++ require.ErrorIs(t, err, ErrFuture, "no checkpoint in empty db") ++ require.Zero(t, idx) ++ }) ++ }) ++ t.Run("Zero case", func(t *testing.T) { ++ genesis := eth.BlockID{Hash: createHash(0), Number: 0} ++ runDBTest(t, ++ func(t *testing.T, db *DB, m *stubMetrics) { ++ require.NoError(t, db.SealBlock(common.Hash{}, genesis, 5000), "seal genesis") ++ }, ++ func(t *testing.T, db *DB, m *stubMetrics) { ++ n, ok := db.LatestSealedBlockNum() ++ require.True(t, ok, "genesis block expected") ++ require.Equal(t, genesis.Number, n) ++ idx, err := db.searchCheckpoint(0, 0) ++ require.NoError(t, err) ++ require.Zero(t, idx, "genesis block as checkpoint 0") ++ }) ++ }) ++ t.Run("Later genesis case", func(t *testing.T) { ++ genesis := eth.BlockID{Hash: createHash(10), Number: 10} ++ runDBTest(t, ++ func(t *testing.T, db *DB, m *stubMetrics) { ++ require.NoError(t, db.SealBlock(common.Hash{}, genesis, 5000), "seal genesis") ++ }, ++ func(t *testing.T, db *DB, m *stubMetrics) { ++ n, ok := db.LatestSealedBlockNum() ++ require.True(t, ok, "genesis block expected") ++ require.Equal(t, genesis.Number, n) ++ idx, err := db.searchCheckpoint(genesis.Number, 0) ++ require.NoError(t, err) ++ require.Zero(t, idx, "anchor block as checkpoint 0") ++ _, err = db.searchCheckpoint(0, 0) ++ require.ErrorIs(t, err, ErrSkipped, "no checkpoint before genesis") ++ }) ++ }) ++ t.Run("Block 1 case", func(t *testing.T) { ++ genesis := eth.BlockID{Hash: createHash(0), Number: 0} ++ block1 := eth.BlockID{Hash: createHash(1), Number: 1} ++ runDBTest(t, ++ func(t *testing.T, db *DB, m *stubMetrics) { ++ require.NoError(t, db.SealBlock(common.Hash{}, genesis, 5000), "seal genesis") ++ require.NoError(t, db.SealBlock(genesis.Hash, block1, 5001), "seal block 1") ++ }, ++ func(t *testing.T, db *DB, m *stubMetrics) { ++ n, ok := db.LatestSealedBlockNum() ++ require.True(t, ok, "block 1 expected") ++ require.Equal(t, block1.Number, n) ++ idx, err := db.searchCheckpoint(block1.Number, 0) ++ require.NoError(t, err) ++ require.Equal(t, entrydb.EntryIdx(0), idx, "checkpoint 0 still for block 1") ++ }) ++ }) ++ t.Run("Using checkpoint case", func(t *testing.T) { ++ genesis := eth.BlockID{Hash: createHash(0), Number: 0} ++ runDBTest(t, ++ func(t *testing.T, db *DB, m *stubMetrics) { ++ require.NoError(t, db.SealBlock(common.Hash{}, genesis, 5000), "seal genesis") ++ for i := 1; i <= 260; i++ { ++ id := eth.BlockID{Hash: createHash(i), Number: uint64(i)} ++ require.NoError(t, db.SealBlock(createHash(i-1), id, 5001), "seal block %d", i) ++ } ++ }, ++ func(t *testing.T, db *DB, m *stubMetrics) { ++ n, ok := db.LatestSealedBlockNum() ++ require.True(t, ok, "latest block expected") ++ expected := uint64(260) ++ require.Equal(t, expected, n) ++ idx, err := db.searchCheckpoint(expected, 0) ++ require.NoError(t, err) ++ // It costs 2 entries per block, so if we add more than 1 checkpoint worth of blocks, ++ // then we get to checkpoint 2 ++ require.Equal(t, entrydb.EntryIdx(searchCheckpointFrequency*2), idx, "checkpoint 1 reached") ++ }) ++ }) ++} ++ + func TestAddLog(t *testing.T) { + t.Run("BlockZero", func(t *testing.T) { + // There are no logs in the genesis block so recording an entry for block 0 should be rejected. + runDBTest(t, + func(t *testing.T, db *DB, m *stubMetrics) {}, + func(t *testing.T, db *DB, m *stubMetrics) { +- err := db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(15), Number: 0}, 5000, 0, nil) ++ genesis := eth.BlockID{Hash: createHash(15), Number: 0} ++ err := db.AddLog(createHash(1), genesis, 0, nil) + require.ErrorIs(t, err, ErrLogOutOfOrder) + }) + }) +  +- t.Run("FirstEntry", func(t *testing.T) { ++ t.Run("FirstEntries", func(t *testing.T) { + runDBTest(t, + func(t *testing.T, db *DB, m *stubMetrics) { +- err := db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(15), Number: 15}, 5000, 0, nil) +- require.NoError(t, err) ++ genesis := eth.BlockID{Hash: createHash(15), Number: 15} ++ require.NoError(t, db.SealBlock(common.Hash{}, genesis, 5000), "seal genesis") ++ err := db.AddLog(createHash(1), genesis, 0, nil) ++ require.NoError(t, err, "first log after genesis") ++ require.NoError(t, db.SealBlock(genesis.Hash, eth.BlockID{Hash: createHash(16), Number: 16}, 5001)) + }, + func(t *testing.T, db *DB, m *stubMetrics) { +- requireContains(t, db, 15, 0, createHash(1)) ++ requireContains(t, db, 16, 0, createHash(1)) + }) + }) +  + t.Run("MultipleEntriesFromSameBlock", func(t *testing.T) { + runDBTest(t, + func(t *testing.T, db *DB, m *stubMetrics) { +- err := db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(15), Number: 15}, 5000, 0, nil) ++ // create 15 empty blocks ++ for i := 0; i <= 15; i++ { ++ bl := eth.BlockID{Hash: createHash(i), Number: uint64(i)} ++ require.NoError(t, db.SealBlock(createHash(i-1), bl, 5000+uint64(i)), "seal blocks") ++ } ++ // Now apply 3 logs on top of that, contents for block 16 ++ bl15 := eth.BlockID{Hash: createHash(15), Number: 15} ++ err := db.AddLog(createHash(1), bl15, 0, nil) + require.NoError(t, err) +- err = db.AddLog(createTruncatedHash(2), eth.BlockID{Hash: createHash(15), Number: 15}, 5000, 1, nil) ++ err = db.AddLog(createHash(2), bl15, 1, nil) + require.NoError(t, err) +- err = db.AddLog(createTruncatedHash(3), eth.BlockID{Hash: createHash(15), Number: 15}, 5000, 2, nil) ++ err = db.AddLog(createHash(3), bl15, 2, nil) ++ require.NoError(t, err) ++ // Now seal block 16 ++ bl16 := eth.BlockID{Hash: createHash(16), Number: 16} ++ err = db.SealBlock(bl15.Hash, bl16, 5016) + require.NoError(t, err) + }, + func(t *testing.T, db *DB, m *stubMetrics) { +- require.EqualValues(t, 5, m.entryCount, "should not output new searchCheckpoint for every log") +- requireContains(t, db, 15, 0, createHash(1)) +- requireContains(t, db, 15, 1, createHash(2)) +- requireContains(t, db, 15, 2, createHash(3)) ++ require.EqualValues(t, 16*2+3+2, m.entryCount, "empty blocks have logs") ++ requireContains(t, db, 16, 0, createHash(1)) ++ requireContains(t, db, 16, 1, createHash(2)) ++ requireContains(t, db, 16, 2, createHash(3)) + }) + }) +  + t.Run("MultipleEntriesFromMultipleBlocks", func(t *testing.T) { + runDBTest(t, + func(t *testing.T, db *DB, m *stubMetrics) { +- err := db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(15), Number: 15}, 5000, 0, nil) ++ bl14 := eth.BlockID{Hash: createHash(14), Number: 14} ++ err := db.SealBlock(createHash(13), bl14, 5000) + require.NoError(t, err) +- err = db.AddLog(createTruncatedHash(2), eth.BlockID{Hash: createHash(15), Number: 15}, 5000, 1, nil) ++ bl15 := eth.BlockID{Hash: createHash(15), Number: 15} ++ err = db.SealBlock(createHash(14), bl15, 5001) + require.NoError(t, err) +- err = db.AddLog(createTruncatedHash(3), eth.BlockID{Hash: createHash(16), Number: 16}, 5002, 0, nil) ++ err = db.AddLog(createHash(1), bl15, 0, nil) + require.NoError(t, err) +- err = db.AddLog(createTruncatedHash(4), eth.BlockID{Hash: createHash(16), Number: 16}, 5002, 1, nil) ++ err = db.AddLog(createHash(2), bl15, 1, nil) ++ require.NoError(t, err) ++ bl16 := eth.BlockID{Hash: createHash(16), Number: 16} ++ err = db.SealBlock(bl15.Hash, bl16, 5003) ++ require.NoError(t, err) ++ err = db.AddLog(createHash(3), bl16, 0, nil) ++ require.NoError(t, err) ++ err = db.AddLog(createHash(4), bl16, 1, nil) ++ require.NoError(t, err) ++ bl17 := eth.BlockID{Hash: createHash(17), Number: 17} ++ err = db.SealBlock(bl16.Hash, bl17, 5003) + require.NoError(t, err) + }, + func(t *testing.T, db *DB, m *stubMetrics) { +- require.EqualValues(t, 6, m.entryCount, "should not output new searchCheckpoint for every block") +- requireContains(t, db, 15, 0, createHash(1)) +- requireContains(t, db, 15, 1, createHash(2)) +- requireContains(t, db, 16, 0, createHash(3)) +- requireContains(t, db, 16, 1, createHash(4)) ++ require.EqualValues(t, 2+2+1+1+2+1+1+2, m.entryCount, "should not output new searchCheckpoint for every block") ++ requireContains(t, db, 16, 0, createHash(1)) ++ requireContains(t, db, 16, 1, createHash(2)) ++ requireContains(t, db, 17, 0, createHash(3)) ++ requireContains(t, db, 17, 1, createHash(4)) + }) + }) +  + t.Run("ErrorWhenBeforeCurrentBlock", func(t *testing.T) { + runDBTest(t, + func(t *testing.T, db *DB, m *stubMetrics) { +- err := db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(15), Number: 15}, 5000, 0, nil) ++ bl15 := eth.BlockID{Hash: createHash(15), Number: 15} ++ err := db.SealBlock(common.Hash{}, bl15, 5001) + require.NoError(t, err) + }, + func(t *testing.T, db *DB, m *stubMetrics) { +- err := db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(14), Number: 14}, 4998, 0, nil) +- require.ErrorIs(t, err, ErrLogOutOfOrder) ++ bl14 := eth.BlockID{Hash: createHash(14), Number: 14} ++ err := db.SealBlock(createHash(13), bl14, 5000) ++ require.ErrorIs(t, err, ErrConflict) + }) + }) +  + t.Run("ErrorWhenBeforeCurrentBlockButAfterLastCheckpoint", func(t *testing.T) { + runDBTest(t, + func(t *testing.T, db *DB, m *stubMetrics) { +- err := db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(13), Number: 13}, 5000, 0, nil) ++ err := db.lastEntryContext.forceBlock(eth.BlockID{Hash: createHash(13), Number: 13}, 5000) + require.NoError(t, err) +- err = db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(15), Number: 15}, 5000, 0, nil) ++ err = db.SealBlock(createHash(13), eth.BlockID{Hash: createHash(14), Number: 14}, 5001) ++ require.NoError(t, err) ++ err = db.SealBlock(createHash(14), eth.BlockID{Hash: createHash(15), Number: 15}, 5002) + require.NoError(t, err) + }, + func(t *testing.T, db *DB, m *stubMetrics) { +- err := db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(14), Number: 14}, 4998, 0, nil) +- require.ErrorIs(t, err, ErrLogOutOfOrder) ++ onto := eth.BlockID{Hash: createHash(14), Number: 14} ++ err := db.AddLog(createHash(1), onto, 0, nil) ++ require.ErrorIs(t, err, ErrLogOutOfOrder, "cannot build logs on 14 when 15 is already sealed") + }) + }) +  + t.Run("ErrorWhenBeforeCurrentLogEvent", func(t *testing.T) { + runDBTest(t, + func(t *testing.T, db *DB, m *stubMetrics) { +- require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(15), Number: 15}, 5000, 0, nil)) +- require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(15), Number: 15}, 5000, 1, nil)) ++ bl15 := eth.BlockID{Hash: createHash(15), Number: 15} ++ err := db.lastEntryContext.forceBlock(bl15, 5000) ++ require.NoError(t, err) ++ require.NoError(t, db.AddLog(createHash(1), bl15, 0, nil)) ++ require.NoError(t, db.AddLog(createHash(1), bl15, 1, nil)) + }, + func(t *testing.T, db *DB, m *stubMetrics) { +- err := db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(14), Number: 15}, 4998, 0, nil) +- require.ErrorIs(t, err, ErrLogOutOfOrder) ++ bl15 := eth.BlockID{Hash: createHash(15), Number: 15} ++ err := db.AddLog(createHash(1), bl15, 0, nil) ++ require.ErrorIs(t, err, ErrLogOutOfOrder, "already at log index 2") + }) + }) +  +- t.Run("ErrorWhenBeforeCurrentLogEventButAfterLastCheckpoint", func(t *testing.T) { ++ t.Run("ErrorWhenBeforeBlockSeal", func(t *testing.T) { + runDBTest(t, + func(t *testing.T, db *DB, m *stubMetrics) { +- err := db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(15), Number: 15}, 5000, 0, nil) ++ bl15 := eth.BlockID{Hash: createHash(15), Number: 15} ++ err := db.lastEntryContext.forceBlock(bl15, 5000) + require.NoError(t, err) +- err = db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(15), Number: 15}, 5000, 1, nil) +- require.NoError(t, err) +- err = db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(15), Number: 15}, 5000, 2, nil) +- require.NoError(t, err) ++ require.NoError(t, db.AddLog(createHash(1), bl15, 0, nil)) ++ require.NoError(t, db.AddLog(createHash(1), bl15, 1, nil)) + }, + func(t *testing.T, db *DB, m *stubMetrics) { +- err := db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(14), Number: 15}, 4998, 1, nil) ++ err := db.AddLog(createHash(1), eth.BlockID{Hash: createHash(16), Number: 16}, 0, nil) + require.ErrorIs(t, err, ErrLogOutOfOrder) + }) + }) +@@ -196,24 +320,31 @@ + t.Run("ErrorWhenAtCurrentLogEvent", func(t *testing.T) { + runDBTest(t, + func(t *testing.T, db *DB, m *stubMetrics) { +- require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(15), Number: 15}, 5000, 0, nil)) +- require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(15), Number: 15}, 5000, 1, nil)) ++ bl15 := eth.BlockID{Hash: createHash(15), Number: 15} ++ err := db.lastEntryContext.forceBlock(bl15, 5000) ++ require.NoError(t, err) ++ require.NoError(t, db.AddLog(createHash(1), bl15, 0, nil)) ++ require.NoError(t, db.AddLog(createHash(1), bl15, 1, nil)) + }, + func(t *testing.T, db *DB, m *stubMetrics) { +- err := db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(15), Number: 15}, 4998, 1, nil) +- require.ErrorIs(t, err, ErrLogOutOfOrder) ++ bl15 := eth.BlockID{Hash: createHash(15), Number: 15} ++ err := db.AddLog(createHash(1), bl15, 1, nil) ++ require.ErrorIs(t, err, ErrLogOutOfOrder, "already at log index 2") + }) + }) +  + t.Run("ErrorWhenAtCurrentLogEventButAfterLastCheckpoint", func(t *testing.T) { + runDBTest(t, + func(t *testing.T, db *DB, m *stubMetrics) { +- require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(15), Number: 15}, 5000, 0, nil)) +- require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(15), Number: 15}, 5000, 1, nil)) +- require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(15), Number: 15}, 5000, 2, nil)) ++ bl15 := eth.BlockID{Hash: createHash(15), Number: 15} ++ err := db.lastEntryContext.forceBlock(bl15, 5000) ++ require.NoError(t, err) ++ require.NoError(t, db.AddLog(createHash(1), bl15, 0, nil)) ++ require.NoError(t, db.AddLog(createHash(1), bl15, 1, nil)) + }, + func(t *testing.T, db *DB, m *stubMetrics) { +- err := db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(14), Number: 15}, 4998, 2, nil) ++ bl15 := eth.BlockID{Hash: createHash(16), Number: 16} ++ err := db.AddLog(createHash(1), bl15, 2, nil) + require.ErrorIs(t, err, ErrLogOutOfOrder) + }) + }) +@@ -221,19 +352,27 @@ + t.Run("ErrorWhenSkippingLogEvent", func(t *testing.T) { + runDBTest(t, + func(t *testing.T, db *DB, m *stubMetrics) { +- err := db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(15), Number: 15}, 5000, 0, nil) ++ bl15 := eth.BlockID{Hash: createHash(15), Number: 15} ++ err := db.lastEntryContext.forceBlock(bl15, 5000) + require.NoError(t, err) ++ require.NoError(t, db.AddLog(createHash(1), bl15, 0, nil)) + }, + func(t *testing.T, db *DB, m *stubMetrics) { +- err := db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(15), Number: 15}, 4998, 2, nil) ++ bl15 := eth.BlockID{Hash: createHash(15), Number: 15} ++ err := db.AddLog(createHash(1), bl15, 2, nil) + require.ErrorIs(t, err, ErrLogOutOfOrder) + }) + }) +  + t.Run("ErrorWhenFirstLogIsNotLogIdxZero", func(t *testing.T) { +- runDBTest(t, func(t *testing.T, db *DB, m *stubMetrics) {}, ++ runDBTest(t, func(t *testing.T, db *DB, m *stubMetrics) { ++ bl15 := eth.BlockID{Hash: createHash(15), Number: 15} ++ err := db.lastEntryContext.forceBlock(bl15, 5000) ++ require.NoError(t, err) ++ }, + func(t *testing.T, db *DB, m *stubMetrics) { +- err := db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(15), Number: 15}, 4998, 5, nil) ++ bl15 := eth.BlockID{Hash: createHash(15), Number: 15} ++ err := db.AddLog(createHash(1), bl15, 5, nil) + require.ErrorIs(t, err, ErrLogOutOfOrder) + }) + }) +@@ -241,54 +380,102 @@ + t.Run("ErrorWhenFirstLogOfNewBlockIsNotLogIdxZero", func(t *testing.T) { + runDBTest(t, + func(t *testing.T, db *DB, m *stubMetrics) { +- require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(14), Number: 14}, 4996, 0, nil)) ++ bl15 := eth.BlockID{Hash: createHash(15), Number: 15} ++ err := db.lastEntryContext.forceBlock(bl15, 5000) ++ require.NoError(t, err) ++ err = db.AddLog(createHash(1), bl15, 0, nil) ++ require.NoError(t, err) + }, + func(t *testing.T, db *DB, m *stubMetrics) { +- err := db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(15), Number: 15}, 4998, 1, nil) ++ bl15 := eth.BlockID{Hash: createHash(15), Number: 15} ++ err := db.AddLog(createHash(1), bl15, 1, nil) ++ require.NoError(t, err) ++ bl16 := eth.BlockID{Hash: createHash(16), Number: 16} ++ err = db.SealBlock(bl15.Hash, bl16, 5001) ++ require.NoError(t, err) ++ err = db.AddLog(createHash(1), bl16, 1, nil) + require.ErrorIs(t, err, ErrLogOutOfOrder) + }) + }) +  + t.Run("MultipleSearchCheckpoints", func(t *testing.T) { ++ block0 := eth.BlockID{Hash: createHash(10), Number: 10} + block1 := eth.BlockID{Hash: createHash(11), Number: 11} + block2 := eth.BlockID{Hash: createHash(12), Number: 12} +- block3 := eth.BlockID{Hash: createHash(15), Number: 15} +- block4 := eth.BlockID{Hash: createHash(16), Number: 16} +- // First checkpoint is at entry idx 0 +- // Block 1 logs don't reach the second checkpoint ++ block3 := eth.BlockID{Hash: createHash(13), Number: 13} ++ block4 := eth.BlockID{Hash: createHash(14), Number: 14} ++ // Ignoring seal-checkpoints in checkpoint counting comments here; ++ // First search-checkpoint is at entry idx 0 ++ // Block 1 logs don't reach the second search-checkpoint + block1LogCount := searchCheckpointFrequency - 10 +- // Block 2 logs extend to just after the third checkpoint +- block2LogCount := searchCheckpointFrequency + 20 +- // Block 3 logs extend to immediately before the fourth checkpoint +- block3LogCount := searchCheckpointFrequency - 16 ++ // Block 2 logs extend to just after the third search-checkpoint ++ block2LogCount := searchCheckpointFrequency + 16 ++ // Block 3 logs extend to immediately before the fourth search-checkpoint ++ block3LogCount := searchCheckpointFrequency - 19 + block4LogCount := 2 + runDBTest(t, + func(t *testing.T, db *DB, m *stubMetrics) { +- for i := 0; i < block1LogCount; i++ { +- err := db.AddLog(createTruncatedHash(i), block1, 3000, uint32(i), nil) +- require.NoErrorf(t, err, "failed to add log %v of block 1", i) ++ // force in block 0 ++ require.NoError(t, db.lastEntryContext.forceBlock(block0, 3000)) ++ expectedIndex := entrydb.EntryIdx(2) ++ t.Logf("block 0 complete, at entry %d", db.lastEntryContext.NextIndex()) ++ require.Equal(t, expectedIndex, db.lastEntryContext.NextIndex()) ++ { // create block 1 ++ for i := 0; i < block1LogCount; i++ { ++ err := db.AddLog(createHash(i), block0, uint32(i), nil) ++ require.NoError(t, err) ++ } ++ err := db.SealBlock(block0.Hash, block1, 3001) // second seal-checkpoint ++ require.NoError(t, err) + } +- for i := 0; i < block2LogCount; i++ { +- err := db.AddLog(createTruncatedHash(i), block2, 3002, uint32(i), nil) +- require.NoErrorf(t, err, "failed to add log %v of block 2", i) ++ expectedIndex += entrydb.EntryIdx(block1LogCount) + 2 ++ t.Logf("block 1 complete, at entry %d", db.lastEntryContext.NextIndex()) ++ require.Equal(t, expectedIndex, db.lastEntryContext.NextIndex(), "added logs and a seal checkpoint") ++ { // create block 2 ++ for i := 0; i < block2LogCount; i++ { ++ // two of these imply a search checkpoint, the second and third search-checkpoint ++ err := db.AddLog(createHash(i), block1, uint32(i), nil) ++ require.NoError(t, err) ++ } ++ err := db.SealBlock(block1.Hash, block2, 3002) // third seal-checkpoint ++ require.NoError(t, err) + } +- for i := 0; i < block3LogCount; i++ { +- err := db.AddLog(createTruncatedHash(i), block3, 3004, uint32(i), nil) +- require.NoErrorf(t, err, "failed to add log %v of block 3", i) ++ expectedIndex += entrydb.EntryIdx(block2LogCount) + 2 + 2 + 2 ++ t.Logf("block 2 complete, at entry %d", db.lastEntryContext.NextIndex()) ++ require.Equal(t, expectedIndex, db.lastEntryContext.NextIndex(), "added logs, two search checkpoints, and a seal checkpoint") ++ { // create block 3 ++ for i := 0; i < block3LogCount; i++ { ++ err := db.AddLog(createHash(i), block2, uint32(i), nil) ++ require.NoError(t, err) ++ } ++ err := db.SealBlock(block2.Hash, block3, 3003) ++ require.NoError(t, err) + } +- // Verify that we're right before the fourth checkpoint will be written. ++ expectedIndex += entrydb.EntryIdx(block3LogCount) + 2 ++ t.Logf("block 3 complete, at entry %d", db.lastEntryContext.NextIndex()) ++ require.Equal(t, expectedIndex, db.lastEntryContext.NextIndex(), "added logs, and a seal checkpoint") ++ ++ // Verify that we're right before the fourth search-checkpoint will be written. + // entryCount is the number of entries, so given 0 based indexing is the index of the next entry + // the first checkpoint is at entry 0, the second at entry searchCheckpointFrequency etc +- // so the fourth is at entry 3*searchCheckpointFrequency +- require.EqualValues(t, 3*searchCheckpointFrequency, m.entryCount) +- for i := 0; i < block4LogCount; i++ { +- err := db.AddLog(createTruncatedHash(i), block4, 3006, uint32(i), nil) +- require.NoErrorf(t, err, "failed to add log %v of block 4", i) ++ // so the fourth is at entry 3*searchCheckpointFrequency. ++ require.EqualValues(t, 3*searchCheckpointFrequency-1, m.entryCount) ++ { // create block 4 ++ for i := 0; i < block4LogCount; i++ { ++ // includes a fourth search checkpoint ++ err := db.AddLog(createHash(i), block3, uint32(i), nil) ++ require.NoError(t, err) ++ } ++ err := db.SealBlock(block3.Hash, block4, 3003) // fourth seal checkpoint ++ require.NoError(t, err) + } ++ expectedIndex += entrydb.EntryIdx(block4LogCount) + 2 + 2 ++ require.Equal(t, expectedIndex, db.lastEntryContext.NextIndex(), "added logs, a search checkpoint, and a seal checkpoint") ++ t.Logf("block 4 complete, at entry %d", db.lastEntryContext.NextIndex()) + }, + func(t *testing.T, db *DB, m *stubMetrics) { +- // Check that we wrote additional search checkpoints +- expectedCheckpointCount := 4 ++ // Check that we wrote additional search checkpoints and seal checkpoints ++ expectedCheckpointCount := 4 + 4 + expectedEntryCount := block1LogCount + block2LogCount + block3LogCount + block4LogCount + (2 * expectedCheckpointCount) + require.EqualValues(t, expectedEntryCount, m.entryCount) + // Check we can find all the logs. +@@ -317,73 +504,98 @@ Chain: 3, + BlockNum: 42894, + LogIdx: 42, + Timestamp: 8742482, +- Hash: types.TruncateHash(createHash(8844)), ++ Hash: createHash(8844), + } + t.Run("FirstEntry", func(t *testing.T) { + runDBTest(t, + func(t *testing.T, db *DB, m *stubMetrics) { +- err := db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(15), Number: 15}, 5000, 0, &execMsg) ++ bl15 := eth.BlockID{Hash: createHash(15), Number: 15} ++ require.NoError(t, db.lastEntryContext.forceBlock(bl15, 5000)) ++ err := db.AddLog(createHash(1), bl15, 0, &execMsg) + require.NoError(t, err) + }, + func(t *testing.T, db *DB, m *stubMetrics) { +- requireContains(t, db, 15, 0, createHash(1), execMsg) ++ requireContains(t, db, 16, 0, createHash(1), execMsg) + }) + }) +  +- t.Run("CheckpointBetweenInitEventAndExecLink", func(t *testing.T) { ++ t.Run("BlockSealSearchCheckpointOverlap", func(t *testing.T) { + runDBTest(t, + func(t *testing.T, db *DB, m *stubMetrics) { ++ bl15 := eth.BlockID{Hash: createHash(15), Number: 15} ++ require.NoError(t, db.lastEntryContext.forceBlock(bl15, 5000)) + for i := uint32(0); m.entryCount < searchCheckpointFrequency-1; i++ { +- require.NoError(t, db.AddLog(createTruncatedHash(9), eth.BlockID{Hash: createHash(9), Number: 1}, 500, i, nil)) ++ require.NoError(t, db.AddLog(createHash(9), bl15, i, nil)) + } +- err := db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(15), Number: 15}, 5000, 0, &execMsg) ++ bl16 := eth.BlockID{Hash: createHash(16), Number: 16} ++ require.NoError(t, db.SealBlock(bl15.Hash, bl16, 5001)) ++ // added 3 entries: seal-checkpoint, then a search-checkpoint, then the canonical hash ++ require.Equal(t, m.entryCount, int64(searchCheckpointFrequency+2)) ++ err := db.AddLog(createHash(1), bl16, 0, &execMsg) + require.NoError(t, err) + }, + func(t *testing.T, db *DB, m *stubMetrics) { +- requireContains(t, db, 15, 0, createHash(1), execMsg) ++ requireContains(t, db, 16, 0, createHash(9)) ++ requireContains(t, db, 17, 0, createHash(1), execMsg) + }) + }) +  +- t.Run("CheckpointBetweenInitEventAndExecLinkNotIncrementingBlock", func(t *testing.T) { ++ t.Run("AvoidCheckpointOverlapWithExecutingCheck", func(t *testing.T) { + runDBTest(t, + func(t *testing.T, db *DB, m *stubMetrics) { +- +- for i := uint32(0); m.entryCount < searchCheckpointFrequency-1; i++ { +- require.NoError(t, db.AddLog(createTruncatedHash(9), eth.BlockID{Hash: createHash(9), Number: 1}, 500, i, nil)) ++ bl15 := eth.BlockID{Hash: createHash(15), Number: 15} ++ require.NoError(t, db.lastEntryContext.forceBlock(bl15, 5000)) ++ // we add 256 - 2 (start) - 2 (init msg, exec link) = 252 entries ++ for i := uint32(0); i < 252; i++ { ++ require.NoError(t, db.AddLog(createHash(9), bl15, i, nil)) + } +- err := db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(15), Number: 1}, 5000, 253, &execMsg) ++ // add an executing message ++ err := db.AddLog(createHash(1), bl15, 252, &execMsg) + require.NoError(t, err) ++ // 0,1: start ++ // 2..252+2: initiating logs without exec message ++ // 254 = inferred padding - 3 entries for exec msg would overlap with checkpoint ++ // 255 = inferred padding ++ // 256 = search checkpoint - what would be the exec check without padding ++ // 257 = canonical hash ++ // 258 = initiating message ++ // 259 = executing message link ++ // 260 = executing message check ++ require.Equal(t, int64(261), m.entryCount) ++ db.debugTip() + }, + func(t *testing.T, db *DB, m *stubMetrics) { +- requireContains(t, db, 1, 253, createHash(1), execMsg) ++ requireContains(t, db, 16, 251, createHash(9)) ++ requireContains(t, db, 16, 252, createHash(1), execMsg) + }) + }) +  +- t.Run("CheckpointBetweenExecLinkAndExecCheck", func(t *testing.T) { ++ t.Run("AvoidCheckpointOverlapWithExecutingLink", func(t *testing.T) { + runDBTest(t, + func(t *testing.T, db *DB, m *stubMetrics) { +- for i := uint32(0); m.entryCount < searchCheckpointFrequency-2; i++ { +- require.NoError(t, db.AddLog(createTruncatedHash(9), eth.BlockID{Hash: createHash(9), Number: 1}, 500, i, nil)) ++ bl15 := eth.BlockID{Hash: createHash(15), Number: 15} ++ require.NoError(t, db.lastEntryContext.forceBlock(bl15, 5000)) ++ // we add 256 - 2 (start) - 1 (init msg) = 253 entries ++ for i := uint32(0); i < 253; i++ { ++ require.NoError(t, db.AddLog(createHash(9), bl15, i, nil)) + } +- err := db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(15), Number: 15}, 5000, 0, &execMsg) ++ // add an executing message ++ err := db.AddLog(createHash(1), bl15, 253, &execMsg) + require.NoError(t, err) ++ // 0,1: start ++ // 2..253+2: initiating logs without exec message ++ // 255 = inferred padding - 3 entries for exec msg would overlap with checkpoint ++ // 256 = search checkpoint - what would be the exec link without padding ++ // 257 = canonical hash ++ // 258 = initiating message ++ // 259 = executing message link ++ // 260 = executing message check ++ db.debugTip() ++ require.Equal(t, int64(261), m.entryCount) + }, + func(t *testing.T, db *DB, m *stubMetrics) { +- requireContains(t, db, 15, 0, createHash(1), execMsg) +- }) +- }) +- +- t.Run("CheckpointBetweenExecLinkAndExecCheckNotIncrementingBlock", func(t *testing.T) { +- runDBTest(t, +- func(t *testing.T, db *DB, m *stubMetrics) { +- for i := uint32(0); m.entryCount < searchCheckpointFrequency-2; i++ { +- require.NoError(t, db.AddLog(createTruncatedHash(9), eth.BlockID{Hash: createHash(9), Number: 1}, 500, i, nil)) +- } +- err := db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(15), Number: 1}, 5000, 252, &execMsg) +- require.NoError(t, err) +- }, +- func(t *testing.T, db *DB, m *stubMetrics) { +- requireContains(t, db, 1, 252, createHash(1), execMsg) ++ requireContains(t, db, 16, 252, createHash(9)) ++ requireContains(t, db, 16, 253, createHash(1), execMsg) + }) + }) + } +@@ -391,35 +603,36 @@ + func TestContains(t *testing.T) { + runDBTest(t, + func(t *testing.T, db *DB, m *stubMetrics) { +- require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(50), Number: 50}, 500, 0, nil)) +- require.NoError(t, db.AddLog(createTruncatedHash(3), eth.BlockID{Hash: createHash(50), Number: 50}, 500, 1, nil)) +- require.NoError(t, db.AddLog(createTruncatedHash(2), eth.BlockID{Hash: createHash(50), Number: 50}, 500, 2, nil)) +- require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(52), Number: 52}, 500, 0, nil)) +- require.NoError(t, db.AddLog(createTruncatedHash(3), eth.BlockID{Hash: createHash(52), Number: 52}, 500, 1, nil)) ++ bl50 := eth.BlockID{Hash: createHash(50), Number: 50} ++ require.NoError(t, db.lastEntryContext.forceBlock(bl50, 5000)) ++ require.NoError(t, db.AddLog(createHash(1), bl50, 0, nil)) ++ require.NoError(t, db.AddLog(createHash(3), bl50, 1, nil)) ++ require.NoError(t, db.AddLog(createHash(2), bl50, 2, nil)) ++ bl51 := eth.BlockID{Hash: createHash(51), Number: 51} ++ require.NoError(t, db.SealBlock(bl50.Hash, bl51, 5001)) ++ bl52 := eth.BlockID{Hash: createHash(52), Number: 52} ++ require.NoError(t, db.SealBlock(bl51.Hash, bl52, 5001)) ++ require.NoError(t, db.AddLog(createHash(1), bl52, 0, nil)) ++ require.NoError(t, db.AddLog(createHash(3), bl52, 1, nil)) + }, + func(t *testing.T, db *DB, m *stubMetrics) { + // Should find added logs +- requireContains(t, db, 50, 0, createHash(1)) +- requireContains(t, db, 50, 1, createHash(3)) +- requireContains(t, db, 50, 2, createHash(2)) +- requireContains(t, db, 52, 0, createHash(1)) +- requireContains(t, db, 52, 1, createHash(3)) ++ requireContains(t, db, 51, 0, createHash(1)) ++ requireContains(t, db, 51, 1, createHash(3)) ++ requireContains(t, db, 51, 2, createHash(2)) ++ requireContains(t, db, 53, 0, createHash(1)) ++ requireContains(t, db, 53, 1, createHash(3)) +  +- // Should not find log when block number too low +- requireNotContains(t, db, 49, 0, createHash(1)) ++ // 52 was sealed as empty ++ requireConflicts(t, db, 52, 0, createHash(1)) +  +- // Should not find log when block number too high +- requireNotContains(t, db, 51, 0, createHash(1)) ++ // 53 only contained 2 logs, not 3, and is not sealed yet ++ requireFuture(t, db, 53, 2, createHash(3)) ++ // 54 doesn't exist yet ++ requireFuture(t, db, 54, 0, createHash(3)) +  +- // Should not find log when requested log after end of database +- requireNotContains(t, db, 52, 2, createHash(3)) +- requireNotContains(t, db, 53, 0, createHash(3)) +- +- // Should not find log when log index too high +- requireNotContains(t, db, 50, 3, createHash(2)) +- +- // Should not find log when hash doesn't match log at block number and index +- requireWrongHash(t, db, 50, 0, createHash(5), types.ExecutingMessage{}) ++ // 51 only contained 3 logs, not 4 ++ requireConflicts(t, db, 51, 3, createHash(2)) + }) + } +  +@@ -429,72 +642,81 @@ Chain: 33, + BlockNum: 22, + LogIdx: 99, + Timestamp: 948294, +- Hash: createTruncatedHash(332299), ++ Hash: createHash(332299), + } + execMsg2 := types.ExecutingMessage{ + Chain: 44, + BlockNum: 55, + LogIdx: 66, + Timestamp: 77777, +- Hash: createTruncatedHash(445566), ++ Hash: createHash(445566), + } + execMsg3 := types.ExecutingMessage{ + Chain: 77, + BlockNum: 88, + LogIdx: 89, + Timestamp: 6578567, +- Hash: createTruncatedHash(778889), ++ Hash: createHash(778889), + } + runDBTest(t, + func(t *testing.T, db *DB, m *stubMetrics) { +- require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(50), Number: 50}, 500, 0, nil)) +- require.NoError(t, db.AddLog(createTruncatedHash(3), eth.BlockID{Hash: createHash(50), Number: 50}, 500, 1, &execMsg1)) +- require.NoError(t, db.AddLog(createTruncatedHash(2), eth.BlockID{Hash: createHash(50), Number: 50}, 500, 2, nil)) +- require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(52), Number: 52}, 500, 0, &execMsg2)) +- require.NoError(t, db.AddLog(createTruncatedHash(3), eth.BlockID{Hash: createHash(52), Number: 52}, 500, 1, &execMsg3)) ++ bl50 := eth.BlockID{Hash: createHash(50), Number: 50} ++ require.NoError(t, db.lastEntryContext.forceBlock(bl50, 500)) ++ require.NoError(t, db.AddLog(createHash(1), bl50, 0, nil)) ++ require.NoError(t, db.AddLog(createHash(3), bl50, 1, &execMsg1)) ++ require.NoError(t, db.AddLog(createHash(2), bl50, 2, nil)) ++ bl51 := eth.BlockID{Hash: createHash(51), Number: 51} ++ require.NoError(t, db.SealBlock(bl50.Hash, bl51, 5001)) ++ bl52 := eth.BlockID{Hash: createHash(52), Number: 52} ++ require.NoError(t, db.SealBlock(bl51.Hash, bl52, 5001)) ++ require.NoError(t, db.AddLog(createHash(1), bl52, 0, &execMsg2)) ++ require.NoError(t, db.AddLog(createHash(3), bl52, 1, &execMsg3)) + }, + func(t *testing.T, db *DB, m *stubMetrics) { + // Should find added logs +- requireExecutingMessage(t, db, 50, 0, types.ExecutingMessage{}) +- requireExecutingMessage(t, db, 50, 1, execMsg1) +- requireExecutingMessage(t, db, 50, 2, types.ExecutingMessage{}) +- requireExecutingMessage(t, db, 52, 0, execMsg2) +- requireExecutingMessage(t, db, 52, 1, execMsg3) ++ requireExecutingMessage(t, db, 51, 0, types.ExecutingMessage{}) ++ requireExecutingMessage(t, db, 51, 1, execMsg1) ++ requireExecutingMessage(t, db, 51, 2, types.ExecutingMessage{}) ++ requireExecutingMessage(t, db, 53, 0, execMsg2) ++ requireExecutingMessage(t, db, 53, 1, execMsg3) +  +- // Should not find log when block number too low +- requireNotContains(t, db, 49, 0, createHash(1)) ++ // 52 was sealed without logs ++ requireConflicts(t, db, 52, 0, createHash(1)) +  +- // Should not find log when block number too high +- requireNotContains(t, db, 51, 0, createHash(1)) +- +- // Should not find log when requested log after end of database +- requireNotContains(t, db, 52, 2, createHash(3)) +- requireNotContains(t, db, 53, 0, createHash(3)) ++ // 53 only contained 2 logs, not 3, and is not sealed yet ++ requireFuture(t, db, 53, 2, createHash(3)) ++ // 54 doesn't exist yet ++ requireFuture(t, db, 54, 0, createHash(3)) +  +- // Should not find log when log index too high +- requireNotContains(t, db, 50, 3, createHash(2)) ++ // 51 only contained 3 logs, not 4 ++ requireConflicts(t, db, 51, 3, createHash(2)) + }) + } +  + func TestGetBlockInfo(t *testing.T) { +- t.Run("ReturnsEOFWhenEmpty", func(t *testing.T) { ++ t.Run("ReturnsErrFutureWhenEmpty", func(t *testing.T) { + runDBTest(t, + func(t *testing.T, db *DB, m *stubMetrics) {}, + func(t *testing.T, db *DB, m *stubMetrics) { +- _, _, err := db.ClosestBlockInfo(10) +- require.ErrorIs(t, err, io.EOF) ++ bl10 := eth.BlockID{Hash: createHash(10), Number: 10} ++ _, err := db.FindSealedBlock(bl10) ++ require.ErrorIs(t, err, ErrFuture) + }) + }) +  +- t.Run("ReturnsEOFWhenRequestedBlockBeforeFirstSearchCheckpoint", func(t *testing.T) { ++ t.Run("ReturnsErrFutureWhenRequestedBlockBeforeFirstSearchCheckpoint", func(t *testing.T) { + runDBTest(t, + func(t *testing.T, db *DB, m *stubMetrics) { +- err := db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(11), Number: 11}, 500, 0, nil) ++ bl11 := eth.BlockID{Hash: createHash(11), Number: 11} ++ require.NoError(t, db.lastEntryContext.forceBlock(bl11, 500)) ++ err := db.AddLog(createHash(1), bl11, 0, nil) + require.NoError(t, err) + }, + func(t *testing.T, db *DB, m *stubMetrics) { +- _, _, err := db.ClosestBlockInfo(10) +- require.ErrorIs(t, err, io.EOF) ++ // if the DB starts at 11, then shouldn't find 10 ++ bl10 := eth.BlockID{Hash: createHash(10), Number: 10} ++ _, err := db.FindSealedBlock(bl10) ++ require.ErrorIs(t, err, ErrSkipped) + }) + }) +  +@@ -502,56 +724,24 @@ t.Run("ReturnFirstBlockInfo", func(t *testing.T) { + block := eth.BlockID{Hash: createHash(11), Number: 11} + runDBTest(t, + func(t *testing.T, db *DB, m *stubMetrics) { +- err := db.AddLog(createTruncatedHash(1), block, 500, 0, nil) +- require.NoError(t, err) +- }, +- func(t *testing.T, db *DB, m *stubMetrics) { +- requireClosestBlockInfo(t, db, 11, block.Number, block.Hash) +- requireClosestBlockInfo(t, db, 12, block.Number, block.Hash) +- requireClosestBlockInfo(t, db, 200, block.Number, block.Hash) +- }) +- }) +- +- t.Run("ReturnClosestCheckpointBlockInfo", func(t *testing.T) { +- runDBTest(t, +- func(t *testing.T, db *DB, m *stubMetrics) { +- for i := 1; i < searchCheckpointFrequency+3; i++ { +- block := eth.BlockID{Hash: createHash(i), Number: uint64(i)} +- err := db.AddLog(createTruncatedHash(i), block, uint64(i)*2, 0, nil) +- require.NoError(t, err) +- } ++ require.NoError(t, db.SealBlock(common.Hash{}, block, 500)) + }, + func(t *testing.T, db *DB, m *stubMetrics) { +- // Expect block from the first checkpoint +- requireClosestBlockInfo(t, db, 1, 1, createHash(1)) +- requireClosestBlockInfo(t, db, 10, 1, createHash(1)) +- requireClosestBlockInfo(t, db, searchCheckpointFrequency-3, 1, createHash(1)) +- +- // Expect block from the second checkpoint +- // 2 entries used for initial checkpoint but we start at block 1 +- secondCheckpointBlockNum := searchCheckpointFrequency - 1 +- requireClosestBlockInfo(t, db, uint64(secondCheckpointBlockNum), uint64(secondCheckpointBlockNum), createHash(secondCheckpointBlockNum)) +- requireClosestBlockInfo(t, db, uint64(secondCheckpointBlockNum)+1, uint64(secondCheckpointBlockNum), createHash(secondCheckpointBlockNum)) +- requireClosestBlockInfo(t, db, uint64(secondCheckpointBlockNum)+2, uint64(secondCheckpointBlockNum), createHash(secondCheckpointBlockNum)) ++ index, err := db.FindSealedBlock(block) ++ require.NoError(t, err) ++ require.Equal(t, entrydb.EntryIdx(2), index, ++ "expecting to continue after search checkpoint that declared the block") + }) + }) + } +  +-func requireClosestBlockInfo(t *testing.T, db *DB, searchFor uint64, expectedBlockNum uint64, expectedHash common.Hash) { +- blockNum, hash, err := db.ClosestBlockInfo(searchFor) +- require.NoError(t, err) +- require.Equal(t, expectedBlockNum, blockNum) +- require.Equal(t, types.TruncateHash(expectedHash), hash) +-} +- + func requireContains(t *testing.T, db *DB, blockNum uint64, logIdx uint32, logHash common.Hash, execMsg ...types.ExecutingMessage) { + require.LessOrEqual(t, len(execMsg), 1, "cannot have multiple executing messages for a single log") + m, ok := db.m.(*stubMetrics) + require.True(t, ok, "Did not get the expected metrics type") +- result, _, err := db.Contains(blockNum, logIdx, types.TruncateHash(logHash)) ++ _, err := db.Contains(blockNum, logIdx, logHash) + require.NoErrorf(t, err, "Error searching for log %v in block %v", logIdx, blockNum) +- require.Truef(t, result, "Did not find log %v in block %v with hash %v", logIdx, blockNum, logHash) +- require.LessOrEqual(t, m.entriesReadForSearch, int64(searchCheckpointFrequency), "Should not need to read more than between two checkpoints") ++ require.LessOrEqual(t, m.entriesReadForSearch, int64(searchCheckpointFrequency*2), "Should not need to read more than between two checkpoints") + require.NotZero(t, m.entriesReadForSearch, "Must read at least some entries to find the log") +  + var expectedExecMsg types.ExecutingMessage +@@ -561,318 +751,354 @@ } + requireExecutingMessage(t, db, blockNum, logIdx, expectedExecMsg) + } +  +-func requireNotContains(t *testing.T, db *DB, blockNum uint64, logIdx uint32, logHash common.Hash) { ++func requireConflicts(t *testing.T, db *DB, blockNum uint64, logIdx uint32, logHash common.Hash) { + m, ok := db.m.(*stubMetrics) + require.True(t, ok, "Did not get the expected metrics type") +- result, _, err := db.Contains(blockNum, logIdx, types.TruncateHash(logHash)) +- require.NoErrorf(t, err, "Error searching for log %v in block %v", logIdx, blockNum) +- require.Falsef(t, result, "Found unexpected log %v in block %v with hash %v", logIdx, blockNum, logHash) +- require.LessOrEqual(t, m.entriesReadForSearch, int64(searchCheckpointFrequency), "Should not need to read more than between two checkpoints") +- +- _, err = db.Executes(blockNum, logIdx) +- require.ErrorIs(t, err, ErrNotFound, "Found unexpected log when getting executing message") +- require.LessOrEqual(t, m.entriesReadForSearch, int64(searchCheckpointFrequency), "Should not need to read more than between two checkpoints") ++ _, err := db.Contains(blockNum, logIdx, logHash) ++ require.ErrorIs(t, err, ErrConflict, "canonical chain must not include this log") ++ require.LessOrEqual(t, m.entriesReadForSearch, int64(searchCheckpointFrequency*2), "Should not need to read more than between two checkpoints") + } +  +-func requireExecutingMessage(t *testing.T, db *DB, blockNum uint64, logIdx uint32, execMsg types.ExecutingMessage) { ++func requireFuture(t *testing.T, db *DB, blockNum uint64, logIdx uint32, logHash common.Hash) { + m, ok := db.m.(*stubMetrics) + require.True(t, ok, "Did not get the expected metrics type") +- actualExecMsg, err := db.Executes(blockNum, logIdx) +- require.NoError(t, err, "Error when searching for executing message") +- require.Equal(t, execMsg, actualExecMsg, "Should return matching executing message") +- require.LessOrEqual(t, m.entriesReadForSearch, int64(searchCheckpointFrequency), "Should not need to read more than between two checkpoints") +- require.NotZero(t, m.entriesReadForSearch, "Must read at least some entries to find the log") ++ _, err := db.Contains(blockNum, logIdx, logHash) ++ require.ErrorIs(t, err, ErrFuture, "canonical chain does not yet include this log") ++ require.LessOrEqual(t, m.entriesReadForSearch, int64(searchCheckpointFrequency*2), "Should not need to read more than between two checkpoints") + } +  +-func requireWrongHash(t *testing.T, db *DB, blockNum uint64, logIdx uint32, logHash common.Hash, _ types.ExecutingMessage) { ++func requireExecutingMessage(t *testing.T, db *DB, blockNum uint64, logIdx uint32, execMsg types.ExecutingMessage) { + m, ok := db.m.(*stubMetrics) + require.True(t, ok, "Did not get the expected metrics type") +- result, _, err := db.Contains(blockNum, logIdx, types.TruncateHash(logHash)) +- require.NoErrorf(t, err, "Error searching for log %v in block %v", logIdx, blockNum) +- require.Falsef(t, result, "Found unexpected log %v in block %v with hash %v", logIdx, blockNum, logHash) +- +- _, err = db.Executes(blockNum, logIdx) ++ _, iter, err := db.findLogInfo(blockNum, logIdx) + require.NoError(t, err, "Error when searching for executing message") +- require.LessOrEqual(t, m.entriesReadForSearch, int64(searchCheckpointFrequency), "Should not need to read more than between two checkpoints") ++ actualExecMsg := iter.ExecMessage() // non-nil if not just an initiating message, but also an executing message ++ if execMsg == (types.ExecutingMessage{}) { ++ require.Nil(t, actualExecMsg) ++ } else { ++ require.NotNil(t, actualExecMsg) ++ require.Equal(t, execMsg, *actualExecMsg, "Should return matching executing message") ++ } ++ require.LessOrEqual(t, m.entriesReadForSearch, int64(searchCheckpointFrequency*2), "Should not need to read more than between two checkpoints") ++ require.NotZero(t, m.entriesReadForSearch, "Must read at least some entries to find the log") + } +  + func TestRecoverOnCreate(t *testing.T) { + createDb := func(t *testing.T, store *stubEntryStore) (*DB, *stubMetrics, error) { + logger := testlog.Logger(t, log.LvlInfo) + m := &stubMetrics{} +- db, err := NewFromEntryStore(logger, m, store) ++ db, err := NewFromEntryStore(logger, m, store, true) + return db, m, err + } +  +- validInitEvent, err := newInitiatingEvent(logContext{blockNum: 1, logIdx: 0}, 1, 0, createTruncatedHash(1), false) +- require.NoError(t, err) +- validEventSequence := []entrydb.Entry{ +- newSearchCheckpoint(1, 0, 100).encode(), +- newCanonicalHash(createTruncatedHash(344)).encode(), +- validInitEvent.encode(), ++ storeWithEvents := func(evts ...entrydb.Entry) *stubEntryStore { ++ store := &stubEntryStore{} ++ store.entries = append(store.entries, evts...) ++ return store + } +- var emptyEventSequence []entrydb.Entry ++ t.Run("NoTruncateWhenLastEntryIsLogWithNoExecMessageSealed", func(t *testing.T) { ++ store := storeWithEvents( ++ // seal 0, 1, 2, 3 ++ newSearchCheckpoint(0, 0, 100).encode(), ++ newCanonicalHash(createHash(300)).encode(), ++ newSearchCheckpoint(1, 0, 101).encode(), ++ newCanonicalHash(createHash(301)).encode(), ++ newSearchCheckpoint(2, 0, 102).encode(), ++ newCanonicalHash(createHash(302)).encode(), ++ newSearchCheckpoint(3, 0, 103).encode(), ++ newCanonicalHash(createHash(303)).encode(), ++ // open and seal 4 ++ newInitiatingEvent(createHash(1), false).encode(), ++ newSearchCheckpoint(4, 0, 104).encode(), ++ newCanonicalHash(createHash(304)).encode(), ++ ) ++ db, m, err := createDb(t, store) ++ require.NoError(t, err) ++ require.EqualValues(t, int64(4*2+3), m.entryCount) ++ requireContains(t, db, 4, 0, createHash(1)) ++ }) +  +- for _, prefixEvents := range [][]entrydb.Entry{emptyEventSequence, validEventSequence} { +- prefixEvents := prefixEvents +- storeWithEvents := func(evts ...entrydb.Entry) *stubEntryStore { +- store := &stubEntryStore{} +- store.entries = append(store.entries, prefixEvents...) +- store.entries = append(store.entries, evts...) +- return store ++ t.Run("NoTruncateWhenLastEntryIsExecutingCheckSealed", func(t *testing.T) { ++ execMsg := types.ExecutingMessage{ ++ Chain: 4, ++ BlockNum: 10, ++ LogIdx: 4, ++ Timestamp: 1288, ++ Hash: createHash(4), + } +- t.Run(fmt.Sprintf("PrefixEvents-%v", len(prefixEvents)), func(t *testing.T) { +- t.Run("NoTruncateWhenLastEntryIsLogWithNoExecMessage", func(t *testing.T) { +- initEvent, err := newInitiatingEvent(logContext{blockNum: 3, logIdx: 0}, 3, 0, createTruncatedHash(1), false) +- require.NoError(t, err) +- store := storeWithEvents( +- newSearchCheckpoint(3, 0, 100).encode(), +- newCanonicalHash(createTruncatedHash(344)).encode(), +- initEvent.encode(), +- ) +- db, m, err := createDb(t, store) +- require.NoError(t, err) +- require.EqualValues(t, len(prefixEvents)+3, m.entryCount) +- requireContains(t, db, 3, 0, createHash(1)) +- }) ++ linkEvt, err := newExecutingLink(execMsg) ++ require.NoError(t, err) ++ store := storeWithEvents( ++ newSearchCheckpoint(0, 0, 100).encode(), ++ newCanonicalHash(createHash(300)).encode(), ++ newSearchCheckpoint(1, 0, 101).encode(), ++ newCanonicalHash(createHash(301)).encode(), ++ newSearchCheckpoint(2, 0, 102).encode(), ++ newCanonicalHash(createHash(302)).encode(), ++ newInitiatingEvent(createHash(1111), true).encode(), ++ linkEvt.encode(), ++ newExecutingCheck(execMsg.Hash).encode(), ++ newSearchCheckpoint(3, 0, 103).encode(), ++ newCanonicalHash(createHash(303)).encode(), ++ ) ++ db, m, err := createDb(t, store) ++ require.NoError(t, err) ++ require.EqualValues(t, int64(3*2+5), m.entryCount) ++ requireContains(t, db, 3, 0, createHash(1111), execMsg) ++ }) +  +- t.Run("NoTruncateWhenLastEntryIsExecutingCheck", func(t *testing.T) { +- initEvent, err := newInitiatingEvent(logContext{blockNum: 3, logIdx: 0}, 3, 0, createTruncatedHash(1), true) +- execMsg := types.ExecutingMessage{ +- Chain: 4, +- BlockNum: 10, +- LogIdx: 4, +- Timestamp: 1288, +- Hash: createTruncatedHash(4), +- } +- require.NoError(t, err) +- linkEvt, err := newExecutingLink(execMsg) +- require.NoError(t, err) +- store := storeWithEvents( +- newSearchCheckpoint(3, 0, 100).encode(), +- newCanonicalHash(createTruncatedHash(344)).encode(), +- initEvent.encode(), +- linkEvt.encode(), +- newExecutingCheck(execMsg.Hash).encode(), +- ) +- db, m, err := createDb(t, store) +- require.NoError(t, err) +- require.EqualValues(t, len(prefixEvents)+5, m.entryCount) +- requireContains(t, db, 3, 0, createHash(1), execMsg) +- }) ++ t.Run("TruncateWhenLastEntrySearchCheckpoint", func(t *testing.T) { ++ // A checkpoint, without a canonical blockhash, is useless, and thus truncated. ++ store := storeWithEvents( ++ newSearchCheckpoint(0, 0, 100).encode()) ++ _, m, err := createDb(t, store) ++ require.NoError(t, err) ++ require.EqualValues(t, int64(0), m.entryCount) ++ }) +  +- t.Run("TruncateWhenLastEntrySearchCheckpoint", func(t *testing.T) { +- store := storeWithEvents(newSearchCheckpoint(3, 0, 100).encode()) +- _, m, err := createDb(t, store) +- require.NoError(t, err) +- require.EqualValues(t, len(prefixEvents), m.entryCount) +- }) ++ t.Run("NoTruncateWhenLastEntryCanonicalHash", func(t *testing.T) { ++ // A completed seal is fine to have as last entry. ++ store := storeWithEvents( ++ newSearchCheckpoint(0, 0, 100).encode(), ++ newCanonicalHash(createHash(344)).encode(), ++ ) ++ _, m, err := createDb(t, store) ++ require.NoError(t, err) ++ require.EqualValues(t, int64(2), m.entryCount) ++ }) +  +- t.Run("TruncateWhenLastEntryCanonicalHash", func(t *testing.T) { +- store := storeWithEvents( +- newSearchCheckpoint(3, 0, 100).encode(), +- newCanonicalHash(createTruncatedHash(344)).encode(), +- ) +- _, m, err := createDb(t, store) +- require.NoError(t, err) +- require.EqualValues(t, len(prefixEvents), m.entryCount) +- }) ++ t.Run("TruncateWhenLastEntryInitEventWithExecMsg", func(t *testing.T) { ++ // An initiating event that claims an executing message, ++ // without said executing message, is dropped. ++ store := storeWithEvents( ++ newSearchCheckpoint(0, 0, 100).encode(), ++ newCanonicalHash(createHash(344)).encode(), ++ // both pruned because we go back to a seal ++ newInitiatingEvent(createHash(0), false).encode(), ++ newInitiatingEvent(createHash(1), true).encode(), ++ ) ++ _, m, err := createDb(t, store) ++ require.NoError(t, err) ++ require.EqualValues(t, int64(2), m.entryCount) ++ }) +  +- t.Run("TruncateWhenLastEntryInitEventWithExecMsg", func(t *testing.T) { +- initEvent, err := newInitiatingEvent(logContext{blockNum: 3, logIdx: 0}, 3, 0, createTruncatedHash(1), true) +- require.NoError(t, err) +- store := storeWithEvents( +- newSearchCheckpoint(3, 0, 100).encode(), +- newCanonicalHash(createTruncatedHash(344)).encode(), +- initEvent.encode(), +- ) +- _, m, err := createDb(t, store) +- require.NoError(t, err) +- require.EqualValues(t, len(prefixEvents), m.entryCount) +- }) ++ t.Run("NoTruncateWhenLastEntrySealed", func(t *testing.T) { ++ // An initiating event that claims an executing message, ++ // without said executing message, is dropped. ++ store := storeWithEvents( ++ newSearchCheckpoint(0, 0, 100).encode(), ++ newCanonicalHash(createHash(300)).encode(), ++ // pruned because we go back to a seal ++ newInitiatingEvent(createHash(0), false).encode(), ++ newSearchCheckpoint(1, 0, 100).encode(), ++ newCanonicalHash(createHash(301)).encode(), ++ ) ++ _, m, err := createDb(t, store) ++ require.NoError(t, err) ++ require.EqualValues(t, int64(5), m.entryCount) ++ }) +  +- t.Run("TruncateWhenLastEntryInitEventWithExecLink", func(t *testing.T) { +- initEvent, err := newInitiatingEvent(logContext{blockNum: 3, logIdx: 0}, 3, 0, createTruncatedHash(1), true) +- require.NoError(t, err) +- execMsg := types.ExecutingMessage{ +- Chain: 4, +- BlockNum: 10, +- LogIdx: 4, +- Timestamp: 1288, +- Hash: createTruncatedHash(4), +- } +- require.NoError(t, err) +- linkEvt, err := newExecutingLink(execMsg) +- require.NoError(t, err) +- store := storeWithEvents( +- newSearchCheckpoint(3, 0, 100).encode(), +- newCanonicalHash(createTruncatedHash(344)).encode(), +- initEvent.encode(), +- linkEvt.encode(), +- ) +- _, m, err := createDb(t, store) +- require.NoError(t, err) +- require.EqualValues(t, len(prefixEvents), m.entryCount) +- }) +- }) +- } ++ t.Run("TruncateWhenLastEntryInitEventWithExecLink", func(t *testing.T) { ++ execMsg := types.ExecutingMessage{ ++ Chain: 4, ++ BlockNum: 10, ++ LogIdx: 4, ++ Timestamp: 1288, ++ Hash: createHash(4), ++ } ++ linkEvt, err := newExecutingLink(execMsg) ++ require.NoError(t, err) ++ store := storeWithEvents( ++ newSearchCheckpoint(3, 0, 100).encode(), ++ newCanonicalHash(createHash(344)).encode(), ++ newInitiatingEvent(createHash(1), true).encode(), ++ linkEvt.encode(), ++ ) ++ _, m, err := createDb(t, store) ++ require.NoError(t, err) ++ require.EqualValues(t, int64(2), m.entryCount) ++ }) + } +  + func TestRewind(t *testing.T) { + t.Run("WhenEmpty", func(t *testing.T) { + runDBTest(t, func(t *testing.T, db *DB, m *stubMetrics) {}, + func(t *testing.T, db *DB, m *stubMetrics) { +- require.NoError(t, db.Rewind(100)) +- require.NoError(t, db.Rewind(0)) ++ require.ErrorIs(t, db.Rewind(100), ErrFuture) ++ // Genesis is a block to, not present in an empty DB ++ require.ErrorIs(t, db.Rewind(0), ErrFuture) + }) + }) +  + t.Run("AfterLastBlock", func(t *testing.T) { + runDBTest(t, + func(t *testing.T, db *DB, m *stubMetrics) { +- require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(50), Number: 50}, 500, 0, nil)) +- require.NoError(t, db.AddLog(createTruncatedHash(2), eth.BlockID{Hash: createHash(50), Number: 50}, 500, 1, nil)) +- require.NoError(t, db.AddLog(createTruncatedHash(3), eth.BlockID{Hash: createHash(51), Number: 51}, 502, 0, nil)) +- require.NoError(t, db.AddLog(createTruncatedHash(4), eth.BlockID{Hash: createHash(74), Number: 74}, 700, 0, nil)) +- require.NoError(t, db.Rewind(75)) ++ bl50 := eth.BlockID{Hash: createHash(50), Number: 50} ++ require.NoError(t, db.SealBlock(createHash(49), bl50, 500)) ++ require.NoError(t, db.AddLog(createHash(1), bl50, 0, nil)) ++ require.NoError(t, db.AddLog(createHash(2), bl50, 1, nil)) ++ bl51 := eth.BlockID{Hash: createHash(51), Number: 51} ++ require.NoError(t, db.SealBlock(bl50.Hash, bl51, 502)) ++ require.NoError(t, db.AddLog(createHash(3), bl51, 0, nil)) ++ bl52 := eth.BlockID{Hash: createHash(52), Number: 52} ++ require.NoError(t, db.SealBlock(bl51.Hash, bl52, 504)) ++ require.NoError(t, db.AddLog(createHash(4), bl52, 0, nil)) ++ // cannot rewind to a block that is not sealed yet ++ require.ErrorIs(t, db.Rewind(53), ErrFuture) + }, + func(t *testing.T, db *DB, m *stubMetrics) { +- requireContains(t, db, 50, 0, createHash(1)) +- requireContains(t, db, 50, 1, createHash(2)) +- requireContains(t, db, 51, 0, createHash(3)) +- requireContains(t, db, 74, 0, createHash(4)) ++ requireContains(t, db, 51, 0, createHash(1)) ++ requireContains(t, db, 51, 1, createHash(2)) ++ requireContains(t, db, 52, 0, createHash(3)) ++ // Still have the pending log of unsealed block if the rewind to unknown sealed block fails ++ requireContains(t, db, 53, 0, createHash(4)) + }) + }) +  + t.Run("BeforeFirstBlock", func(t *testing.T) { + runDBTest(t, + func(t *testing.T, db *DB, m *stubMetrics) { +- require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(50), Number: 50}, 500, 0, nil)) +- require.NoError(t, db.AddLog(createTruncatedHash(2), eth.BlockID{Hash: createHash(50), Number: 50}, 500, 1, nil)) +- require.NoError(t, db.Rewind(25)) ++ bl50 := eth.BlockID{Hash: createHash(50), Number: 50} ++ require.NoError(t, db.SealBlock(createHash(49), bl50, 500)) ++ require.NoError(t, db.AddLog(createHash(1), bl50, 0, nil)) ++ require.NoError(t, db.AddLog(createHash(2), bl50, 1, nil)) ++ // cannot go back to an unknown block ++ require.ErrorIs(t, db.Rewind(25), ErrSkipped) + }, + func(t *testing.T, db *DB, m *stubMetrics) { +- requireNotContains(t, db, 50, 0, createHash(1)) +- requireNotContains(t, db, 50, 0, createHash(1)) +- require.Zero(t, m.entryCount) ++ requireContains(t, db, 51, 0, createHash(1)) ++ requireContains(t, db, 51, 0, createHash(1)) + }) + }) +  + t.Run("AtFirstBlock", func(t *testing.T) { + runDBTest(t, + func(t *testing.T, db *DB, m *stubMetrics) { +- require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(50), Number: 50}, 500, 0, nil)) +- require.NoError(t, db.AddLog(createTruncatedHash(2), eth.BlockID{Hash: createHash(50), Number: 50}, 500, 1, nil)) +- require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(51), Number: 51}, 502, 0, nil)) +- require.NoError(t, db.AddLog(createTruncatedHash(2), eth.BlockID{Hash: createHash(51), Number: 51}, 502, 1, nil)) +- require.NoError(t, db.Rewind(50)) ++ bl50 := eth.BlockID{Hash: createHash(50), Number: 50} ++ require.NoError(t, db.SealBlock(createHash(49), bl50, 500)) ++ require.NoError(t, db.AddLog(createHash(1), bl50, 0, nil)) ++ require.NoError(t, db.AddLog(createHash(2), bl50, 1, nil)) ++ bl51 := eth.BlockID{Hash: createHash(51), Number: 51} ++ require.NoError(t, db.SealBlock(bl50.Hash, bl51, 502)) ++ require.NoError(t, db.AddLog(createHash(1), bl51, 0, nil)) ++ require.NoError(t, db.AddLog(createHash(2), bl51, 1, nil)) ++ bl52 := eth.BlockID{Hash: createHash(52), Number: 52} ++ require.NoError(t, db.SealBlock(bl51.Hash, bl52, 504)) ++ require.NoError(t, db.Rewind(51)) + }, + func(t *testing.T, db *DB, m *stubMetrics) { +- requireContains(t, db, 50, 0, createHash(1)) +- requireContains(t, db, 50, 1, createHash(2)) +- requireNotContains(t, db, 51, 0, createHash(1)) +- requireNotContains(t, db, 51, 1, createHash(2)) ++ requireContains(t, db, 51, 0, createHash(1)) ++ requireContains(t, db, 51, 1, createHash(2)) ++ requireFuture(t, db, 52, 0, createHash(1)) ++ requireFuture(t, db, 52, 1, createHash(2)) + }) + }) +  +- t.Run("AtSecondCheckpoint", func(t *testing.T) { ++ t.Run("AfterSecondCheckpoint", func(t *testing.T) { + runDBTest(t, + func(t *testing.T, db *DB, m *stubMetrics) { ++ bl50 := eth.BlockID{Hash: createHash(50), Number: 50} ++ require.NoError(t, db.SealBlock(createHash(49), bl50, 500)) + for i := uint32(0); m.entryCount < searchCheckpointFrequency; i++ { +- require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(50), Number: 50}, 500, i, nil)) ++ require.NoError(t, db.AddLog(createHash(1), bl50, i, nil)) + } +- require.EqualValues(t, searchCheckpointFrequency, m.entryCount) +- require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(51), Number: 51}, 502, 0, nil)) +- require.EqualValues(t, searchCheckpointFrequency+3, m.entryCount, "Should have inserted new checkpoint and extra log") +- require.NoError(t, db.AddLog(createTruncatedHash(2), eth.BlockID{Hash: createHash(51), Number: 51}, 502, 1, nil)) +- require.NoError(t, db.Rewind(50)) ++ // The checkpoint is added automatically, ++ // it will be there as soon as it reaches 255 with log events. ++ // Thus add 2 for the checkpoint. ++ require.EqualValues(t, searchCheckpointFrequency+2, m.entryCount) ++ bl51 := eth.BlockID{Hash: createHash(51), Number: 51} ++ require.NoError(t, db.SealBlock(bl50.Hash, bl51, 502)) ++ require.NoError(t, db.AddLog(createHash(1), bl51, 0, nil)) ++ require.EqualValues(t, searchCheckpointFrequency+2+3, m.entryCount, "Should have inserted new checkpoint and extra log") ++ require.NoError(t, db.AddLog(createHash(2), bl51, 1, nil)) ++ bl52 := eth.BlockID{Hash: createHash(52), Number: 52} ++ require.NoError(t, db.SealBlock(bl51.Hash, bl52, 504)) ++ require.NoError(t, db.Rewind(51)) + }, + func(t *testing.T, db *DB, m *stubMetrics) { +- require.EqualValues(t, searchCheckpointFrequency, m.entryCount, "Should have deleted second checkpoint") +- requireContains(t, db, 50, 0, createHash(1)) +- requireContains(t, db, 50, 1, createHash(1)) +- requireNotContains(t, db, 51, 0, createHash(1)) +- requireNotContains(t, db, 51, 1, createHash(2)) ++ require.EqualValues(t, searchCheckpointFrequency+2+2, m.entryCount, "Should have deleted second checkpoint") ++ requireContains(t, db, 51, 0, createHash(1)) ++ requireContains(t, db, 51, 1, createHash(1)) ++ requireFuture(t, db, 52, 0, createHash(1)) ++ requireFuture(t, db, 52, 1, createHash(2)) + }) + }) +  +- t.Run("BetweenLogEntries", func(t *testing.T) { ++ t.Run("BetweenBlockEntries", func(t *testing.T) { + runDBTest(t, + func(t *testing.T, db *DB, m *stubMetrics) { +- require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(50), Number: 50}, 500, 0, nil)) +- require.NoError(t, db.AddLog(createTruncatedHash(2), eth.BlockID{Hash: createHash(50), Number: 50}, 500, 1, nil)) +- require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(60), Number: 60}, 502, 0, nil)) +- require.NoError(t, db.AddLog(createTruncatedHash(2), eth.BlockID{Hash: createHash(60), Number: 60}, 502, 1, nil)) +- require.NoError(t, db.Rewind(55)) +- }, +- func(t *testing.T, db *DB, m *stubMetrics) { +- requireContains(t, db, 50, 0, createHash(1)) +- requireContains(t, db, 50, 1, createHash(2)) +- requireNotContains(t, db, 60, 0, createHash(1)) +- requireNotContains(t, db, 60, 1, createHash(2)) +- }) +- }) +- +- t.Run("AtExistingLogEntry", func(t *testing.T) { +- runDBTest(t, +- func(t *testing.T, db *DB, m *stubMetrics) { +- require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(59), Number: 59}, 500, 0, nil)) +- require.NoError(t, db.AddLog(createTruncatedHash(2), eth.BlockID{Hash: createHash(59), Number: 59}, 500, 1, nil)) +- require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(60), Number: 60}, 502, 0, nil)) +- require.NoError(t, db.AddLog(createTruncatedHash(2), eth.BlockID{Hash: createHash(60), Number: 60}, 502, 1, nil)) +- require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(61), Number: 61}, 502, 0, nil)) +- require.NoError(t, db.AddLog(createTruncatedHash(2), eth.BlockID{Hash: createHash(61), Number: 61}, 502, 1, nil)) +- require.NoError(t, db.Rewind(60)) ++ // create many blocks, and all the odd blocks get 2 logs ++ for i := uint32(0); i < 30; i++ { ++ bl := eth.BlockID{Hash: createHash(int(i)), Number: uint64(i)} ++ require.NoError(t, db.SealBlock(createHash(int(i)-1), bl, 500+uint64(i))) ++ if i%2 == 0 { ++ require.NoError(t, db.AddLog(createHash(1), bl, 0, nil)) ++ require.NoError(t, db.AddLog(createHash(2), bl, 1, nil)) ++ } ++ } ++ require.NoError(t, db.Rewind(15)) + }, + func(t *testing.T, db *DB, m *stubMetrics) { +- requireContains(t, db, 59, 0, createHash(1)) +- requireContains(t, db, 59, 1, createHash(2)) +- requireContains(t, db, 60, 0, createHash(1)) +- requireContains(t, db, 60, 1, createHash(2)) +- requireNotContains(t, db, 61, 0, createHash(1)) +- requireNotContains(t, db, 61, 1, createHash(2)) ++ requireContains(t, db, 15, 0, createHash(1)) ++ requireContains(t, db, 15, 1, createHash(2)) ++ requireFuture(t, db, 16, 0, createHash(1)) ++ requireFuture(t, db, 16, 1, createHash(2)) + }) + }) +  + t.Run("AtLastEntry", func(t *testing.T) { + runDBTest(t, + func(t *testing.T, db *DB, m *stubMetrics) { +- require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(50), Number: 50}, 500, 0, nil)) +- require.NoError(t, db.AddLog(createTruncatedHash(2), eth.BlockID{Hash: createHash(50), Number: 50}, 500, 1, nil)) +- require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(60), Number: 60}, 502, 0, nil)) +- require.NoError(t, db.AddLog(createTruncatedHash(2), eth.BlockID{Hash: createHash(60), Number: 60}, 502, 1, nil)) +- require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(70), Number: 70}, 502, 0, nil)) +- require.NoError(t, db.AddLog(createTruncatedHash(2), eth.BlockID{Hash: createHash(70), Number: 70}, 502, 1, nil)) +- require.NoError(t, db.Rewind(70)) ++ // create many blocks, and all the even blocks get 2 logs ++ for i := uint32(0); i <= 30; i++ { ++ bl := eth.BlockID{Hash: createHash(int(i)), Number: uint64(i)} ++ require.NoError(t, db.SealBlock(createHash(int(i)-1), bl, 500+uint64(i))) ++ if i%2 == 1 { ++ require.NoError(t, db.AddLog(createHash(1), bl, 0, nil)) ++ require.NoError(t, db.AddLog(createHash(2), bl, 1, nil)) ++ } ++ } ++ // We ended at 30, and sealed it, nothing left to prune ++ require.NoError(t, db.Rewind(30)) + }, + func(t *testing.T, db *DB, m *stubMetrics) { +- requireContains(t, db, 50, 0, createHash(1)) +- requireContains(t, db, 50, 1, createHash(2)) +- requireContains(t, db, 60, 0, createHash(1)) +- requireContains(t, db, 60, 1, createHash(2)) +- requireContains(t, db, 70, 0, createHash(1)) +- requireContains(t, db, 70, 1, createHash(2)) ++ requireContains(t, db, 20, 0, createHash(1)) ++ requireContains(t, db, 20, 1, createHash(2)) ++ // built on top of 29, these are in sealed block 30, still around ++ requireContains(t, db, 30, 0, createHash(1)) ++ requireContains(t, db, 30, 1, createHash(2)) + }) + }) +  +- t.Run("ReaddDeletedBlocks", func(t *testing.T) { ++ t.Run("ReadDeletedBlocks", func(t *testing.T) { + runDBTest(t, + func(t *testing.T, db *DB, m *stubMetrics) { +- require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(59), Number: 59}, 500, 0, nil)) +- require.NoError(t, db.AddLog(createTruncatedHash(2), eth.BlockID{Hash: createHash(59), Number: 59}, 500, 1, nil)) +- require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(60), Number: 60}, 502, 0, nil)) +- require.NoError(t, db.AddLog(createTruncatedHash(2), eth.BlockID{Hash: createHash(60), Number: 60}, 502, 1, nil)) +- require.NoError(t, db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(61), Number: 61}, 502, 0, nil)) +- require.NoError(t, db.AddLog(createTruncatedHash(2), eth.BlockID{Hash: createHash(61), Number: 61}, 502, 1, nil)) +- require.NoError(t, db.Rewind(60)) ++ // create many blocks, and all the odd blocks get 2 logs ++ for i := uint32(0); i < 30; i++ { ++ bl := eth.BlockID{Hash: createHash(int(i)), Number: uint64(i)} ++ require.NoError(t, db.SealBlock(createHash(int(i)-1), bl, 500+uint64(i))) ++ if i%2 == 0 { ++ require.NoError(t, db.AddLog(createHash(1), bl, 0, nil)) ++ require.NoError(t, db.AddLog(createHash(2), bl, 1, nil)) ++ } ++ } ++ require.NoError(t, db.Rewind(16)) + }, + func(t *testing.T, db *DB, m *stubMetrics) { +- err := db.AddLog(createTruncatedHash(2), eth.BlockID{Hash: createHash(59), Number: 59}, 500, 1, nil) +- require.ErrorIs(t, err, ErrLogOutOfOrder, "Cannot add block before rewound head") +- err = db.AddLog(createTruncatedHash(2), eth.BlockID{Hash: createHash(60), Number: 60}, 502, 1, nil) +- require.ErrorIs(t, err, ErrLogOutOfOrder, "Cannot add block that was rewound to") +- err = db.AddLog(createTruncatedHash(1), eth.BlockID{Hash: createHash(60), Number: 61}, 502, 0, nil) +- require.NoError(t, err, "Can re-add deleted block") ++ bl29 := eth.BlockID{Hash: createHash(29), Number: 29} ++ // 29 was deleted ++ err := db.AddLog(createHash(2), bl29, 1, nil) ++ require.ErrorIs(t, err, ErrLogOutOfOrder, "Cannot add log on removed block") ++ // 15 is older, we have up to 16 ++ bl15 := eth.BlockID{Hash: createHash(15), Number: 15} ++ // try to add a third log to 15 ++ err = db.AddLog(createHash(10), bl15, 2, nil) ++ require.ErrorIs(t, err, ErrLogOutOfOrder) ++ bl16 := eth.BlockID{Hash: createHash(16), Number: 16} ++ // try to add a log to 17, on top of 16 ++ err = db.AddLog(createHash(42), bl16, 0, nil) ++ require.NoError(t, err) ++ requireContains(t, db, 17, 0, createHash(42)) + }) + }) + }
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+59
+
-119
+ +
+ +
+
+
diff --git OP/op-supervisor/supervisor/backend/db/logs/entries.go CELO/op-supervisor/supervisor/backend/db/logs/entries.go +index 8816474cdd2fef3d495661c9acac58ba731cddda..431adc99f465d40643e7e81842e94da39b7ba127 100644 +--- OP/op-supervisor/supervisor/backend/db/logs/entries.go ++++ CELO/op-supervisor/supervisor/backend/db/logs/entries.go +@@ -3,161 +3,111 @@ + import ( + "encoding/binary" + "fmt" +- "math" ++ ++ "github.com/ethereum/go-ethereum/common" +  + "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/db/entrydb" +- "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/types" ++ "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" + ) +  ++// searchCheckpoint is both a checkpoint for searching, as well as a checkpoint for sealing blocks. + type searchCheckpoint struct { +- blockNum uint64 +- logIdx uint32 ++ blockNum uint64 ++ // seen logs *after* the seal of the mentioned block, i.e. not part of this block, but building on top of it. ++ // There is at least one checkpoint per L2 block with logsSince == 0, i.e. the exact block boundary. ++ logsSince uint32 + timestamp uint64 + } +  +-func newSearchCheckpoint(blockNum uint64, logIdx uint32, timestamp uint64) searchCheckpoint { ++func newSearchCheckpoint(blockNum uint64, logsSince uint32, timestamp uint64) searchCheckpoint { + return searchCheckpoint{ + blockNum: blockNum, +- logIdx: logIdx, ++ logsSince: logsSince, + timestamp: timestamp, + } + } +  + func newSearchCheckpointFromEntry(data entrydb.Entry) (searchCheckpoint, error) { +- if data[0] != typeSearchCheckpoint { +- return searchCheckpoint{}, fmt.Errorf("%w: attempting to decode search checkpoint but was type %v", ErrDataCorruption, data[0]) ++ if data.Type() != entrydb.TypeSearchCheckpoint { ++ return searchCheckpoint{}, fmt.Errorf("%w: attempting to decode search checkpoint but was type %s", ErrDataCorruption, data.Type()) + } + return searchCheckpoint{ + blockNum: binary.LittleEndian.Uint64(data[1:9]), +- logIdx: binary.LittleEndian.Uint32(data[9:13]), ++ logsSince: binary.LittleEndian.Uint32(data[9:13]), + timestamp: binary.LittleEndian.Uint64(data[13:21]), + }, nil + } +  +-// encode creates a search checkpoint entry +-// type 0: "search checkpoint" <type><uint64 block number: 8 bytes><uint32 event index offset: 4 bytes><uint64 timestamp: 8 bytes> = 20 bytes ++// encode creates a checkpoint entry ++// type 0: "search checkpoint" <type><uint64 block number: 8 bytes><uint32 logsSince count: 4 bytes><uint64 timestamp: 8 bytes> = 21 bytes + func (s searchCheckpoint) encode() entrydb.Entry { + var data entrydb.Entry +- data[0] = typeSearchCheckpoint ++ data[0] = uint8(entrydb.TypeSearchCheckpoint) + binary.LittleEndian.PutUint64(data[1:9], s.blockNum) +- binary.LittleEndian.PutUint32(data[9:13], s.logIdx) ++ binary.LittleEndian.PutUint32(data[9:13], s.logsSince) + binary.LittleEndian.PutUint64(data[13:21], s.timestamp) + return data + } +  + type canonicalHash struct { +- hash types.TruncatedHash ++ hash common.Hash + } +  +-func newCanonicalHash(hash types.TruncatedHash) canonicalHash { ++func newCanonicalHash(hash common.Hash) canonicalHash { + return canonicalHash{hash: hash} + } +  + func newCanonicalHashFromEntry(data entrydb.Entry) (canonicalHash, error) { +- if data[0] != typeCanonicalHash { +- return canonicalHash{}, fmt.Errorf("%w: attempting to decode canonical hash but was type %v", ErrDataCorruption, data[0]) ++ if data.Type() != entrydb.TypeCanonicalHash { ++ return canonicalHash{}, fmt.Errorf("%w: attempting to decode canonical hash but was type %s", ErrDataCorruption, data.Type()) + } +- var truncated types.TruncatedHash +- copy(truncated[:], data[1:21]) +- return newCanonicalHash(truncated), nil ++ return newCanonicalHash(common.Hash(data[1:33])), nil + } +  + func (c canonicalHash) encode() entrydb.Entry { + var entry entrydb.Entry +- entry[0] = typeCanonicalHash +- copy(entry[1:21], c.hash[:]) ++ entry[0] = uint8(entrydb.TypeCanonicalHash) ++ copy(entry[1:33], c.hash[:]) + return entry + } +  + type initiatingEvent struct { +- blockDiff uint8 +- incrementLogIdx bool +- hasExecMsg bool +- logHash types.TruncatedHash ++ hasExecMsg bool ++ logHash common.Hash + } +  + func newInitiatingEventFromEntry(data entrydb.Entry) (initiatingEvent, error) { +- if data[0] != typeInitiatingEvent { +- return initiatingEvent{}, fmt.Errorf("%w: attempting to decode initiating event but was type %v", ErrDataCorruption, data[0]) ++ if data.Type() != entrydb.TypeInitiatingEvent { ++ return initiatingEvent{}, fmt.Errorf("%w: attempting to decode initiating event but was type %s", ErrDataCorruption, data.Type()) + } +- blockNumDiff := data[1] +- flags := data[2] ++ flags := data[1] + return initiatingEvent{ +- blockDiff: blockNumDiff, +- incrementLogIdx: flags&eventFlagIncrementLogIdx != 0, +- hasExecMsg: flags&eventFlagHasExecutingMessage != 0, +- logHash: types.TruncatedHash(data[3:23]), ++ hasExecMsg: flags&eventFlagHasExecutingMessage != 0, ++ logHash: common.Hash(data[2:34]), + }, nil + } +  +-func newInitiatingEvent(pre logContext, blockNum uint64, logIdx uint32, logHash types.TruncatedHash, hasExecMsg bool) (initiatingEvent, error) { +- blockDiff := blockNum - pre.blockNum +- if blockDiff > math.MaxUint8 { +- // TODO(optimism#11091): Need to find a way to support this. +- return initiatingEvent{}, fmt.Errorf("too many block skipped between %v and %v", pre.blockNum, blockNum) +- } +- +- currLogIdx := pre.logIdx +- if blockDiff > 0 { +- currLogIdx = 0 +- } +- logDiff := logIdx - currLogIdx +- if logDiff > 1 { +- return initiatingEvent{}, fmt.Errorf("skipped logs between %v and %v", currLogIdx, logIdx) +- } +- ++func newInitiatingEvent(logHash common.Hash, hasExecMsg bool) initiatingEvent { + return initiatingEvent{ +- blockDiff: uint8(blockDiff), +- incrementLogIdx: logDiff > 0, +- hasExecMsg: hasExecMsg, +- logHash: logHash, +- }, nil ++ hasExecMsg: hasExecMsg, ++ logHash: logHash, ++ } + } +  + // encode creates an initiating event entry +-// type 2: "initiating event" <type><blocknum diff: 1 byte><event flags: 1 byte><event-hash: 20 bytes> = 23 bytes ++// type 2: "initiating event" <type><flags><event-hash: 20 bytes> = 22 bytes + func (i initiatingEvent) encode() entrydb.Entry { + var data entrydb.Entry +- data[0] = typeInitiatingEvent +- data[1] = i.blockDiff ++ data[0] = uint8(entrydb.TypeInitiatingEvent) + flags := byte(0) +- if i.incrementLogIdx { +- // Set flag to indicate log idx needs to be incremented (ie we're not directly after a checkpoint) +- flags = flags | eventFlagIncrementLogIdx +- } + if i.hasExecMsg { + flags = flags | eventFlagHasExecutingMessage + } +- data[2] = flags +- copy(data[3:23], i.logHash[:]) ++ data[1] = flags ++ copy(data[2:34], i.logHash[:]) + return data + } +  +-func (i initiatingEvent) postContext(pre logContext) logContext { +- post := logContext{ +- blockNum: pre.blockNum + uint64(i.blockDiff), +- logIdx: pre.logIdx, +- } +- if i.blockDiff > 0 { +- post.logIdx = 0 +- } +- if i.incrementLogIdx { +- post.logIdx++ +- } +- return post +-} +- +-// preContext is the reverse of postContext and calculates the logContext required as input to get the specified post +-// context after applying this init event. +-func (i initiatingEvent) preContext(post logContext) logContext { +- pre := post +- pre.blockNum = post.blockNum - uint64(i.blockDiff) +- if i.incrementLogIdx { +- pre.logIdx-- +- } +- return pre +-} +- + type executingLink struct { + chain uint32 + blockNum uint64 +@@ -178,8 +128,8 @@ }, nil + } +  + func newExecutingLinkFromEntry(data entrydb.Entry) (executingLink, error) { +- if data[0] != typeExecutingLink { +- return executingLink{}, fmt.Errorf("%w: attempting to decode executing link but was type %v", ErrDataCorruption, data[0]) ++ if data.Type() != entrydb.TypeExecutingLink { ++ return executingLink{}, fmt.Errorf("%w: attempting to decode executing link but was type %s", ErrDataCorruption, data.Type()) + } + timestamp := binary.LittleEndian.Uint64(data[16:24]) + return executingLink{ +@@ -194,7 +144,7 @@ // encode creates an executing link entry + // type 3: "executing link" <type><chain: 4 bytes><blocknum: 8 bytes><event index: 3 bytes><uint64 timestamp: 8 bytes> = 24 bytes + func (e executingLink) encode() entrydb.Entry { + var entry entrydb.Entry +- entry[0] = typeExecutingLink ++ entry[0] = uint8(entrydb.TypeExecutingLink) + binary.LittleEndian.PutUint32(entry[1:5], e.chain) + binary.LittleEndian.PutUint64(entry[5:13], e.blockNum) +  +@@ -207,45 +157,35 @@ return entry + } +  + type executingCheck struct { +- hash types.TruncatedHash ++ hash common.Hash + } +  +-func newExecutingCheck(hash types.TruncatedHash) executingCheck { ++func newExecutingCheck(hash common.Hash) executingCheck { + return executingCheck{hash: hash} + } +  +-func newExecutingCheckFromEntry(entry entrydb.Entry) (executingCheck, error) { +- if entry[0] != typeExecutingCheck { +- return executingCheck{}, fmt.Errorf("%w: attempting to decode executing check but was type %v", ErrDataCorruption, entry[0]) ++func newExecutingCheckFromEntry(data entrydb.Entry) (executingCheck, error) { ++ if data.Type() != entrydb.TypeExecutingCheck { ++ return executingCheck{}, fmt.Errorf("%w: attempting to decode executing check but was type %s", ErrDataCorruption, data.Type()) + } +- var hash types.TruncatedHash +- copy(hash[:], entry[1:21]) +- return newExecutingCheck(hash), nil ++ return newExecutingCheck(common.Hash(data[1:33])), nil + } +  + // encode creates an executing check entry +-// type 4: "executing check" <type><event-hash: 20 bytes> = 21 bytes ++// type 4: "executing check" <type><event-hash: 32 bytes> = 33 bytes + func (e executingCheck) encode() entrydb.Entry { + var entry entrydb.Entry +- entry[0] = typeExecutingCheck +- copy(entry[1:21], e.hash[:]) ++ entry[0] = uint8(entrydb.TypeExecutingCheck) ++ copy(entry[1:33], e.hash[:]) + return entry + } +  +-func newExecutingMessageFromEntries(linkEntry entrydb.Entry, checkEntry entrydb.Entry) (types.ExecutingMessage, error) { +- link, err := newExecutingLinkFromEntry(linkEntry) +- if err != nil { +- return types.ExecutingMessage{}, fmt.Errorf("invalid executing link: %w", err) +- } +- check, err := newExecutingCheckFromEntry(checkEntry) +- if err != nil { +- return types.ExecutingMessage{}, fmt.Errorf("invalid executing check: %w", err) +- } +- return types.ExecutingMessage{ +- Chain: link.chain, +- BlockNum: link.blockNum, +- LogIdx: link.logIdx, +- Timestamp: link.timestamp, +- Hash: check.hash, +- }, nil ++type paddingEntry struct{} ++ ++// encoding of the padding entry ++// type 5: "padding" <type><padding: 33 bytes> = 34 bytes ++func (e paddingEntry) encode() entrydb.Entry { ++ var entry entrydb.Entry ++ entry[0] = uint8(entrydb.TypePadding) ++ return entry + }
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+112
+
-82
+ +
+ +
+
+
diff --git OP/op-supervisor/supervisor/backend/db/logs/iterator.go CELO/op-supervisor/supervisor/backend/db/logs/iterator.go +index 7312966b245546df6381e5df01ccedfef60d6f5f..4b3bd1b65908d1e31f56f8fbf8d57e3ca3e48e7d 100644 +--- OP/op-supervisor/supervisor/backend/db/logs/iterator.go ++++ CELO/op-supervisor/supervisor/backend/db/logs/iterator.go +@@ -5,110 +5,140 @@ "errors" + "fmt" + "io" +  ++ "github.com/ethereum/go-ethereum/common" ++ + "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/db/entrydb" +- "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/types" ++ "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" + ) +  ++type IteratorState interface { ++ NextIndex() entrydb.EntryIdx ++ SealedBlock() (hash common.Hash, num uint64, ok bool) ++ InitMessage() (hash common.Hash, logIndex uint32, ok bool) ++ ExecMessage() *types.ExecutingMessage ++} ++ + type Iterator interface { +- NextLog() (blockNum uint64, logIdx uint32, evtHash types.TruncatedHash, outErr error) +- Index() entrydb.EntryIdx +- ExecMessage() (types.ExecutingMessage, error) ++ End() error ++ NextInitMsg() error ++ NextExecMsg() error ++ NextBlock() error ++ IteratorState + } +  + type iterator struct { +- db *DB +- nextEntryIdx entrydb.EntryIdx ++ db *DB ++ current logContext ++ entriesRead int64 ++} +  +- current logContext +- hasExecMsg bool +- +- entriesRead int64 ++// End traverses the iterator to the end of the DB. ++// It does not return io.EOF or ErrFuture. ++func (i *iterator) End() error { ++ for { ++ _, err := i.next() ++ if errors.Is(err, ErrFuture) { ++ return nil ++ } else if err != nil { ++ return err ++ } ++ } + } +  +-// NextLog returns the next log in the iterator. +-// It scans forward until it finds an initiating event, returning the block number, log index, and event hash. +-func (i *iterator) NextLog() (blockNum uint64, logIdx uint32, evtHash types.TruncatedHash, outErr error) { +- for i.nextEntryIdx <= i.db.lastEntryIdx() { +- entryIdx := i.nextEntryIdx +- entry, err := i.db.store.Read(entryIdx) ++// NextInitMsg returns the next initiating message in the iterator. ++// It scans forward until it finds and fully reads an initiating event, skipping any blocks. ++func (i *iterator) NextInitMsg() error { ++ seenLog := false ++ for { ++ typ, err := i.next() + if err != nil { +- outErr = fmt.Errorf("failed to read entry %v: %w", i, err) +- return ++ return err + } +- i.nextEntryIdx++ +- i.entriesRead++ +- i.hasExecMsg = false +- switch entry[0] { +- case typeSearchCheckpoint: +- current, err := newSearchCheckpointFromEntry(entry) +- if err != nil { +- outErr = fmt.Errorf("failed to parse search checkpoint at idx %v: %w", entryIdx, err) +- return +- } +- i.current.blockNum = current.blockNum +- i.current.logIdx = current.logIdx +- case typeInitiatingEvent: +- evt, err := newInitiatingEventFromEntry(entry) +- if err != nil { +- outErr = fmt.Errorf("failed to parse initiating event at idx %v: %w", entryIdx, err) +- return +- } +- i.current = evt.postContext(i.current) +- blockNum = i.current.blockNum +- logIdx = i.current.logIdx +- evtHash = evt.logHash +- i.hasExecMsg = evt.hasExecMsg +- return +- case typeCanonicalHash: // Skip +- case typeExecutingCheck: // Skip +- case typeExecutingLink: // Skip +- default: +- outErr = fmt.Errorf("unknown entry type at idx %v %v", entryIdx, entry[0]) +- return ++ if typ == entrydb.TypeInitiatingEvent { ++ seenLog = true ++ } ++ if !i.current.hasCompleteBlock() { ++ continue // must know the block we're building on top of ++ } ++ if i.current.hasIncompleteLog() { ++ continue // didn't finish processing the log yet ++ } ++ if seenLog { ++ return nil + } + } +- outErr = io.EOF +- return + } +  +-func (i *iterator) Index() entrydb.EntryIdx { +- return i.nextEntryIdx - 1 ++// NextExecMsg returns the next executing message in the iterator. ++// It scans forward until it finds and fully reads an initiating event, skipping any blocks. ++// This does not stay at the executing message of the current initiating message, if there is any. ++func (i *iterator) NextExecMsg() error { ++ for { ++ err := i.NextInitMsg() ++ if err != nil { ++ return err ++ } ++ if i.current.execMsg != nil { ++ return nil // found a new executing message! ++ } ++ } + } +  +-func (i *iterator) ExecMessage() (types.ExecutingMessage, error) { +- if !i.hasExecMsg { +- return types.ExecutingMessage{}, nil ++// NextBlock returns the next block in the iterator. ++// It scans forward until it finds and fully reads a block, skipping any events. ++func (i *iterator) NextBlock() error { ++ seenBlock := false ++ for { ++ typ, err := i.next() ++ if err != nil { ++ return err ++ } ++ if typ == entrydb.TypeSearchCheckpoint { ++ seenBlock = true ++ } ++ if !i.current.hasCompleteBlock() { ++ continue // need the full block content ++ } ++ if seenBlock { ++ return nil ++ } + } +- // Look ahead to find the exec message info +- logEntryIdx := i.nextEntryIdx - 1 +- execMsg, err := i.readExecMessage(logEntryIdx) ++} ++ ++// Read and apply the next entry. ++func (i *iterator) next() (entrydb.EntryType, error) { ++ index := i.current.nextEntryIndex ++ entry, err := i.db.store.Read(index) + if err != nil { +- return types.ExecutingMessage{}, fmt.Errorf("failed to read exec message for initiating event at %v: %w", logEntryIdx, err) ++ if errors.Is(err, io.EOF) { ++ return 0, ErrFuture ++ } ++ return 0, fmt.Errorf("failed to read entry %d: %w", index, err) + } +- return execMsg, nil ++ if err := i.current.ApplyEntry(entry); err != nil { ++ return entry.Type(), fmt.Errorf("failed to apply entry %d to iterator state: %w", index, err) ++ } ++ ++ i.entriesRead++ ++ return entry.Type(), nil + } +  +-func (i *iterator) readExecMessage(initEntryIdx entrydb.EntryIdx) (types.ExecutingMessage, error) { +- linkIdx := initEntryIdx + 1 +- if linkIdx%searchCheckpointFrequency == 0 { +- linkIdx += 2 // skip the search checkpoint and canonical hash entries +- } +- linkEntry, err := i.db.store.Read(linkIdx) +- if errors.Is(err, io.EOF) { +- return types.ExecutingMessage{}, fmt.Errorf("%w: missing expected executing link event at idx %v", ErrDataCorruption, linkIdx) +- } else if err != nil { +- return types.ExecutingMessage{}, fmt.Errorf("failed to read executing link event at idx %v: %w", linkIdx, err) +- } ++func (i *iterator) NextIndex() entrydb.EntryIdx { ++ return i.current.NextIndex() ++} +  +- checkIdx := linkIdx + 1 +- if checkIdx%searchCheckpointFrequency == 0 { +- checkIdx += 2 // skip the search checkpoint and canonical hash entries +- } +- checkEntry, err := i.db.store.Read(checkIdx) +- if errors.Is(err, io.EOF) { +- return types.ExecutingMessage{}, fmt.Errorf("%w: missing expected executing check event at idx %v", ErrDataCorruption, checkIdx) +- } else if err != nil { +- return types.ExecutingMessage{}, fmt.Errorf("failed to read executing check event at idx %v: %w", checkIdx, err) +- } +- return newExecutingMessageFromEntries(linkEntry, checkEntry) ++// SealedBlock returns the sealed block that we are appending logs after, if any is available. ++// I.e. the block is the parent block of the block containing the logs that are currently appending to it. ++func (i *iterator) SealedBlock() (hash common.Hash, num uint64, ok bool) { ++ return i.current.SealedBlock() ++} ++ ++// InitMessage returns the current initiating message, if any is available. ++func (i *iterator) InitMessage() (hash common.Hash, logIndex uint32, ok bool) { ++ return i.current.InitMessage() ++} ++ ++// ExecMessage returns the current executing message, if any is available. ++func (i *iterator) ExecMessage() *types.ExecutingMessage { ++ return i.current.ExecMessage() + }
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+407
+
-0
+ +
+ +
+
+
diff --git OP/op-supervisor/supervisor/backend/db/logs/state.go CELO/op-supervisor/supervisor/backend/db/logs/state.go +new file mode 100644 +index 0000000000000000000000000000000000000000..bb00762acc2e4e08f9824d0dd68ba0ac4d33b5f8 +--- /dev/null ++++ CELO/op-supervisor/supervisor/backend/db/logs/state.go +@@ -0,0 +1,407 @@ ++package logs ++ ++import ( ++ "errors" ++ "fmt" ++ "io" ++ ++ "github.com/ethereum/go-ethereum/common" ++ ++ "github.com/ethereum-optimism/optimism/op-service/eth" ++ "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/db/entrydb" ++ "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" ++) ++ ++// logContext is a buffer on top of the DB, ++// where blocks and logs can be applied to. ++// ++// Rules: ++// ++// if entry_index % 256 == 0: must be type 0. For easy binary search. ++// else if end_of_block: also type 0. ++// else: ++// after type 0: type 1 ++// after type 1: type 2 iff any event and space, otherwise type 0 ++// after type 2: type 3 iff executing, otherwise type 2 or 0 ++// after type 3: type 4 ++// after type 4: type 2 iff any event and space, otherwise type 0 ++// after type 5: any ++// ++// Type 0 can repeat: seal the block, then start a search checkpoint, then a single canonical hash. ++// Type 0 may also be used as padding: type 2 only starts when it will not be interrupted by a search checkpoint. ++// ++// Types (<type> = 1 byte): ++// type 0: "checkpoint" <type><uint64 block number: 8 bytes><uint32 logsSince count: 4 bytes><uint64 timestamp: 8 bytes> = 21 bytes ++// type 1: "canonical hash" <type><parent blockhash: 32 bytes> = 33 bytes ++// type 2: "initiating event" <type><event flags: 1 byte><event-hash: 32 bytes> = 34 bytes ++// type 3: "executing link" <type><chain: 4 bytes><blocknum: 8 bytes><event index: 3 bytes><uint64 timestamp: 8 bytes> = 24 bytes ++// type 4: "executing check" <type><event-hash: 32 bytes> = 33 bytes ++// type 5: "padding" <type><padding: 33 bytes> = 34 bytes ++// other types: future compat. E.g. for linking to L1, registering block-headers as a kind of initiating-event, tracking safe-head progression, etc. ++// ++// Right-pad each entry that is not 34 bytes. ++// ++// We insert a checkpoint for every search interval and block sealing event, ++// and these may overlap as the same thing. ++// Such seal has logsSince == 0, i.e. wrapping up the last block and starting a fresh list of logs. ++// ++// event-flags: each bit represents a boolean value, currently only two are defined ++// * event-flags & 0x01 - true if the initiating event has an executing link that should follow. Allows detecting when the executing link failed to write. ++// event-hash: H(origin, timestamp, payloadhash); enough to check identifier matches & payload matches. ++type logContext struct { ++ // next entry index, including the contents of `out` ++ nextEntryIndex entrydb.EntryIdx ++ ++ // blockHash of the last sealed block. ++ // A block is not considered sealed until we know its block hash. ++ // While we process logs we keep the parent-block of said logs around as sealed block. ++ blockHash common.Hash ++ // blockNum of the last sealed block ++ blockNum uint64 ++ // timestamp of the last sealed block ++ timestamp uint64 ++ ++ // number of logs since the last sealed block ++ logsSince uint32 ++ ++ // payload-hash of the log-event that was last processed. (may not be fully processed, see doneLog) ++ logHash common.Hash ++ ++ // executing message that might exist for the current log event. ++ // Might be incomplete; if !logDone while we already processed the initiating event, ++ // then we know an executing message is still coming. ++ execMsg *types.ExecutingMessage ++ ++ need entrydb.EntryTypeFlag ++ ++ // buffer of entries not yet in the DB. ++ // This is generated as objects are applied. ++ // E.g. you can build multiple hypothetical blocks with log events on top of the state, ++ // before flushing the entries to a DB. ++ // However, no entries can be read from the DB while objects are being applied. ++ out []entrydb.Entry ++} ++ ++type EntryObj interface { ++ encode() entrydb.Entry ++} ++ ++func (l *logContext) NextIndex() entrydb.EntryIdx { ++ return l.nextEntryIndex ++} ++ ++// SealedBlock returns the block that we are building on top of, and if it is sealed. ++func (l *logContext) SealedBlock() (hash common.Hash, num uint64, ok bool) { ++ if !l.hasCompleteBlock() { ++ return common.Hash{}, 0, false ++ } ++ return l.blockHash, l.blockNum, true ++} ++ ++func (l *logContext) hasCompleteBlock() bool { ++ return !l.need.Any(entrydb.FlagCanonicalHash) ++} ++ ++func (l *logContext) hasIncompleteLog() bool { ++ return l.need.Any(entrydb.FlagInitiatingEvent | entrydb.FlagExecutingLink | entrydb.FlagExecutingCheck) ++} ++ ++func (l *logContext) hasReadableLog() bool { ++ return l.logsSince > 0 && !l.hasIncompleteLog() ++} ++ ++// InitMessage returns the current initiating message, if any is available. ++func (l *logContext) InitMessage() (hash common.Hash, logIndex uint32, ok bool) { ++ if !l.hasReadableLog() { ++ return common.Hash{}, 0, false ++ } ++ return l.logHash, l.logsSince - 1, true ++} ++ ++// ExecMessage returns the current executing message, if any is available. ++func (l *logContext) ExecMessage() *types.ExecutingMessage { ++ if l.hasCompleteBlock() && l.hasReadableLog() && l.execMsg != nil { ++ return l.execMsg ++ } ++ return nil ++} ++ ++// ApplyEntry applies an entry on top of the current state. ++func (l *logContext) ApplyEntry(entry entrydb.Entry) error { ++ // Wrap processEntry to add common useful error message info ++ err := l.processEntry(entry) ++ if err != nil { ++ return fmt.Errorf("failed to process type %s entry at idx %d (%x): %w", entry.Type().String(), l.nextEntryIndex, entry[:], err) ++ } ++ return nil ++} ++ ++// processEntry decodes and applies an entry to the state. ++// Entries may not be applied if we are in the process of generating entries from objects. ++// These outputs need to be flushed before inputs can be accepted. ++func (l *logContext) processEntry(entry entrydb.Entry) error { ++ if len(l.out) != 0 { ++ panic("can only apply without appending if the state is still empty") ++ } ++ switch entry.Type() { ++ case entrydb.TypeSearchCheckpoint: ++ current, err := newSearchCheckpointFromEntry(entry) ++ if err != nil { ++ return err ++ } ++ l.blockNum = current.blockNum ++ l.blockHash = common.Hash{} ++ l.logsSince = current.logsSince // TODO this is bumping the logsSince? ++ l.timestamp = current.timestamp ++ l.need.Add(entrydb.FlagCanonicalHash) ++ // Log data after the block we are sealing remains to be seen ++ if l.logsSince == 0 { ++ l.logHash = common.Hash{} ++ l.execMsg = nil ++ } ++ case entrydb.TypeCanonicalHash: ++ if !l.need.Any(entrydb.FlagCanonicalHash) { ++ return errors.New("not ready for canonical hash entry, already sealed the last block") ++ } ++ canonHash, err := newCanonicalHashFromEntry(entry) ++ if err != nil { ++ return err ++ } ++ l.blockHash = canonHash.hash ++ l.need.Remove(entrydb.FlagCanonicalHash) ++ case entrydb.TypeInitiatingEvent: ++ if !l.hasCompleteBlock() { ++ return errors.New("did not complete block seal, cannot add log") ++ } ++ if l.hasIncompleteLog() { ++ return errors.New("cannot process log before last log completes") ++ } ++ evt, err := newInitiatingEventFromEntry(entry) ++ if err != nil { ++ return err ++ } ++ l.execMsg = nil // clear the old state ++ l.logHash = evt.logHash ++ if evt.hasExecMsg { ++ l.need.Add(entrydb.FlagExecutingLink | entrydb.FlagExecutingCheck) ++ } else { ++ l.logsSince += 1 ++ } ++ l.need.Remove(entrydb.FlagInitiatingEvent) ++ case entrydb.TypeExecutingLink: ++ if !l.need.Any(entrydb.FlagExecutingLink) { ++ return errors.New("unexpected executing-link") ++ } ++ link, err := newExecutingLinkFromEntry(entry) ++ if err != nil { ++ return err ++ } ++ l.execMsg = &types.ExecutingMessage{ ++ Chain: link.chain, ++ BlockNum: link.blockNum, ++ LogIdx: link.logIdx, ++ Timestamp: link.timestamp, ++ Hash: common.Hash{}, // not known yet ++ } ++ l.need.Remove(entrydb.FlagExecutingLink) ++ l.need.Add(entrydb.FlagExecutingCheck) ++ case entrydb.TypeExecutingCheck: ++ if l.need.Any(entrydb.FlagExecutingLink) { ++ return errors.New("need executing link to be applied before the check part") ++ } ++ if !l.need.Any(entrydb.FlagExecutingCheck) { ++ return errors.New("unexpected executing check") ++ } ++ link, err := newExecutingCheckFromEntry(entry) ++ if err != nil { ++ return err ++ } ++ l.execMsg.Hash = link.hash ++ l.need.Remove(entrydb.FlagExecutingCheck) ++ l.logsSince += 1 ++ case entrydb.TypePadding: ++ if l.need.Any(entrydb.FlagPadding) { ++ l.need.Remove(entrydb.FlagPadding) ++ } else { ++ l.need.Remove(entrydb.FlagPadding2) ++ } ++ default: ++ return fmt.Errorf("unknown entry type: %s", entry.Type()) ++ } ++ l.nextEntryIndex += 1 ++ return nil ++} ++ ++// appendEntry add the entry to the output-buffer, ++// and registers it as last processed entry type, and increments the next entry-index. ++func (l *logContext) appendEntry(obj EntryObj) { ++ entry := obj.encode() ++ l.out = append(l.out, entry) ++ l.nextEntryIndex += 1 ++} ++ ++// infer advances the logContext in cases where multiple entries are to be appended implicitly ++// depending on the last type of entry, a new entry is appended, ++// or when the searchCheckpoint should be inserted. ++// This can be done repeatedly until there is no more implied data to extend. ++func (l *logContext) infer() error { ++ // We force-insert a checkpoint whenever we hit the known fixed interval. ++ if l.nextEntryIndex%searchCheckpointFrequency == 0 { ++ l.need.Add(entrydb.FlagSearchCheckpoint) ++ } ++ if l.need.Any(entrydb.FlagSearchCheckpoint) { ++ l.appendEntry(newSearchCheckpoint(l.blockNum, l.logsSince, l.timestamp)) ++ l.need.Add(entrydb.FlagCanonicalHash) // always follow with a canonical hash ++ l.need.Remove(entrydb.FlagSearchCheckpoint) ++ return nil ++ } ++ if l.need.Any(entrydb.FlagCanonicalHash) { ++ l.appendEntry(newCanonicalHash(l.blockHash)) ++ l.need.Remove(entrydb.FlagCanonicalHash) ++ return nil ++ } ++ if l.need.Any(entrydb.FlagPadding) { ++ l.appendEntry(paddingEntry{}) ++ l.need.Remove(entrydb.FlagPadding) ++ return nil ++ } ++ if l.need.Any(entrydb.FlagPadding2) { ++ l.appendEntry(paddingEntry{}) ++ l.need.Remove(entrydb.FlagPadding2) ++ return nil ++ } ++ if l.need.Any(entrydb.FlagInitiatingEvent) { ++ // If we are running out of space for log-event data, ++ // write some checkpoints as padding, to pass the checkpoint. ++ if l.execMsg != nil { // takes 3 total. Need to avoid the checkpoint. ++ switch l.nextEntryIndex % searchCheckpointFrequency { ++ case searchCheckpointFrequency - 1: ++ l.need.Add(entrydb.FlagPadding) ++ return nil ++ case searchCheckpointFrequency - 2: ++ l.need.Add(entrydb.FlagPadding | entrydb.FlagPadding2) ++ return nil ++ } ++ } ++ evt := newInitiatingEvent(l.logHash, l.execMsg != nil) ++ l.appendEntry(evt) ++ l.need.Remove(entrydb.FlagInitiatingEvent) ++ if l.execMsg == nil { ++ l.logsSince += 1 ++ } ++ return nil ++ } ++ if l.need.Any(entrydb.FlagExecutingLink) { ++ link, err := newExecutingLink(*l.execMsg) ++ if err != nil { ++ return fmt.Errorf("failed to create executing link: %w", err) ++ } ++ l.appendEntry(link) ++ l.need.Remove(entrydb.FlagExecutingLink) ++ return nil ++ } ++ if l.need.Any(entrydb.FlagExecutingCheck) { ++ l.appendEntry(newExecutingCheck(l.execMsg.Hash)) ++ l.need.Remove(entrydb.FlagExecutingCheck) ++ l.logsSince += 1 ++ return nil ++ } ++ return io.EOF ++} ++ ++// inferFull advances the queued entries held by the log context repeatedly ++// until no more implied entries can be added ++func (l *logContext) inferFull() error { ++ for i := 0; i < 10; i++ { ++ err := l.infer() ++ if err == nil { ++ continue ++ } ++ if err == io.EOF { // wrapped io.EOF does not count. ++ return nil ++ } else { ++ return err ++ } ++ } ++ panic("hit sanity limit") ++} ++ ++// forceBlock force-overwrites the state, to match the given sealed block as starting point (excl) ++func (l *logContext) forceBlock(upd eth.BlockID, timestamp uint64) error { ++ if l.nextEntryIndex != 0 { ++ return errors.New("can only bootstrap on top of an empty state") ++ } ++ l.blockHash = upd.Hash ++ l.blockNum = upd.Number ++ l.timestamp = timestamp ++ l.logsSince = 0 ++ l.execMsg = nil ++ l.logHash = common.Hash{} ++ l.need = 0 ++ l.out = nil ++ return l.inferFull() // apply to the state as much as possible ++} ++ ++// SealBlock applies a block header on top of the current state. ++// This seals the state; no further logs of this block may be added with ApplyLog. ++func (l *logContext) SealBlock(parent common.Hash, upd eth.BlockID, timestamp uint64) error { ++ // If we don't have any entries yet, allow any block to start things off ++ if l.nextEntryIndex != 0 { ++ if err := l.inferFull(); err != nil { // ensure we can start applying ++ return err ++ } ++ if l.blockHash != parent { ++ return fmt.Errorf("%w: cannot apply block %s (parent %s) on top of %s", ErrConflict, upd, parent, l.blockHash) ++ } ++ if l.blockHash != (common.Hash{}) && l.blockNum+1 != upd.Number { ++ return fmt.Errorf("%w: cannot apply block %d on top of %d", ErrConflict, upd.Number, l.blockNum) ++ } ++ if l.timestamp > timestamp { ++ return fmt.Errorf("%w: block timestamp %d must be equal or larger than current timestamp %d", ErrConflict, timestamp, l.timestamp) ++ } ++ } ++ l.blockHash = upd.Hash ++ l.blockNum = upd.Number ++ l.timestamp = timestamp ++ l.logsSince = 0 ++ l.execMsg = nil ++ l.logHash = common.Hash{} ++ l.need.Add(entrydb.FlagSearchCheckpoint) ++ return l.inferFull() // apply to the state as much as possible ++} ++ ++// ApplyLog applies a log on top of the current state. ++// The parent-block that the log comes after must be applied with ApplyBlock first. ++func (l *logContext) ApplyLog(parentBlock eth.BlockID, logIdx uint32, logHash common.Hash, execMsg *types.ExecutingMessage) error { ++ if parentBlock == (eth.BlockID{}) { ++ return fmt.Errorf("genesis does not have logs: %w", ErrLogOutOfOrder) ++ } ++ if err := l.inferFull(); err != nil { // ensure we can start applying ++ return err ++ } ++ if !l.hasCompleteBlock() { ++ if l.blockNum == 0 { ++ return fmt.Errorf("%w: should not have logs in block 0", ErrLogOutOfOrder) ++ } else { ++ return errors.New("cannot append log before last known block is sealed") ++ } ++ } ++ // check parent block ++ if l.blockHash != parentBlock.Hash { ++ return fmt.Errorf("%w: log builds on top of block %s, but have block %s", ErrLogOutOfOrder, parentBlock, l.blockHash) ++ } ++ if l.blockNum != parentBlock.Number { ++ return fmt.Errorf("%w: log builds on top of block %d, but have block %d", ErrLogOutOfOrder, parentBlock.Number, l.blockNum) ++ } ++ // check if log fits on top. The length so far == the index of the next log. ++ if logIdx != l.logsSince { ++ return fmt.Errorf("%w: expected event index %d, cannot append %d", ErrLogOutOfOrder, l.logsSince, logIdx) ++ } ++ l.logHash = logHash ++ l.execMsg = execMsg ++ l.need.Add(entrydb.FlagInitiatingEvent) ++ if execMsg != nil { ++ l.need.Add(entrydb.FlagExecutingLink | entrydb.FlagExecutingCheck) ++ } ++ return l.inferFull() // apply to the state as much as possible ++}
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+18
+
-8
+ +
+ +
+
+
diff --git OP/op-supervisor/supervisor/backend/db/safety_checkers.go CELO/op-supervisor/supervisor/backend/db/safety_checkers.go +index 3c92c1e808dfe3d7f7dfcbf2ff8fd71b97d6e18f..916f26f6dead3cf3556f5db5a5cb442835adb33a 100644 +--- OP/op-supervisor/supervisor/backend/db/safety_checkers.go ++++ CELO/op-supervisor/supervisor/backend/db/safety_checkers.go +@@ -1,9 +1,13 @@ + package db +  + import ( ++ "errors" ++ ++ "github.com/ethereum/go-ethereum/common" ++ + "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/db/entrydb" + "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/db/heads" +- backendTypes "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/types" ++ "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/db/logs" + "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" + ) +  +@@ -18,7 +22,7 @@ // and updating the local head for a chain. + type SafetyChecker interface { + LocalHeadForChain(chainID types.ChainID) entrydb.EntryIdx + CrossHeadForChain(chainID types.ChainID) entrydb.EntryIdx +- Check(chain types.ChainID, blockNum uint64, logIdx uint32, logHash backendTypes.TruncatedHash) bool ++ Check(chain types.ChainID, blockNum uint64, logIdx uint32, logHash common.Hash) bool + Update(chain types.ChainID, index entrydb.EntryIdx) heads.OperationFn + Name() string + SafetyLevel() types.SafetyLevel +@@ -126,28 +130,34 @@ localHead entrydb.EntryIdx, + chain types.ChainID, + blockNum uint64, + logIdx uint32, +- logHash backendTypes.TruncatedHash) bool { ++ logHash common.Hash) bool { +  + // for the Check to be valid, the log must: + // exist at the blockNum and logIdx + // have a hash that matches the provided hash (implicit in the Contains call), and + // be less than or equal to the local head for the chain +- exists, index, err := chainsDB.logDBs[chain].Contains(blockNum, logIdx, logHash) ++ index, err := chainsDB.logDBs[chain].Contains(blockNum, logIdx, logHash) + if err != nil { ++ if errors.Is(err, logs.ErrFuture) { ++ return false // TODO(#12031) ++ } ++ if errors.Is(err, logs.ErrConflict) { ++ return false // TODO(#12031) ++ } + return false + } +- return exists && index <= localHead ++ return index <= localHead + } +  + // Check checks if the log entry is safe, provided a local head for the chain + // it passes on the local head this checker is concerned with, along with its view of the database +-func (c *unsafeChecker) Check(chain types.ChainID, blockNum uint64, logIdx uint32, logHash backendTypes.TruncatedHash) bool { ++func (c *unsafeChecker) Check(chain types.ChainID, blockNum uint64, logIdx uint32, logHash common.Hash) bool { + return check(c.chainsDB, c.LocalHeadForChain(chain), chain, blockNum, logIdx, logHash) + } +-func (c *safeChecker) Check(chain types.ChainID, blockNum uint64, logIdx uint32, logHash backendTypes.TruncatedHash) bool { ++func (c *safeChecker) Check(chain types.ChainID, blockNum uint64, logIdx uint32, logHash common.Hash) bool { + return check(c.chainsDB, c.LocalHeadForChain(chain), chain, blockNum, logIdx, logHash) + } +-func (c *finalizedChecker) Check(chain types.ChainID, blockNum uint64, logIdx uint32, logHash backendTypes.TruncatedHash) bool { ++func (c *finalizedChecker) Check(chain types.ChainID, blockNum uint64, logIdx uint32, logHash common.Hash) bool { + return check(c.chainsDB, c.LocalHeadForChain(chain), chain, blockNum, logIdx, logHash) + } +
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+27
+
-22
+ +
+ +
+
+
diff --git OP/op-supervisor/supervisor/backend/db/safety_checkers_test.go CELO/op-supervisor/supervisor/backend/db/safety_checkers_test.go +index d2303d7ec3e57544cc222c1967733674175a8502..c8fb4e34a757a33b6d301b69013cba30aa5bec70 100644 +--- OP/op-supervisor/supervisor/backend/db/safety_checkers_test.go ++++ CELO/op-supervisor/supervisor/backend/db/safety_checkers_test.go +@@ -1,14 +1,19 @@ + package db +  + import ( +- "fmt" ++ "errors" + "testing" +  ++ "github.com/stretchr/testify/require" ++ ++ "github.com/ethereum/go-ethereum/common" ++ "github.com/ethereum/go-ethereum/log" ++ ++ "github.com/ethereum-optimism/optimism/op-service/testlog" + "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/db/entrydb" + "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/db/heads" +- backendTypes "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/types" ++ "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/db/logs" + "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" +- "github.com/stretchr/testify/require" + ) +  + // TestHeadsForChain tests the heads for a chain, +@@ -25,7 +30,7 @@ LocalFinalized: entrydb.EntryIdx(5), + CrossFinalized: entrydb.EntryIdx(6), + } + h.Put(types.ChainIDFromUInt64(1), chainHeads) +- chainsDB := NewChainsDB(nil, &stubHeadStorage{h}) ++ chainsDB := NewChainsDB(nil, &stubHeadStorage{h}, testlog.Logger(t, log.LevelDebug)) + tcases := []struct { + name string + chainID types.ChainID +@@ -92,7 +97,7 @@ logsStore := map[types.ChainID]LogStorage{ + types.ChainIDFromUInt64(1): logDB, + } +  +- chainsDB := NewChainsDB(logsStore, &stubHeadStorage{h}) ++ chainsDB := NewChainsDB(logsStore, &stubHeadStorage{h}, testlog.Logger(t, log.LevelDebug)) +  + tcases := []struct { + name string +@@ -100,7 +105,7 @@ checkerType types.SafetyLevel + chainID types.ChainID + blockNum uint64 + logIdx uint32 +- loghash backendTypes.TruncatedHash ++ loghash common.Hash + containsResponse containsResponse + expected bool + }{ +@@ -112,8 +117,8 @@ Unsafe, + types.ChainIDFromUInt64(1), + 1, + 1, +- backendTypes.TruncatedHash{1, 2, 3}, +- containsResponse{true, entrydb.EntryIdx(6), nil}, ++ common.Hash{1, 2, 3}, ++ containsResponse{entrydb.EntryIdx(6), nil}, + true, + }, + { +@@ -123,8 +128,8 @@ Safe, + types.ChainIDFromUInt64(1), + 1, + 1, +- backendTypes.TruncatedHash{1, 2, 3}, +- containsResponse{true, entrydb.EntryIdx(3), nil}, ++ common.Hash{1, 2, 3}, ++ containsResponse{entrydb.EntryIdx(3), nil}, + true, + }, + { +@@ -134,8 +139,8 @@ Finalized, + types.ChainIDFromUInt64(1), + 1, + 1, +- backendTypes.TruncatedHash{1, 2, 3}, +- containsResponse{true, entrydb.EntryIdx(1), nil}, ++ common.Hash{1, 2, 3}, ++ containsResponse{entrydb.EntryIdx(1), nil}, + true, + }, + { +@@ -145,8 +150,8 @@ Safe, + types.ChainIDFromUInt64(1), + 1, + 1, +- backendTypes.TruncatedHash{1, 2, 3}, +- containsResponse{false, entrydb.EntryIdx(1), nil}, ++ common.Hash{1, 2, 3}, ++ containsResponse{entrydb.EntryIdx(1), logs.ErrConflict}, + false, + }, + { +@@ -156,8 +161,8 @@ Unsafe, + types.ChainIDFromUInt64(1), + 1, + 1, +- backendTypes.TruncatedHash{1, 2, 3}, +- containsResponse{true, entrydb.EntryIdx(100), nil}, ++ common.Hash{1, 2, 3}, ++ containsResponse{entrydb.EntryIdx(100), nil}, + false, + }, + { +@@ -167,8 +172,8 @@ Safe, + types.ChainIDFromUInt64(1), + 1, + 1, +- backendTypes.TruncatedHash{1, 2, 3}, +- containsResponse{true, entrydb.EntryIdx(5), nil}, ++ common.Hash{1, 2, 3}, ++ containsResponse{entrydb.EntryIdx(5), nil}, + false, + }, + { +@@ -178,8 +183,8 @@ Finalized, + types.ChainIDFromUInt64(1), + 1, + 1, +- backendTypes.TruncatedHash{1, 2, 3}, +- containsResponse{true, entrydb.EntryIdx(3), nil}, ++ common.Hash{1, 2, 3}, ++ containsResponse{entrydb.EntryIdx(3), nil}, + false, + }, + { +@@ -189,8 +194,8 @@ Safe, + types.ChainIDFromUInt64(1), + 1, + 1, +- backendTypes.TruncatedHash{1, 2, 3}, +- containsResponse{false, entrydb.EntryIdx(0), fmt.Errorf("error")}, ++ common.Hash{1, 2, 3}, ++ containsResponse{entrydb.EntryIdx(0), errors.New("error")}, + false, + }, + }
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+4
+
-0
+ +
+ +
+
+
diff --git OP/op-supervisor/supervisor/backend/mock.go CELO/op-supervisor/supervisor/backend/mock.go +index 71c77b23552572e594d874c569f303bf4ae65f80..e62c7b950b7c89e2b7b37cfe337187970841307e 100644 +--- OP/op-supervisor/supervisor/backend/mock.go ++++ CELO/op-supervisor/supervisor/backend/mock.go +@@ -39,6 +39,10 @@ } + return nil + } +  ++func (m *MockBackend) AddL2RPC(ctx context.Context, rpc string) error { ++ return nil ++} ++ + func (m *MockBackend) CheckMessage(identifier types.Identifier, payloadHash common.Hash) (types.SafetyLevel, error) { + return types.CrossUnsafe, nil + }
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+7
+
-2
+ +
+ +
+
+
diff --git OP/op-supervisor/supervisor/backend/source/chain.go CELO/op-supervisor/supervisor/backend/source/chain.go +index f7fd31b202dc95f1c99df505b2da61230fd26f31..c8fef89f8b832e2ce9edbc27fb3a984a4bc2fbde 100644 +--- OP/op-supervisor/supervisor/backend/source/chain.go ++++ CELO/op-supervisor/supervisor/backend/source/chain.go +@@ -26,7 +26,7 @@ + type Storage interface { + LogStorage + DatabaseRewinder +- LatestBlockNum(chainID types.ChainID) uint64 ++ LatestBlockNum(chainID types.ChainID) (num uint64, ok bool) + } +  + // ChainMonitor monitors a source L2 chain, retrieving the data required to populate the database and perform +@@ -43,8 +43,13 @@ if err != nil { + return nil, err + } +  ++ latest, ok := store.LatestBlockNum(chainID) ++ if !ok { ++ logger.Warn("") ++ } ++ + startingHead := eth.L1BlockRef{ +- Number: store.LatestBlockNum(chainID), ++ Number: latest, + } +  + processLogs := newLogProcessor(chainID, store)
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+3
+
-0
+ +
+ +
+
+
diff --git OP/op-supervisor/supervisor/backend/source/chain_processor.go CELO/op-supervisor/supervisor/backend/source/chain_processor.go +index b2f60af904bf4992528bb8bdab5a74c6e64cb225..0a42da1556a06fa4f326f8b294d979e60efe1122 100644 +--- OP/op-supervisor/supervisor/backend/source/chain_processor.go ++++ CELO/op-supervisor/supervisor/backend/source/chain_processor.go +@@ -49,10 +49,13 @@ } + } +  + func (s *ChainProcessor) OnNewHead(ctx context.Context, head eth.L1BlockRef) { ++ s.log.Debug("Processing chain", "chain", s.chain, "head", head, "last", s.lastBlock) + if head.Number <= s.lastBlock.Number { ++ s.log.Info("head is not newer than last processed block", "head", head, "lastBlock", s.lastBlock) + return + } + for s.lastBlock.Number+1 < head.Number { ++ s.log.Debug("Filling in skipped block", "chain", s.chain, "lastBlock", s.lastBlock, "head", head) + blockNum := s.lastBlock.Number + 1 + nextBlock, err := s.client.L1BlockRefByNumber(ctx, blockNum) + if err != nil {
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+10
+
-11
+ +
+ +
+
+
diff --git OP/op-supervisor/supervisor/backend/source/contracts/l2inbox.go CELO/op-supervisor/supervisor/backend/source/contracts/l2inbox.go +index b490b612e6c68b9de5655cd381737b1396941773..741c6ae3d8659b995abb1ac2096a7eeeb81c327c 100644 +--- OP/op-supervisor/supervisor/backend/source/contracts/l2inbox.go ++++ CELO/op-supervisor/supervisor/backend/source/contracts/l2inbox.go +@@ -10,7 +10,6 @@ + "github.com/ethereum-optimism/optimism/op-service/predeploys" + "github.com/ethereum-optimism/optimism/op-service/solabi" + "github.com/ethereum-optimism/optimism/op-service/sources/batching" +- backendTypes "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/types" + "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" + "github.com/ethereum-optimism/optimism/packages/contracts-bedrock/snapshots" + "github.com/ethereum/go-ethereum/common" +@@ -48,20 +47,20 @@ contract: batching.NewBoundContract(abi, predeploys.CrossL2InboxAddr), + } + } +  +-func (i *CrossL2Inbox) DecodeExecutingMessageLog(l *ethTypes.Log) (backendTypes.ExecutingMessage, error) { ++func (i *CrossL2Inbox) DecodeExecutingMessageLog(l *ethTypes.Log) (types.ExecutingMessage, error) { + if l.Address != i.contract.Addr() { +- return backendTypes.ExecutingMessage{}, fmt.Errorf("%w: log not from CrossL2Inbox", ErrEventNotFound) ++ return types.ExecutingMessage{}, fmt.Errorf("%w: log not from CrossL2Inbox", ErrEventNotFound) + } + // use DecodeEvent to check the name of the event + // but the actual decoding is done manually to extract the contract identifier + name, _, err := i.contract.DecodeEvent(l) + if errors.Is(err, batching.ErrUnknownEvent) { +- return backendTypes.ExecutingMessage{}, fmt.Errorf("%w: %v", ErrEventNotFound, err.Error()) ++ return types.ExecutingMessage{}, fmt.Errorf("%w: %v", ErrEventNotFound, err.Error()) + } else if err != nil { +- return backendTypes.ExecutingMessage{}, fmt.Errorf("failed to decode event: %w", err) ++ return types.ExecutingMessage{}, fmt.Errorf("failed to decode event: %w", err) + } + if name != eventExecutingMessage { +- return backendTypes.ExecutingMessage{}, fmt.Errorf("%w: event %v not an ExecutingMessage event", ErrEventNotFound, name) ++ return types.ExecutingMessage{}, fmt.Errorf("%w: event %v not an ExecutingMessage event", ErrEventNotFound, name) + } + // the second topic is the hash of the payload (the first is the event ID) + msgHash := l.Topics[1] +@@ -69,14 +68,14 @@ // the first 32 bytes of the data are the msgHash, so we skip them + identifierBytes := bytes.NewReader(l.Data[32:]) + identifier, err := identifierFromBytes(identifierBytes) + if err != nil { +- return backendTypes.ExecutingMessage{}, fmt.Errorf("failed to read contract identifier: %w", err) ++ return types.ExecutingMessage{}, fmt.Errorf("failed to read contract identifier: %w", err) + } + chainID, err := types.ChainIDFromBig(identifier.ChainId).ToUInt32() + if err != nil { +- return backendTypes.ExecutingMessage{}, fmt.Errorf("failed to convert chain ID %v to uint32: %w", identifier.ChainId, err) ++ return types.ExecutingMessage{}, fmt.Errorf("failed to convert chain ID %v to uint32: %w", identifier.ChainId, err) + } + hash := payloadHashToLogHash(msgHash, identifier.Origin) +- return backendTypes.ExecutingMessage{ ++ return types.ExecutingMessage{ + Chain: chainID, + Hash: hash, + BlockNum: identifier.BlockNumber.Uint64(), +@@ -126,9 +125,9 @@ // The logHash can then be used to traverse from the executing message + // to the log the referenced initiating message. + // TODO: this function is duplicated between contracts and backend/source/log_processor.go + // to avoid a circular dependency. It should be reorganized to avoid this duplication. +-func payloadHashToLogHash(payloadHash common.Hash, addr common.Address) backendTypes.TruncatedHash { ++func payloadHashToLogHash(payloadHash common.Hash, addr common.Address) common.Hash { + msg := make([]byte, 0, 2*common.HashLength) + msg = append(msg, addr.Bytes()...) + msg = append(msg, payloadHash.Bytes()...) +- return backendTypes.TruncateHash(crypto.Keccak256Hash(msg)) ++ return crypto.Keccak256Hash(msg) + }
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+2
+
-2
+ +
+ +
+
+
diff --git OP/op-supervisor/supervisor/backend/source/contracts/l2inbox_test.go CELO/op-supervisor/supervisor/backend/source/contracts/l2inbox_test.go +index b343519a48fc9954202e4c13abea2a084ee10a43..302b188e5cdf7a3ee46f7272b253d84173440ed1 100644 +--- OP/op-supervisor/supervisor/backend/source/contracts/l2inbox_test.go ++++ CELO/op-supervisor/supervisor/backend/source/contracts/l2inbox_test.go +@@ -7,7 +7,7 @@ "testing" +  + "github.com/ethereum-optimism/optimism/op-service/predeploys" + "github.com/ethereum-optimism/optimism/op-service/sources/batching" +- backendTypes "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/types" ++ "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" + "github.com/ethereum-optimism/optimism/packages/contracts-bedrock/snapshots" + "github.com/ethereum/go-ethereum/common" + ethTypes "github.com/ethereum/go-ethereum/core/types" +@@ -19,7 +19,7 @@ func TestDecodeExecutingMessageEvent(t *testing.T) { + inbox := NewCrossL2Inbox() + payload := bytes.Repeat([]byte{0xaa, 0xbb}, 50) + payloadHash := crypto.Keccak256Hash(payload) +- expected := backendTypes.ExecutingMessage{ ++ expected := types.ExecutingMessage{ + Chain: 42424, + BlockNum: 12345, + LogIdx: 98,
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+17
+
-14
+ +
+ +
+
+
diff --git OP/op-supervisor/supervisor/backend/source/log_processor.go CELO/op-supervisor/supervisor/backend/source/log_processor.go +index 3fd96476d41f47a0c82b2e87c5d982cafe6d997b..1c20f8c4530a1c969829a3a70ea7afca53a93815 100644 +--- OP/op-supervisor/supervisor/backend/source/log_processor.go ++++ CELO/op-supervisor/supervisor/backend/source/log_processor.go +@@ -5,30 +5,31 @@ "context" + "errors" + "fmt" +  +- "github.com/ethereum-optimism/optimism/op-service/eth" +- "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/source/contracts" +- backendTypes "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/types" +- supTypes "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" + "github.com/ethereum/go-ethereum/common" + ethTypes "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" ++ ++ "github.com/ethereum-optimism/optimism/op-service/eth" ++ "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/source/contracts" ++ "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" + ) +  + type LogStorage interface { +- AddLog(chain supTypes.ChainID, logHash backendTypes.TruncatedHash, block eth.BlockID, timestamp uint64, logIdx uint32, execMsg *backendTypes.ExecutingMessage) error ++ SealBlock(chain types.ChainID, parentHash common.Hash, block eth.BlockID, timestamp uint64) error ++ AddLog(chain types.ChainID, logHash common.Hash, parentBlock eth.BlockID, logIdx uint32, execMsg *types.ExecutingMessage) error + } +  + type EventDecoder interface { +- DecodeExecutingMessageLog(log *ethTypes.Log) (backendTypes.ExecutingMessage, error) ++ DecodeExecutingMessageLog(log *ethTypes.Log) (types.ExecutingMessage, error) + } +  + type logProcessor struct { +- chain supTypes.ChainID ++ chain types.ChainID + logStore LogStorage + eventDecoder EventDecoder + } +  +-func newLogProcessor(chain supTypes.ChainID, logStore LogStorage) *logProcessor { ++func newLogProcessor(chain types.ChainID, logStore LogStorage) *logProcessor { + return &logProcessor{ + chain: chain, + logStore: logStore, +@@ -43,7 +44,7 @@ for _, rcpt := range rcpts { + for _, l := range rcpt.Logs { + // log hash represents the hash of *this* log as a potentially initiating message + logHash := logToLogHash(l) +- var execMsg *backendTypes.ExecutingMessage ++ var execMsg *types.ExecutingMessage + msg, err := p.eventDecoder.DecodeExecutingMessageLog(l) + if err != nil && !errors.Is(err, contracts.ErrEventNotFound) { + return fmt.Errorf("failed to decode executing message log: %w", err) +@@ -53,13 +54,15 @@ execMsg = &msg + } + // executing messages have multiple entries in the database + // they should start with the initiating message and then include the execution +- fmt.Println("p.chain", p.chain) +- err = p.logStore.AddLog(p.chain, logHash, block.ID(), block.Time, uint32(l.Index), execMsg) ++ err = p.logStore.AddLog(p.chain, logHash, block.ParentID(), uint32(l.Index), execMsg) + if err != nil { + return fmt.Errorf("failed to add log %d from block %v: %w", l.Index, block.ID(), err) + } + } + } ++ if err := p.logStore.SealBlock(p.chain, block.ParentHash, block.ID(), block.Time); err != nil { ++ return fmt.Errorf("failed to seal block %s: %w", block.ID(), err) ++ } + return nil + } +  +@@ -68,7 +71,7 @@ // it is the concatenation of the log's address and the hash of the log's payload, + // which is then hashed again. This is the hash that is stored in the log storage. + // The address is hashed into the payload hash to save space in the log storage, + // and because they represent paired data. +-func logToLogHash(l *ethTypes.Log) backendTypes.TruncatedHash { ++func logToLogHash(l *ethTypes.Log) common.Hash { + payloadHash := crypto.Keccak256(logToMessagePayload(l)) + return payloadHashToLogHash(common.Hash(payloadHash), l.Address) + } +@@ -90,9 +93,9 @@ // it is the concatenation of the log's address and the hash of the log's payload, + // which is then hashed. This is the hash that is stored in the log storage. + // The logHash can then be used to traverse from the executing message + // to the log the referenced initiating message. +-func payloadHashToLogHash(payloadHash common.Hash, addr common.Address) backendTypes.TruncatedHash { ++func payloadHashToLogHash(payloadHash common.Hash, addr common.Address) common.Hash { + msg := make([]byte, 0, 2*common.HashLength) + msg = append(msg, addr.Bytes()...) + msg = append(msg, payloadHash.Bytes()...) +- return backendTypes.TruncateHash(crypto.Keccak256Hash(msg)) ++ return crypto.Keccak256Hash(msg) + }
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+75
+
-40
+ +
+ +
+
+
diff --git OP/op-supervisor/supervisor/backend/source/log_processor_test.go CELO/op-supervisor/supervisor/backend/source/log_processor_test.go +index 5c65973ab4e498ca1bc741350c77c0e4637b0a91..bd7aa7abc3d104c2732ac2942a179a88adef15db 100644 +--- OP/op-supervisor/supervisor/backend/source/log_processor_test.go ++++ CELO/op-supervisor/supervisor/backend/source/log_processor_test.go +@@ -7,18 +7,22 @@ "testing" +  + "github.com/ethereum-optimism/optimism/op-service/eth" + "github.com/ethereum-optimism/optimism/op-service/predeploys" +- backendTypes "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/backend/types" +- supTypes "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" ++ "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types" + "github.com/ethereum/go-ethereum/common" + ethTypes "github.com/ethereum/go-ethereum/core/types" + "github.com/stretchr/testify/require" + ) +  +-var logProcessorChainID = supTypes.ChainIDFromUInt64(4) ++var logProcessorChainID = types.ChainIDFromUInt64(4) +  + func TestLogProcessor(t *testing.T) { + ctx := context.Background() +- block1 := eth.L1BlockRef{Number: 100, Hash: common.Hash{0x11}, Time: 1111} ++ block1 := eth.L1BlockRef{ ++ ParentHash: common.Hash{0x42}, ++ Number: 100, ++ Hash: common.Hash{0x11}, ++ Time: 1111, ++ } + t.Run("NoOutputWhenLogsAreEmpty", func(t *testing.T) { + store := &stubLogStorage{} + processor := newLogProcessor(logProcessorChainID, store) +@@ -59,30 +63,36 @@ processor := newLogProcessor(logProcessorChainID, store) +  + err := processor.ProcessLogs(ctx, block1, rcpts) + require.NoError(t, err) +- expected := []storedLog{ ++ expectedLogs := []storedLog{ + { +- block: block1.ID(), +- timestamp: block1.Time, +- logIdx: 0, +- logHash: logToLogHash(rcpts[0].Logs[0]), +- execMsg: nil, ++ parent: block1.ParentID(), ++ logIdx: 0, ++ logHash: logToLogHash(rcpts[0].Logs[0]), ++ execMsg: nil, + }, + { +- block: block1.ID(), +- timestamp: block1.Time, +- logIdx: 0, +- logHash: logToLogHash(rcpts[0].Logs[1]), +- execMsg: nil, ++ parent: block1.ParentID(), ++ logIdx: 0, ++ logHash: logToLogHash(rcpts[0].Logs[1]), ++ execMsg: nil, + }, + { ++ parent: block1.ParentID(), ++ logIdx: 0, ++ logHash: logToLogHash(rcpts[1].Logs[0]), ++ execMsg: nil, ++ }, ++ } ++ require.Equal(t, expectedLogs, store.logs) ++ ++ expectedBlocks := []storedSeal{ ++ { ++ parent: block1.ParentHash, + block: block1.ID(), + timestamp: block1.Time, +- logIdx: 0, +- logHash: logToLogHash(rcpts[1].Logs[0]), +- execMsg: nil, + }, + } +- require.Equal(t, expected, store.logs) ++ require.Equal(t, expectedBlocks, store.seals) + }) +  + t.Run("IncludeExecutingMessage", func(t *testing.T) { +@@ -97,16 +107,16 @@ }, + }, + }, + } +- execMsg := backendTypes.ExecutingMessage{ ++ execMsg := types.ExecutingMessage{ + Chain: 4, + BlockNum: 6, + LogIdx: 8, + Timestamp: 10, +- Hash: backendTypes.TruncatedHash{0xaa}, ++ Hash: common.Hash{0xaa}, + } + store := &stubLogStorage{} +- processor := newLogProcessor(supTypes.ChainID{4}, store) +- processor.eventDecoder = EventDecoderFn(func(l *ethTypes.Log) (backendTypes.ExecutingMessage, error) { ++ processor := newLogProcessor(types.ChainID{4}, store) ++ processor.eventDecoder = EventDecoderFn(func(l *ethTypes.Log) (types.ExecutingMessage, error) { + require.Equal(t, rcpts[0].Logs[0], l) + return execMsg, nil + }) +@@ -115,14 +125,22 @@ err := processor.ProcessLogs(ctx, block1, rcpts) + require.NoError(t, err) + expected := []storedLog{ + { ++ parent: block1.ParentID(), ++ logIdx: 0, ++ logHash: logToLogHash(rcpts[0].Logs[0]), ++ execMsg: &execMsg, ++ }, ++ } ++ require.Equal(t, expected, store.logs) ++ ++ expectedBlocks := []storedSeal{ ++ { ++ parent: block1.ParentHash, + block: block1.ID(), + timestamp: block1.Time, +- logIdx: 0, +- logHash: logToLogHash(rcpts[0].Logs[0]), +- execMsg: &execMsg, + }, + } +- require.Equal(t, expected, store.logs) ++ require.Equal(t, expectedBlocks, store.seals) + }) + } +  +@@ -163,7 +181,7 @@ } + refHash := logToLogHash(mkLog()) + // The log hash is stored in the database so test that it matches the actual value. + // If this changes, compatibility with existing databases may be affected +- expectedRefHash := backendTypes.TruncateHash(common.HexToHash("0x4e1dc08fddeb273275f787762cdfe945cf47bb4e80a1fabbc7a825801e81b73f")) ++ expectedRefHash := common.HexToHash("0x4e1dc08fddeb273275f787762cdfe945cf47bb4e80a1fabbc7a825801e81b73f") + require.Equal(t, expectedRefHash, refHash, "reference hash changed, check that database compatibility is not broken") +  + // Check that the hash is changed when any data it should include changes +@@ -183,33 +201,50 @@ } + } +  + type stubLogStorage struct { +- logs []storedLog ++ logs []storedLog ++ seals []storedSeal + } +  +-func (s *stubLogStorage) AddLog(chainID supTypes.ChainID, logHash backendTypes.TruncatedHash, block eth.BlockID, timestamp uint64, logIdx uint32, execMsg *backendTypes.ExecutingMessage) error { ++func (s *stubLogStorage) SealBlock(chainID types.ChainID, parentHash common.Hash, block eth.BlockID, timestamp uint64) error { + if logProcessorChainID != chainID { + return fmt.Errorf("chain id mismatch, expected %v but got %v", logProcessorChainID, chainID) + } +- s.logs = append(s.logs, storedLog{ ++ s.seals = append(s.seals, storedSeal{ ++ parent: parentHash, + block: block, + timestamp: timestamp, +- logIdx: logIdx, +- logHash: logHash, +- execMsg: execMsg, ++ }) ++ return nil ++} ++ ++func (s *stubLogStorage) AddLog(chainID types.ChainID, logHash common.Hash, parentBlock eth.BlockID, logIdx uint32, execMsg *types.ExecutingMessage) error { ++ if logProcessorChainID != chainID { ++ return fmt.Errorf("chain id mismatch, expected %v but got %v", logProcessorChainID, chainID) ++ } ++ s.logs = append(s.logs, storedLog{ ++ parent: parentBlock, ++ logIdx: logIdx, ++ logHash: logHash, ++ execMsg: execMsg, + }) + return nil + } +  +-type storedLog struct { ++type storedSeal struct { ++ parent common.Hash + block eth.BlockID + timestamp uint64 +- logIdx uint32 +- logHash backendTypes.TruncatedHash +- execMsg *backendTypes.ExecutingMessage + } +  +-type EventDecoderFn func(*ethTypes.Log) (backendTypes.ExecutingMessage, error) ++type storedLog struct { ++ parent eth.BlockID ++ logIdx uint32 ++ logHash common.Hash ++ execMsg *types.ExecutingMessage ++} +  +-func (f EventDecoderFn) DecodeExecutingMessageLog(log *ethTypes.Log) (backendTypes.ExecutingMessage, error) { ++type EventDecoderFn func(*ethTypes.Log) (types.ExecutingMessage, error) ++ ++func (f EventDecoderFn) DecodeExecutingMessageLog(log *ethTypes.Log) (types.ExecutingMessage, error) { + return f(log) + }
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + (deleted) + +
+
+
+ +
+ +
+ +
+0
+
-27
+ +
+ +
+
+
diff --git OP/op-supervisor/supervisor/backend/types/types.go CELO/op-supervisor/supervisor/backend/types/types.go +deleted file mode 100644 +index cf28120a34ee8fd5015ae17e279aaa9e60563a02..0000000000000000000000000000000000000000 +--- OP/op-supervisor/supervisor/backend/types/types.go ++++ /dev/null +@@ -1,27 +0,0 @@ +-package types +- +-import ( +- "encoding/hex" +- +- "github.com/ethereum/go-ethereum/common" +-) +- +-type TruncatedHash [20]byte +- +-func TruncateHash(hash common.Hash) TruncatedHash { +- var truncated TruncatedHash +- copy(truncated[:], hash[0:20]) +- return truncated +-} +- +-func (h TruncatedHash) String() string { +- return hex.EncodeToString(h[:]) +-} +- +-type ExecutingMessage struct { +- Chain uint32 +- BlockNum uint64 +- LogIdx uint32 +- Timestamp uint64 +- Hash TruncatedHash +-}
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+6
+
-0
+ +
+ +
+
+
diff --git OP/op-supervisor/supervisor/frontend/frontend.go CELO/op-supervisor/supervisor/frontend/frontend.go +index 421b231e128ead5c383fa27602abeda786b80b40..41fb84e511cd264fa3eb5847d2a06042c20264b7 100644 +--- OP/op-supervisor/supervisor/frontend/frontend.go ++++ CELO/op-supervisor/supervisor/frontend/frontend.go +@@ -12,6 +12,7 @@ + type AdminBackend interface { + Start(ctx context.Context) error + Stop(ctx context.Context) error ++ AddL2RPC(ctx context.Context, rpc string) error + } +  + type QueryBackend interface { +@@ -61,3 +62,8 @@ // Stop stops the service, if it was previously started. + func (a *AdminFrontend) Stop(ctx context.Context) error { + return a.Supervisor.Stop(ctx) + } ++ ++// AddL2RPC adds a new L2 chain to the supervisor backend ++func (a *AdminFrontend) AddL2RPC(ctx context.Context, rpc string) error { ++ return a.Supervisor.AddL2RPC(ctx, rpc) ++}
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+9
+
-1
+ +
+ +
+
+
diff --git OP/op-supervisor/supervisor/service.go CELO/op-supervisor/supervisor/service.go +index aecd90ad2fbadcdeae4fdf64f401bfa7d2e4cc3a..47fcb3e9ec23e35ccd51f5bc672c77e2454c7e71 100644 +--- OP/op-supervisor/supervisor/service.go ++++ CELO/op-supervisor/supervisor/service.go +@@ -164,6 +164,7 @@ return fmt.Errorf("unable to start backend: %w", err) + } +  + su.metrics.RecordUp() ++ su.log.Info("JSON-RPC Server started", "endpoint", su.rpcServer.Endpoint()) + return nil + } +  +@@ -171,7 +172,7 @@ func (su *SupervisorService) Stop(ctx context.Context) error { + if !su.closing.CompareAndSwap(false, true) { + return nil // already closing + } +- ++ su.log.Info("Stopping JSON-RPC server") + var result error + if su.rpcServer != nil { + if err := su.rpcServer.Stop(); err != nil { +@@ -193,9 +194,16 @@ if err := su.metricsSrv.Stop(ctx); err != nil { + result = errors.Join(result, fmt.Errorf("failed to stop metrics server: %w", err)) + } + } ++ su.log.Info("JSON-RPC server stopped") + return result + } +  + func (su *SupervisorService) Stopped() bool { + return su.closing.Load() + } ++ ++func (su *SupervisorService) RPC() string { ++ // the RPC endpoint is assumed to be HTTP ++ // TODO(#11032): make this flexible for ws if the server supports it ++ return "http://" + su.rpcServer.Endpoint() ++}
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+8
+
-0
+ +
+ +
+
+
diff --git OP/op-supervisor/supervisor/types/types.go CELO/op-supervisor/supervisor/types/types.go +index 54b1a8a0c92c0200baf9df3e721691124f5901a6..b035e26abcefd2a23ce2bf8ddd7323f43f0f68fe 100644 +--- OP/op-supervisor/supervisor/types/types.go ++++ CELO/op-supervisor/supervisor/types/types.go +@@ -13,6 +13,14 @@ "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + ) +  ++type ExecutingMessage struct { ++ Chain uint32 // same as ChainID for now, but will be indirect, i.e. translated to full ID, later ++ BlockNum uint64 ++ LogIdx uint32 ++ Timestamp uint64 ++ Hash common.Hash ++} ++ + type Message struct { + Identifier Identifier `json:"identifier"` + PayloadHash common.Hash `json:"payloadHash"`
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+2
+
-6
+ +
+ +
+
+
diff --git OP/ops/docker/Dockerfile.packages CELO/ops/docker/Dockerfile.packages +index f4f110244f5f3cf32481a5a5ecf3b842ebe907e6..dbd496afc8af3a19e08be7371744091caa81deb5 100644 +--- OP/ops/docker/Dockerfile.packages ++++ CELO/ops/docker/Dockerfile.packages +@@ -34,7 +34,7 @@ && cd packages/contracts-bedrock \ + && just build \ + && echo $(git rev-parse HEAD) > .gitcommit +  +-FROM --platform=linux/amd64 debian:bookworm-20240812-slim ++FROM --platform=linux/amd64 debian:bookworm-20240812-slim as contracts-bedrock +  + RUN apt-get update && apt-get install -y \ + curl \ +@@ -70,8 +70,4 @@ COPY --from=base /opt/optimism/versions.json /opt/optimism/versions.json +  + WORKDIR /opt/optimism/packages/contracts-bedrock +  +-# Set "just" as entrypoint, so the default args (the Dockerfile CMD) +-# are passed in to it. This was previously "pnpm run" + "deploy". +-ENTRYPOINT ["just"] +- +-CMD ["deploy"] ++CMD ["echo", "Override this command to use this image."]
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+34
+
-0
+ +
+ +
+
+
diff --git OP/ops/docker/deployment-utils/Dockerfile CELO/ops/docker/deployment-utils/Dockerfile +new file mode 100644 +index 0000000000000000000000000000000000000000..c0f82e5a3405d97f301a7e75d7afa47a8e739024 +--- /dev/null ++++ CELO/ops/docker/deployment-utils/Dockerfile +@@ -0,0 +1,35 @@ ++FROM golang:1.23.1-bookworm AS go-base ++ ++RUN go install github.com/tomwright/dasel/v2/cmd/dasel@master ++ ++FROM debian:12.7-slim AS base ++ ++SHELL ["/bin/bash", "-c"] ++ ++ENV PATH=/root/.cargo/bin:/root/.foundry/bin:$PATH ++ENV DEBIAN_FRONTEND=noninteractive ++ENV SHELL=/bin/bash ++ ++RUN apt-get update && apt-get install -y curl git jq build-essential ++ ++RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > rustup.sh && \ ++ chmod +x ./rustup.sh && \ ++ sh rustup.sh -y ++ ++RUN source $HOME/.profile && rustup update nightly ++RUN curl -L https://foundry.paradigm.xyz | bash ++RUN foundryup ++ ++FROM debian:12.7-slim ++ ++ENV PATH=/root/.cargo/bin:/root/.foundry/bin:$PATH ++ENV DEBIAN_FRONTEND=noninteractive ++ ++RUN apt-get update && apt-get install -y bash curl jq ++ ++SHELL ["/bin/bash", "-c"] ++ ++COPY --from=base /root/.foundry/bin/forge /usr/local/bin/forge ++COPY --from=base /root/.foundry/bin/cast /usr/local/bin/cast ++COPY --from=base /root/.foundry/bin/anvil /usr/local/bin/anvil ++COPY --from=go-base /go/bin/dasel /usr/local/bin/dasel +\ No newline at end of file
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+15
+
-0
+ +
+ +
+
+
diff --git OP/ops/docker/deployment-utils/README.md CELO/ops/docker/deployment-utils/README.md +new file mode 100644 +index 0000000000000000000000000000000000000000..450af3423b11dbe59596e8a3d10c8ddd59ab7f3a +--- /dev/null ++++ CELO/ops/docker/deployment-utils/README.md +@@ -0,0 +1,16 @@ ++# deployment-utils ++ ++This image provides a minimal set of Foundry and Bash tools for use with builder images like Kurtosis. It contains the ++following packages: ++ ++- The Foundry suite (`forge`, `cast`, `anvil`) ++- [`Dasel`](https://github.com/TomWright/dasel), for TOML/YAML manipulation. ++- `jq` for JSON manipulation. ++- `curl`, for when you need to cURLs. ++- A default `bash` shell. ++ ++## Image Size ++ ++According to `dive`, this image is 255MB in size including the base Debian image. Most of the additional size comes from ++the tools themselves. I'd like to keep it this way. This image should not contain toolchains, libraries, etc. - it is ++designed to run prebuilt software and manipulate configuration files. Use the CI builder for everything else. +\ No newline at end of file
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+17
+
-0
+ +
+ +
+
+
diff --git OP/ops/docker/op-stack-go/Dockerfile CELO/ops/docker/op-stack-go/Dockerfile +index 18163a86c3ccb0329408d1443174cf5e83f5f0f6..35f14d19a4391b7680d67084d8885527f5273932 100644 +--- OP/ops/docker/op-stack-go/Dockerfile ++++ CELO/ops/docker/op-stack-go/Dockerfile +@@ -46,8 +46,15 @@ + # Build the Go services, utilizing caches and share the many common packages. + # The "id" defaults to the value of "target", the cache will thus be reused during this build. + # "sharing" defaults to "shared", the cache will thus be available to other concurrent docker builds. ++ ++# For now fetch the v1 cannon binary from the op-challenger image ++#FROM --platform=$BUILDPLATFORM us-docker.pkg.dev/oplabs-tools-artifacts/images/op-challenger:v1.1.0 AS cannon-builder-0 ++ + FROM --platform=$BUILDPLATFORM builder AS cannon-builder + ARG CANNON_VERSION=v0.0.0 ++# uncomment these lines once there's a new Cannon version available ++#COPY --from=cannon-builder-0 /usr/local/bin/cannon ./cannon/multicannon/embeds/cannon-0 ++#COPY --from=cannon-builder-0 /usr/local/bin/cannon ./cannon/multicannon/embeds/cannon-1 + RUN --mount=type=cache,target=/go/pkg/mod --mount=type=cache,target=/root/.cache/go-build cd cannon && make cannon \ + GOOS=$TARGETOS GOARCH=$TARGETARCH GITCOMMIT=$GIT_COMMIT GITDATE=$GIT_DATE VERSION="$CANNON_VERSION" +  +@@ -101,8 +108,14 @@ ARG OP_SUPERVISOR_VERSION=v0.0.0 + RUN --mount=type=cache,target=/go/pkg/mod --mount=type=cache,target=/root/.cache/go-build cd op-supervisor && make op-supervisor \ + GOOS=$TARGETOS GOARCH=$TARGETARCH GITCOMMIT=$GIT_COMMIT GITDATE=$GIT_DATE VERSION="$OP_SUPERVISOR_VERSION" +  ++FROM --platform=$BUILDPLATFORM builder AS op-deployer-builder ++ARG OP_NODE_VERSION=v0.0.0 ++RUN --mount=type=cache,target=/go/pkg/mod --mount=type=cache,target=/root/.cache/go-build cd op-chain-ops && make op-deployer \ ++ GOOS=$TARGETOS GOARCH=$TARGETARCH GITCOMMIT=$GIT_COMMIT GITDATE=$GIT_DATE VERSION="$OP_DEPLOYER_VERSION" ++ + FROM --platform=$TARGETPLATFORM $TARGET_BASE_IMAGE AS cannon-target + COPY --from=cannon-builder /app/cannon/bin/cannon /usr/local/bin/ ++COPY --from=cannon-builder /app/cannon/multicannon/embeds/* /usr/local/bin/ + CMD ["cannon"] +  + FROM --platform=$TARGETPLATFORM $TARGET_BASE_IMAGE AS op-program-target +@@ -150,3 +163,7 @@ + FROM --platform=$TARGETPLATFORM $TARGET_BASE_IMAGE AS op-supervisor-target + COPY --from=op-supervisor-builder /app/op-supervisor/bin/op-supervisor /usr/local/bin/ + CMD ["op-supervisor"] ++ ++FROM --platform=$TARGETPLATFORM $TARGET_BASE_IMAGE AS op-deployer-target ++COPY --from=op-deployer-builder /app/op-chain-ops/bin/op-deployer /usr/local/bin/ ++CMD ["op-deployer"]
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+26
+
-0
+ +
+ +
+
+
diff --git OP/ops/docker/proofs-tools/Dockerfile CELO/ops/docker/proofs-tools/Dockerfile +new file mode 100644 +index 0000000000000000000000000000000000000000..61f39c8af705719bb5906f700437f9759dda6ae4 +--- /dev/null ++++ CELO/ops/docker/proofs-tools/Dockerfile +@@ -0,0 +1,26 @@ ++ARG GIT_COMMIT ++ARG GIT_DATE ++ ++ARG CHALLENGER_VERSION ++ARG KONA_VERSION ++ARG ASTERISC_VERSION ++ ++FROM --platform=$BUILDPLATFORM us-docker.pkg.dev/oplabs-tools-artifacts/images/op-challenger:$CHALLENGER_VERSION AS challenger ++FROM --platform=$BUILDPLATFORM ghcr.io/anton-rs/kona/kona-fpp-asterisc:$KONA_VERSION AS kona ++FROM --platform=$BUILDPLATFORM ghcr.io/ethereum-optimism/asterisc/asterisc:$ASTERISC_VERSION AS asterisc ++ ++FROM --platform=$BUILDPLATFORM ubuntu:22.04 AS proofs-tools ++RUN apt-get update && apt-get install -y --no-install-recommends musl openssl ca-certificates ++COPY --from=challenger /usr/local/bin/op-challenger /usr/local/bin/ ++COPY --from=challenger /usr/local/bin/cannon /usr/local/bin/ ++ENV OP_CHALLENGER_CANNON_BIN /usr/local/bin/cannon ++COPY --from=challenger /usr/local/bin/op-program /usr/local/bin/ ++ENV OP_CHALLENGER_CANNON_SERVER=/usr/local/bin/op-program ++ ++COPY --from=kona /kona-host /usr/local/bin/ ++ENV OP_CHALLENGER_ASTERISC_KONA_SERVER=/usr/local/bin/kona-host ++ ++COPY --from=asterisc /usr/local/bin/asterisc /usr/local/bin/ ++ENV OP_CHALLENGER_ASTERISC_BIN=/usr/local/bin/asterisc ++ ++CMD /usr/local/bin/op-challenger
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+8
+
-0
+ +
+ +
+
+
diff --git OP/ops/docker/proofs-tools/README.md CELO/ops/docker/proofs-tools/README.md +new file mode 100644 +index 0000000000000000000000000000000000000000..faa47f8d4ad33c5340635d2908c8bb23d9e85f2b +--- /dev/null ++++ CELO/ops/docker/proofs-tools/README.md +@@ -0,0 +1,8 @@ ++## Proofs Tools ++ ++The proofs-tools docker image provides a collection of useful fault proofs related tools in a single docker image. ++In particular it provides op-challenger with cannon, asterisc, op-program and kona-host ready to participate in ++cannon, asterisc or asterisc-kona game types. ++ ++The version of each tool used in the image is specified ++in [docker-bake.hcl](https://github.com/ethereum-optimism/optimism/blob/develop/docker-bake.hcl).
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+1
+
-1
+ +
+ +
+
+
diff --git OP/ops/scripts/ci-docker-tag-op-stack-release.sh CELO/ops/scripts/ci-docker-tag-op-stack-release.sh +index 49904d7cce9af7a7743f9a72079d945c084246fb..45dd920949946f40a8ce855ede42f6adb2b12bd8 100755 +--- OP/ops/scripts/ci-docker-tag-op-stack-release.sh ++++ CELO/ops/scripts/ci-docker-tag-op-stack-release.sh +@@ -6,7 +6,7 @@ DOCKER_REPO=$1 + GIT_TAG=$2 + GIT_SHA=$3 +  +-IMAGE_NAME=$(echo "$GIT_TAG" | grep -Eow '^(ci-builder(-rust)?|da-server|ufm-[a-z0-9\-]*|op-[a-z0-9\-]*)' || true) ++IMAGE_NAME=$(echo "$GIT_TAG" | grep -Eow '^(ci-builder(-rust)?|da-server|proofs-tools|cannon|ufm-[a-z0-9\-]*|op-[a-z0-9\-]*)' || true) + if [ -z "$IMAGE_NAME" ]; then + echo "image name could not be parsed from git tag '$GIT_TAG'" + exit 1
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+15
+
-7
+ +
+ +
+
+
diff --git OP/ops/scripts/todo-checker.sh CELO/ops/scripts/todo-checker.sh +index d90d97fc47c9de8cc4e12d0ee39a11c3253ca4f7..6b144ec200cfda6ef4dd05d546450359bc5318d2 100755 +--- OP/ops/scripts/todo-checker.sh ++++ CELO/ops/scripts/todo-checker.sh +@@ -5,6 +5,7 @@ + # Flags + FAIL_INVALID_FMT=false + VERBOSE=false ++CHECK_CLOSED=false +  + # Github API access token (Optional - necessary for private repositories.) + GH_API_TOKEN="${CI_TODO_CHECKER_PAT:-""}" +@@ -36,6 +37,7 @@ # Parse flags + # + # `--strict`: Toggle strict mode; Will fail if any TODOs are found that don't match the expected + # `--verbose`: Toggle verbose mode; Will print out details about each TODO ++# `--check-closed`: Check for closed issues and error out if found + for arg in "$@"; do + case $arg in + --strict) +@@ -44,6 +46,10 @@ shift + ;; + --verbose) + VERBOSE=true ++ shift ++ ;; ++ --check-closed) ++ CHECK_CLOSED=true + shift + ;; + esac +@@ -65,10 +71,10 @@ # * TODO(<issue_number>): <description> (Default org & repo: "ethereum-optimism/monorepo") + # * TODO(repo#<issue_number>): <description> (Default org "ethereum-optimism") + # * TODO(org/repo#<issue_number>): <description> + # +- # Check if it's just a number +- if [[ $ISSUE_REFERENCE =~ ^[0-9]+$ ]]; then ++ # Check if it's just a number or a number with a leading # ++ if [[ $ISSUE_REFERENCE =~ ^[0-9]+$ ]] || [[ $ISSUE_REFERENCE =~ ^#([0-9]+)$ ]]; then + REPO_FULL="$ORG/$REPO" +- ISSUE_NUM="$ISSUE_REFERENCE" ++ ISSUE_NUM="${ISSUE_REFERENCE#\#}" # Remove leading # if present + # Check for org_name/repo_name#number format + elif [[ $ISSUE_REFERENCE =~ ^([^/]+)/([^#]+)#([0-9]+)$ ]]; then + REPO_FULL="${BASH_REMATCH[1]}/${BASH_REMATCH[2]}" +@@ -104,14 +110,16 @@ + # Check issue state + STATE=$(echo "$RESPONSE" | jq -r .state) +  +- if [[ "$STATE" == "closed" ]]; then ++ if [[ "$STATE" == "closed" ]] && $CHECK_CLOSED; then + echo -e "${RED}[Error]:${NC} Issue #$ISSUE_NUM is closed. Please remove the TODO in ${GREEN}$FILE:$LINE_NUM${NC} referencing ${YELLOW}$ISSUE_REFERENCE${NC} (${CYAN}https://github.com/$GH_URL_PATH${NC})" + exit 1 + fi +  +- ((OPEN_COUNT++)) +- TITLE=$(echo "$RESPONSE" | jq -r .title) +- OPEN_ISSUES+=("$REPO_FULL/issues/$ISSUE_NUM|$TITLE|$FILE:$LINE_NUM") ++ if [[ "$STATE" == "open" ]]; then ++ ((OPEN_COUNT++)) ++ TITLE=$(echo "$RESPONSE" | jq -r .title) ++ OPEN_ISSUES+=("$REPO_FULL/issues/$ISSUE_NUM|$TITLE|$FILE:$LINE_NUM") ++ fi + done +  + # Print summary
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+280
+
-0
+ +
+ +
+
+
diff --git OP/packages/contracts-bedrock/lib/multicall/src/Multicall3.sol CELO/packages/contracts-bedrock/lib/multicall/src/Multicall3.sol +new file mode 100644 +index 0000000000000000000000000000000000000000..92195a5e91b974b51d163cdf29f56f02f2b149c9 +--- /dev/null ++++ CELO/packages/contracts-bedrock/lib/multicall/src/Multicall3.sol +@@ -0,0 +1,280 @@ ++// SPDX-License-Identifier: MIT ++pragma solidity ^0.8.12; ++ ++/// @title Multicall3 ++/// @notice Aggregate results from multiple function calls ++/// @dev Multicall & Multicall2 backwards-compatible ++/// @dev Aggregate methods are marked `payable` to save 24 gas per call ++/// @author Michael Elliot <mike@makerdao.com> ++/// @author Joshua Levine <joshua@makerdao.com> ++/// @author Nick Johnson <arachnid@notdot.net> ++/// @author Andreas Bigger <andreas@nascent.xyz> ++/// @author Matt Solomon <matt@mattsolomon.dev> ++contract Multicall3 { ++ struct Call { ++ address target; ++ bytes callData; ++ } ++ ++ struct Call3 { ++ address target; ++ bool allowFailure; ++ bytes callData; ++ } ++ ++ struct Call3Value { ++ address target; ++ bool allowFailure; ++ uint256 value; ++ bytes callData; ++ } ++ ++ struct Result { ++ bool success; ++ bytes returnData; ++ } ++ ++ /// @notice Backwards-compatible call aggregation with Multicall ++ /// @param calls An array of Call structs ++ /// @return blockNumber The block number where the calls were executed ++ /// @return returnData An array of bytes containing the responses ++ function aggregate( ++ Call[] calldata calls ++ ) public payable returns (uint256 blockNumber, bytes[] memory returnData) { ++ blockNumber = block.number; ++ uint256 length = calls.length; ++ returnData = new bytes[](length); ++ Call calldata call; ++ for (uint256 i = 0; i < length; ) { ++ bool success; ++ call = calls[i]; ++ (success, returnData[i]) = call.target.call(call.callData); ++ require(success, 'Multicall3: call failed'); ++ unchecked { ++ ++i; ++ } ++ } ++ } ++ ++ /// @notice Backwards-compatible with Multicall2 ++ /// @notice Aggregate calls without requiring success ++ /// @param requireSuccess If true, require all calls to succeed ++ /// @param calls An array of Call structs ++ /// @return returnData An array of Result structs ++ function tryAggregate( ++ bool requireSuccess, ++ Call[] calldata calls ++ ) public payable returns (Result[] memory returnData) { ++ uint256 length = calls.length; ++ returnData = new Result[](length); ++ Call calldata call; ++ for (uint256 i = 0; i < length; ) { ++ Result memory result = returnData[i]; ++ call = calls[i]; ++ (result.success, result.returnData) = call.target.call(call.callData); ++ if (requireSuccess) require(result.success, 'Multicall3: call failed'); ++ unchecked { ++ ++i; ++ } ++ } ++ } ++ ++ /// @notice Backwards-compatible with Multicall2 ++ /// @notice Aggregate calls and allow failures using tryAggregate ++ /// @param calls An array of Call structs ++ /// @return blockNumber The block number where the calls were executed ++ /// @return blockHash The hash of the block where the calls were executed ++ /// @return returnData An array of Result structs ++ function tryBlockAndAggregate( ++ bool requireSuccess, ++ Call[] calldata calls ++ ) ++ public ++ payable ++ returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData) + { -+ type: 'error', -+ name: 'Unauthorized', -+ inputs: [], -+ }, ++ blockNumber = block.number; ++ blockHash = blockhash(block.number); ++ returnData = tryAggregate(requireSuccess, calls); ++ } ++ ++ /// @notice Backwards-compatible with Multicall2 ++ /// @notice Aggregate calls and allow failures using tryAggregate ++ /// @param calls An array of Call structs ++ /// @return blockNumber The block number where the calls were executed ++ /// @return blockHash The hash of the block where the calls were executed ++ /// @return returnData An array of Result structs ++ function blockAndAggregate( ++ Call[] calldata calls ++ ) ++ public ++ payable ++ returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData) + { -+ type: 'error', -+ name: 'UnexpectedList', -+ inputs: [], -+ }, ++ (blockNumber, blockHash, returnData) = tryBlockAndAggregate(true, calls); ++ } ++ ++ /// @notice Aggregate calls, ensuring each returns success if required ++ /// @param calls An array of Call3 structs ++ /// @return returnData An array of Result structs ++ function aggregate3( ++ Call3[] calldata calls ++ ) public payable returns (Result[] memory returnData) { ++ uint256 length = calls.length; ++ returnData = new Result[](length); ++ Call3 calldata calli; ++ for (uint256 i = 0; i < length; ) { ++ Result memory result = returnData[i]; ++ calli = calls[i]; ++ (result.success, result.returnData) = calli.target.call(calli.callData); ++ assembly { ++ // Revert if the call fails and failure is not allowed ++ // `allowFailure := calldataload(add(calli, 0x20))` and `success := mload(result)` ++ if iszero(or(calldataload(add(calli, 0x20)), mload(result))) { ++ // set "Error(string)" signature: bytes32(bytes4(keccak256("Error(string)"))) ++ mstore( ++ 0x00, ++ 0x08c379a000000000000000000000000000000000000000000000000000000000 ++ ) ++ // set data offset ++ mstore( ++ 0x04, ++ 0x0000000000000000000000000000000000000000000000000000000000000020 ++ ) ++ // set length of revert string ++ mstore( ++ 0x24, ++ 0x0000000000000000000000000000000000000000000000000000000000000017 ++ ) ++ // set revert string: bytes32(abi.encodePacked("Multicall3: call failed")) ++ mstore( ++ 0x44, ++ 0x4d756c746963616c6c333a2063616c6c206661696c6564000000000000000000 ++ ) ++ revert(0x00, 0x64) ++ } ++ } ++ unchecked { ++ ++i; ++ } ++ } ++ } ++ ++ /// @notice Aggregate calls with a msg value ++ /// @notice Reverts if msg.value is less than the sum of the call values ++ /// @param calls An array of Call3Value structs ++ /// @return returnData An array of Result structs ++ function aggregate3Value( ++ Call3Value[] calldata calls ++ ) public payable returns (Result[] memory returnData) { ++ uint256 valAccumulator; ++ uint256 length = calls.length; ++ returnData = new Result[](length); ++ Call3Value calldata calli; ++ for (uint256 i = 0; i < length; ) { ++ Result memory result = returnData[i]; ++ calli = calls[i]; ++ uint256 val = calli.value; ++ // Humanity will be a Type V Kardashev Civilization before this overflows - andreas ++ // ~ 10^25 Wei in existence << ~ 10^76 size uint fits in a uint256 ++ unchecked { ++ valAccumulator += val; ++ } ++ (result.success, result.returnData) = calli.target.call{value: val}( ++ calli.callData ++ ); ++ assembly { ++ // Revert if the call fails and failure is not allowed ++ // `allowFailure := calldataload(add(calli, 0x20))` and `success := mload(result)` ++ if iszero(or(calldataload(add(calli, 0x20)), mload(result))) { ++ // set "Error(string)" signature: bytes32(bytes4(keccak256("Error(string)"))) ++ mstore( ++ 0x00, ++ 0x08c379a000000000000000000000000000000000000000000000000000000000 ++ ) ++ // set data offset ++ mstore( ++ 0x04, ++ 0x0000000000000000000000000000000000000000000000000000000000000020 ++ ) ++ // set length of revert string ++ mstore( ++ 0x24, ++ 0x0000000000000000000000000000000000000000000000000000000000000017 ++ ) ++ // set revert string: bytes32(abi.encodePacked("Multicall3: call failed")) ++ mstore( ++ 0x44, ++ 0x4d756c746963616c6c333a2063616c6c206661696c6564000000000000000000 ++ ) ++ revert(0x00, 0x84) ++ } ++ } ++ unchecked { ++ ++i; ++ } ++ } ++ // Finally, make sure the msg.value = SUM(call[0...i].value) ++ require(msg.value == valAccumulator, 'Multicall3: value mismatch'); ++ } ++ ++ /// @notice Returns the block hash for the given block number ++ /// @param blockNumber The block number ++ function getBlockHash( ++ uint256 blockNumber ++ ) public view returns (bytes32 blockHash) { ++ blockHash = blockhash(blockNumber); ++ } ++ ++ /// @notice Returns the block number ++ function getBlockNumber() public view returns (uint256 blockNumber) { ++ blockNumber = block.number; ++ } ++ ++ /// @notice Returns the block coinbase ++ function getCurrentBlockCoinbase() public view returns (address coinbase) { ++ coinbase = block.coinbase; ++ } ++ ++ /// @notice Returns the block difficulty ++ function getCurrentBlockDifficulty() ++ public ++ view ++ returns (uint256 difficulty) + { -+ type: 'error', -+ name: 'UnexpectedString', -+ inputs: [], -+ }, -+]
++ difficulty = block.difficulty; ++ } ++ ++ /// @notice Returns the block gas limit ++ function getCurrentBlockGasLimit() public view returns (uint256 gaslimit) { ++ gaslimit = block.gaslimit; ++ } ++ ++ /// @notice Returns the block timestamp ++ function getCurrentBlockTimestamp() public view returns (uint256 timestamp) { ++ timestamp = block.timestamp; ++ } ++ ++ /// @notice Returns the (ETH) balance of a given address ++ function getEthBalance(address addr) public view returns (uint256 balance) { ++ balance = addr.balance; ++ } ++ ++ /// @notice Returns the block hash of the last block ++ function getLastBlockHash() public view returns (bytes32 blockHash) { ++ unchecked { ++ blockHash = blockhash(block.number - 1); ++ } ++ } ++ ++ /// @notice Gets the base fee of the given block ++ /// @notice Can revert if the BASEFEE opcode is not implemented by the given chain ++ function getBasefee() public view returns (uint256 basefee) { ++ basefee = block.basefee; ++ } ++ ++ /// @notice Returns the chain id ++ function getChainId() public view returns (uint256 chainid) { ++ chainid = block.chainid; ++ } ++}
+ + + +
+ + +
+
+
+ + OP + +
+ +
+ + (deleted) + +
+
+
+ +
+ +
+ +
+0
+
-256
+ +
+ +
+
+
diff --git OP/packages/contracts-bedrock/scripts/autogen/generate-invariant-docs/main.go CELO/packages/contracts-bedrock/scripts/autogen/generate-invariant-docs/main.go +deleted file mode 100644 +index 0f0f5c77e63d89cf1aab99d4c4b8271240e9fcc2..0000000000000000000000000000000000000000 +--- OP/packages/contracts-bedrock/scripts/autogen/generate-invariant-docs/main.go ++++ /dev/null +@@ -1,256 +0,0 @@ +-package main +- +-import ( +- "flag" +- "fmt" +- "os" +- "path/filepath" +- "slices" +- "strings" +-) +- +-const ( +- NatspecInv = "@custom:invariant" +- BaseInvariantGhUrl = "../test/invariants/" +-) +- +-// Contract represents an invariant test contract +-type Contract struct { +- Name string +- FileName string +- Docs []InvariantDoc +-} +- +-// InvariantDoc represents the documentation of an invariant +-type InvariantDoc struct { +- Header string +- Desc string +- LineNo int +-} +- +-var writtenFiles []string +- +-// Generate the docs +-func main() { +- flag.Parse() +- if flag.NArg() != 1 { +- fmt.Println("Expected path of contracts-bedrock as CLI argument") +- os.Exit(1) +- } +- rootDir := flag.Arg(0) +- +- invariantsDir := filepath.Join(rootDir, "test/invariants") +- fmt.Printf("invariants dir: %s\n", invariantsDir) +- docsDir := filepath.Join(rootDir, "invariant-docs") +- fmt.Printf("invariant docs dir: %s\n", docsDir) +- +- // Forge +- fmt.Println("Generating docs for forge invariants...") +- if err := docGen(invariantsDir, docsDir); err != nil { +- fmt.Printf("Failed to generate invariant docs: %v\n", err) +- os.Exit(1) +- } +- +- fmt.Println("Generating table-of-contents...") +- // Generate an updated table of contents +- if err := tocGen(docsDir); err != nil { +- fmt.Printf("Failed to generate TOC of docs: %v\n", err) +- os.Exit(1) +- } +- fmt.Println("Done!") +-} +- +-// Lazy-parses all test files in the `test/invariants` directory +-// to generate documentation on all invariant tests. +-func docGen(invariantsDir, docsDir string) error { +- +- // Grab all files within the invariants test dir +- files, err := os.ReadDir(invariantsDir) +- if err != nil { +- return fmt.Errorf("error reading directory: %w", err) +- } +- +- // Array to store all found invariant documentation comments. +- var docs []Contract +- +- for _, file := range files { +- // Read the contents of the invariant test file. +- fileName := file.Name() +- filePath := filepath.Join(invariantsDir, fileName) +- fileContents, err := os.ReadFile(filePath) +- if err != nil { +- return fmt.Errorf("error reading file %q: %w", filePath, err) +- } +- +- // Split the file into individual lines and trim whitespace. +- lines := strings.Split(string(fileContents), "\n") +- for i, line := range lines { +- lines[i] = strings.TrimSpace(line) +- } +- +- // Create an object to store all invariant test docs for the current contract +- name := strings.Replace(fileName, ".t.sol", "", 1) +- contract := Contract{Name: name, FileName: fileName} +- +- var currentDoc InvariantDoc +- +- // Loop through all lines to find comments. +- for i := 0; i < len(lines); i++ { +- line := lines[i] +- +- // We have an invariant doc +- if strings.HasPrefix(line, "/// "+NatspecInv) { +- // Assign the header of the invariant doc. +- currentDoc = InvariantDoc{ +- Header: strings.TrimSpace(strings.Replace(line, "/// "+NatspecInv, "", 1)), +- Desc: "", +- } +- i++ +- +- // If the header is multi-line, continue appending to the `currentDoc`'s header. +- for { +- if i >= len(lines) { +- break +- } +- line = lines[i] +- i++ +- if !(strings.HasPrefix(line, "///") && strings.TrimSpace(line) != "///") { +- break +- } +- currentDoc.Header += " " + strings.TrimSpace(strings.Replace(line, "///", "", 1)) +- } +- +- // Process the description +- for { +- if i >= len(lines) { +- break +- } +- line = lines[i] +- i++ +- if !strings.HasPrefix(line, "///") { +- break +- } +- line = strings.TrimSpace(strings.Replace(line, "///", "", 1)) +- +- // If the line has any contents, insert it into the desc. +- // Otherwise, consider it a linebreak. +- if len(line) > 0 { +- currentDoc.Desc += line + " " +- } else { +- currentDoc.Desc += "\n" +- } +- } +- +- // Set the line number of the test +- currentDoc.LineNo = i +- +- // Add the doc to the contract +- contract.Docs = append(contract.Docs, currentDoc) +- } +- } +- +- // Add the contract to the array of docs +- docs = append(docs, contract) +- } +- +- for _, contract := range docs { +- filePath := filepath.Join(docsDir, contract.Name+".md") +- alreadyWritten := slices.Contains(writtenFiles, filePath) +- +- // If the file has already been written, append the extra docs to the end. +- // Otherwise, write the file from scratch. +- var fileContent string +- if alreadyWritten { +- existingContent, err := os.ReadFile(filePath) +- if err != nil { +- return fmt.Errorf("error reading existing file %q: %w", filePath, err) +- } +- fileContent = string(existingContent) + "\n" + renderContractDoc(contract, false) +- } else { +- fileContent = renderContractDoc(contract, true) +- } +- +- err = os.WriteFile(filePath, []byte(fileContent), 0644) +- if err != nil { +- return fmt.Errorf("error writing file %q: %w", filePath, err) +- } +- +- if !alreadyWritten { +- writtenFiles = append(writtenFiles, filePath) +- } +- } +- +- _, _ = fmt.Fprintf(os.Stderr, +- "Generated invariant test documentation for:\n"+ +- " - %d contracts\n"+ +- " - %d invariant tests\n"+ +- "successfully!\n", +- len(docs), +- func() int { +- total := 0 +- for _, contract := range docs { +- total += len(contract.Docs) +- } +- return total +- }(), +- ) +- return nil +-} +- +-// Generate a table of contents for all invariant docs and place it in the README. +-func tocGen(docsDir string) error { +- autoTOCPrefix := "<!-- START autoTOC -->\n" +- autoTOCPostfix := "<!-- END autoTOC -->\n" +- +- files, err := os.ReadDir(docsDir) +- if err != nil { +- return fmt.Errorf("error reading directory %q: %w", docsDir, err) +- } +- +- // Generate a table of contents section. +- var tocList []string +- for _, file := range files { +- fileName := file.Name() +- if fileName != "README.md" { +- tocList = append(tocList, fmt.Sprintf("- [%s](./%s)", strings.Replace(fileName, ".md", "", 1), fileName)) +- } +- } +- toc := fmt.Sprintf("%s\n## Table of Contents\n%s\n%s", +- autoTOCPrefix, strings.Join(tocList, "\n"), autoTOCPostfix) +- +- // Write the table of contents to the README. +- readmePath := filepath.Join(docsDir, "README.md") +- readmeContents, err := os.ReadFile(readmePath) +- if err != nil { +- return fmt.Errorf("error reading README file %q: %w", readmePath, err) +- } +- readmeParts := strings.Split(string(readmeContents), autoTOCPrefix) +- above := readmeParts[0] +- readmeParts = strings.Split(readmeParts[1], autoTOCPostfix) +- below := readmeParts[1] +- err = os.WriteFile(readmePath, []byte(above+toc+below), 0644) +- if err != nil { +- return fmt.Errorf("error writing README file %q: %w", readmePath, err) +- } +- return nil +-} +- +-// Render a `Contract` object into valid markdown. +-func renderContractDoc(contract Contract, header bool) string { +- var sb strings.Builder +- +- if header { +- sb.WriteString(fmt.Sprintf("# `%s` Invariants\n", contract.Name)) +- } +- sb.WriteString("\n") +- +- for i, doc := range contract.Docs { +- line := fmt.Sprintf("%s#L%d", contract.FileName, doc.LineNo) +- sb.WriteString(fmt.Sprintf("## %s\n**Test:** [`%s`](%s%s)\n\n%s", doc.Header, line, BaseInvariantGhUrl, line, doc.Desc)) +- if i != len(contract.Docs)-1 { +- sb.WriteString("\n\n") +- } +- } +- +- return sb.String() +-}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+24
+
-0
+ +
+ +
+
+
diff --git OP/packages/contracts-bedrock/scripts/checks/utils/semver-utils.sh CELO/packages/contracts-bedrock/scripts/checks/utils/semver-utils.sh +new file mode 100755 +index 0000000000000000000000000000000000000000..5f8d80156a45218b8262970c0ad7d9ae6badd167 +--- /dev/null ++++ CELO/packages/contracts-bedrock/scripts/checks/utils/semver-utils.sh +@@ -0,0 +1,24 @@ ++#!/usr/bin/env bash ++set -euo pipefail ++ ++# Function to extract version from contract source as a constant ++extract_constant_version() { ++ local file=$1 ++ grep -o 'string.*constant.*version.*=.*"[^"]*"' "$file" | sed 's/.*"\([^"]*\)".*/\1/' || echo "" ++} ++ ++# Function to extract version from contract source as a function ++extract_function_version() { ++ local file=$1 ++ sed -n '/function.*version()/,/return/p' "$file" | grep -o '"[^"]*"' | sed 's/"//g' || echo "" ++} ++ ++# Function to extract version from either constant or function ++extract_version() { ++ local file=$1 ++ version=$(extract_constant_version "$file") ++ if [ -z "$version" ]; then ++ version=$(extract_function_version "$file") ++ fi ++ echo "$version" ++}
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+9
+
-6
+ +
+ +
+
+
diff --git OP/packages/contracts-bedrock/scripts/fpac/viz/FaultDisputeGameViz.s.sol CELO/packages/contracts-bedrock/scripts/fpac/viz/FaultDisputeGameViz.s.sol +index f03897dd0c26e55af5b8189643f3a15bf578fec3..2e0dd45e4ebefd210c1a88fa4eda9d68550fbffc 100644 +--- OP/packages/contracts-bedrock/scripts/fpac/viz/FaultDisputeGameViz.s.sol ++++ CELO/packages/contracts-bedrock/scripts/fpac/viz/FaultDisputeGameViz.s.sol +@@ -1,17 +1,20 @@ + // SPDX-License-Identifier: MIT + pragma solidity ^0.8.15; +  ++// Testing ++import { FaultDisputeGame_Init } from "test/dispute/FaultDisputeGame.t.sol"; ++ ++// Scripts + import { Script } from "forge-std/Script.sol"; + import { console2 as console } from "forge-std/console2.sol"; +- +-import { FaultDisputeGame_Init } from "test/dispute/FaultDisputeGame.t.sol"; +-import { DisputeGameFactory } from "src/dispute/DisputeGameFactory.sol"; +-import { FaultDisputeGame } from "src/dispute/FaultDisputeGame.sol"; +-import { IFaultDisputeGame } from "src/dispute/interfaces/IFaultDisputeGame.sol"; + import { Process } from "scripts/libraries/Process.sol"; +  ++// Libraries + import "src/dispute/lib/Types.sol"; + import "src/dispute/lib/Errors.sol"; ++ ++// Interfaces ++import { IFaultDisputeGame } from "src/dispute/interfaces/IFaultDisputeGame.sol"; +  + /** + * @title FaultDisputeGameViz +@@ -43,7 +46,7 @@ /** + * @dev Entry point + */ + function remote(address _addr) public { +- gameProxy = FaultDisputeGame(payable(_addr)); ++ gameProxy = IFaultDisputeGame(payable(_addr)); + buildGraph(); + console.log("Saved graph to `./dispute_game.svg"); + }
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+0
+
-1
+ +
+ +
+
+
diff --git OP/packages/contracts-bedrock/scripts/periphery/deploy/DeployPeriphery.s.sol CELO/packages/contracts-bedrock/scripts/periphery/deploy/DeployPeriphery.s.sol +index 856104eb2734713ebd689b44a04974a11187ee53..8f4b86b95d62dac1426ec402ce08f7147f9e6ee7 100644 +--- OP/packages/contracts-bedrock/scripts/periphery/deploy/DeployPeriphery.s.sol ++++ CELO/packages/contracts-bedrock/scripts/periphery/deploy/DeployPeriphery.s.sol +@@ -10,7 +10,6 @@ import { PeripheryDeployConfig } from "scripts/periphery/deploy/PeripheryDeployConfig.s.sol"; +  + import { ProxyAdmin } from "src/universal/ProxyAdmin.sol"; + import { Proxy } from "src/universal/Proxy.sol"; +-import { L1StandardBridge } from "src/L1/L1StandardBridge.sol"; + import { Faucet } from "src/periphery/faucet/Faucet.sol"; + import { Drippie } from "src/periphery/drippie/Drippie.sol"; + import { CheckGelatoLow } from "src/periphery/drippie/dripchecks/CheckGelatoLow.sol";
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+1
+
-1
+ +
+ +
+
+
diff --git OP/packages/contracts-bedrock/scripts/periphery/drippie/ManageDrippie.s.sol CELO/packages/contracts-bedrock/scripts/periphery/drippie/ManageDrippie.s.sol +index 903216b3d16ac57fe580f065a3877c4a074886ac..f37a16f547f92945790c2d721ca9d36d0d8a6647 100644 +--- OP/packages/contracts-bedrock/scripts/periphery/drippie/ManageDrippie.s.sol ++++ CELO/packages/contracts-bedrock/scripts/periphery/drippie/ManageDrippie.s.sol +@@ -4,7 +4,7 @@ + import { console2 as console } from "forge-std/console2.sol"; + import { Script } from "forge-std/Script.sol"; +  +-import { LibString } from "solady/src/utils/LibString.sol"; ++import { LibString } from "@solady/utils/LibString.sol"; +  + import { IAutomate as IGelato } from "gelato/interfaces/IAutomate.sol"; + import { LibDataTypes as GelatoDataTypes } from "gelato/libraries/LibDataTypes.sol";
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+94
+
-0
+ +
+ +
+
+
diff --git OP/packages/contracts-bedrock/src/L1/interfaces/IDataAvailabilityChallenge.sol CELO/packages/contracts-bedrock/src/L1/interfaces/IDataAvailabilityChallenge.sol +new file mode 100644 +index 0000000000000000000000000000000000000000..db3c1680e6c5eaa70681597bed4589a68050f672 +--- /dev/null ++++ CELO/packages/contracts-bedrock/src/L1/interfaces/IDataAvailabilityChallenge.sol +@@ -0,0 +1,94 @@ ++// SPDX-License-Identifier: MIT ++pragma solidity ^0.8.0; ++ ++enum ChallengeStatus { ++ Uninitialized, ++ Active, ++ Resolved, ++ Expired ++} ++ ++enum CommitmentType { ++ Keccak256 ++} ++ ++struct Challenge { ++ address challenger; ++ uint256 lockedBond; ++ uint256 startBlock; ++ uint256 resolvedBlock; ++} ++ ++interface IDataAvailabilityChallenge { ++ error BondTooLow(uint256 balance, uint256 required); ++ error ChallengeExists(); ++ error ChallengeNotActive(); ++ error ChallengeNotExpired(); ++ error ChallengeWindowNotOpen(); ++ error InvalidCommitmentLength(uint8 commitmentType, uint256 expectedLength, uint256 actualLength); ++ error InvalidInputData(bytes providedDataCommitment, bytes expectedCommitment); ++ error InvalidResolverRefundPercentage(uint256 invalidResolverRefundPercentage); ++ error UnknownCommitmentType(uint8 commitmentType); ++ error WithdrawalFailed(); ++ ++ event BalanceChanged(address account, uint256 balance); ++ event ChallengeStatusChanged( ++ uint256 indexed challengedBlockNumber, bytes challengedCommitment, ChallengeStatus status ++ ); ++ event Initialized(uint8 version); ++ event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); ++ event RequiredBondSizeChanged(uint256 challengeWindow); ++ event ResolverRefundPercentageChanged(uint256 resolverRefundPercentage); ++ ++ receive() external payable; ++ ++ function balances(address) external view returns (uint256); ++ function bondSize() external view returns (uint256); ++ function challenge(uint256 challengedBlockNumber, bytes memory challengedCommitment) external payable; ++ function challengeWindow() external view returns (uint256); ++ function deposit() external payable; ++ function fixedResolutionCost() external view returns (uint256); ++ function getChallenge( ++ uint256 challengedBlockNumber, ++ bytes memory challengedCommitment ++ ) ++ external ++ view ++ returns (Challenge memory); ++ function getChallengeStatus( ++ uint256 challengedBlockNumber, ++ bytes memory challengedCommitment ++ ) ++ external ++ view ++ returns (ChallengeStatus); ++ function initialize( ++ address _owner, ++ uint256 _challengeWindow, ++ uint256 _resolveWindow, ++ uint256 _bondSize, ++ uint256 _resolverRefundPercentage ++ ) ++ external; ++ function owner() external view returns (address); ++ function renounceOwnership() external; ++ function resolve( ++ uint256 challengedBlockNumber, ++ bytes memory challengedCommitment, ++ bytes memory resolveData ++ ) ++ external; ++ function resolveWindow() external view returns (uint256); ++ function resolverRefundPercentage() external view returns (uint256); ++ function setBondSize(uint256 _bondSize) external; ++ function setResolverRefundPercentage(uint256 _resolverRefundPercentage) external; ++ function transferOwnership(address newOwner) external; ++ function unlockBond(uint256 challengedBlockNumber, bytes memory challengedCommitment) external; ++ function validateCommitment(bytes memory commitment) external pure; ++ function variableResolutionCost() external view returns (uint256); ++ function variableResolutionCostPrecision() external view returns (uint256); ++ function version() external view returns (string memory); ++ function withdraw() external; ++ ++ function __constructor__() external; ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+23
+
-0
+ +
+ +
+
+
diff --git OP/packages/contracts-bedrock/src/L1/interfaces/IDelayedVetoable.sol CELO/packages/contracts-bedrock/src/L1/interfaces/IDelayedVetoable.sol +new file mode 100644 +index 0000000000000000000000000000000000000000..0bea81fed34b838c8eead99c53dde81947d4e1b1 +--- /dev/null ++++ CELO/packages/contracts-bedrock/src/L1/interfaces/IDelayedVetoable.sol +@@ -0,0 +1,23 @@ ++// SPDX-License-Identifier: MIT ++pragma solidity ^0.8.0; ++ ++interface IDelayedVetoable { ++ error ForwardingEarly(); ++ error Unauthorized(address expected, address actual); ++ ++ event DelayActivated(uint256 delay); ++ event Forwarded(bytes32 indexed callHash, bytes data); ++ event Initiated(bytes32 indexed callHash, bytes data); ++ event Vetoed(bytes32 indexed callHash, bytes data); ++ ++ fallback() external; ++ ++ function delay() external returns (uint256 delay_); ++ function initiator() external returns (address initiator_); ++ function queuedAt(bytes32 callHash) external returns (uint256 queuedAt_); ++ function target() external returns (address target_); ++ function version() external view returns (string memory); ++ function vetoer() external returns (address vetoer_); ++ ++ function __constructor__(address vetoer_, address initiator_, address target_, uint256 operatingDelay_) external; ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+21
+
-0
+ +
+ +
+
+
diff --git OP/packages/contracts-bedrock/src/L1/interfaces/IL1CrossDomainMessenger.sol CELO/packages/contracts-bedrock/src/L1/interfaces/IL1CrossDomainMessenger.sol +new file mode 100644 +index 0000000000000000000000000000000000000000..bb92e723c7c346505a902c8f00df81ae49fe07ac +--- /dev/null ++++ CELO/packages/contracts-bedrock/src/L1/interfaces/IL1CrossDomainMessenger.sol +@@ -0,0 +1,21 @@ ++// SPDX-License-Identifier: MIT ++pragma solidity ^0.8.0; ++ ++import { ICrossDomainMessenger } from "src/universal/interfaces/ICrossDomainMessenger.sol"; ++import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol"; ++import { IOptimismPortal } from "src/L1/interfaces/IOptimismPortal.sol"; ++import { ISystemConfig } from "src/L1/interfaces/ISystemConfig.sol"; ++ ++interface IL1CrossDomainMessenger is ICrossDomainMessenger { ++ function PORTAL() external view returns (address); ++ function initialize( ++ ISuperchainConfig _superchainConfig, ++ IOptimismPortal _portal, ++ ISystemConfig _systemConfig ++ ) ++ external; ++ function portal() external view returns (address); ++ function superchainConfig() external view returns (address); ++ function systemConfig() external view returns (address); ++ function version() external view returns (string memory); ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+40
+
-0
+ +
+ +
+
+
diff --git OP/packages/contracts-bedrock/src/L1/interfaces/IL1ERC721Bridge.sol CELO/packages/contracts-bedrock/src/L1/interfaces/IL1ERC721Bridge.sol +new file mode 100644 +index 0000000000000000000000000000000000000000..fd64f40fe5acd6da78ebd37e0e61cdc8199604dd +--- /dev/null ++++ CELO/packages/contracts-bedrock/src/L1/interfaces/IL1ERC721Bridge.sol +@@ -0,0 +1,40 @@ ++// SPDX-License-Identifier: MIT ++pragma solidity ^0.8.0; ++ ++import { IERC721Bridge } from "src/universal/interfaces/IERC721Bridge.sol"; ++import { ICrossDomainMessenger } from "src/universal/interfaces/ICrossDomainMessenger.sol"; ++import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol"; ++ ++interface IL1ERC721Bridge is IERC721Bridge { ++ function bridgeERC721( ++ address _localToken, ++ address _remoteToken, ++ uint256 _tokenId, ++ uint32 _minGasLimit, ++ bytes memory _extraData ++ ) ++ external; ++ function bridgeERC721To( ++ address _localToken, ++ address _remoteToken, ++ address _to, ++ uint256 _tokenId, ++ uint32 _minGasLimit, ++ bytes memory _extraData ++ ) ++ external; ++ function deposits(address, address, uint256) external view returns (bool); ++ function finalizeBridgeERC721( ++ address _localToken, ++ address _remoteToken, ++ address _from, ++ address _to, ++ uint256 _tokenId, ++ bytes memory _extraData ++ ) ++ external; ++ function initialize(ICrossDomainMessenger _messenger, ISuperchainConfig _superchainConfig) external; ++ function paused() external view returns (bool); ++ function superchainConfig() external view returns (ISuperchainConfig); ++ function version() external view returns (string memory); ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+75
+
-0
+ +
+ +
+
+
diff --git OP/packages/contracts-bedrock/src/L1/interfaces/IL1StandardBridge.sol CELO/packages/contracts-bedrock/src/L1/interfaces/IL1StandardBridge.sol +new file mode 100644 +index 0000000000000000000000000000000000000000..119c8c1f1d8ef778d1fc81e8cddeb0822bbf3190 +--- /dev/null ++++ CELO/packages/contracts-bedrock/src/L1/interfaces/IL1StandardBridge.sol +@@ -0,0 +1,75 @@ ++// SPDX-License-Identifier: MIT ++pragma solidity ^0.8.0; ++ ++import { IStandardBridge } from "src/universal/interfaces/IStandardBridge.sol"; ++import { ICrossDomainMessenger } from "src/universal/interfaces/ICrossDomainMessenger.sol"; ++import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol"; ++import { ISystemConfig } from "src/L1/interfaces/ISystemConfig.sol"; ++ ++interface IL1StandardBridge is IStandardBridge { ++ event ERC20DepositInitiated( ++ address indexed l1Token, ++ address indexed l2Token, ++ address indexed from, ++ address to, ++ uint256 amount, ++ bytes extraData ++ ); ++ event ERC20WithdrawalFinalized( ++ address indexed l1Token, ++ address indexed l2Token, ++ address indexed from, ++ address to, ++ uint256 amount, ++ bytes extraData ++ ); ++ event ETHDepositInitiated(address indexed from, address indexed to, uint256 amount, bytes extraData); ++ event ETHWithdrawalFinalized(address indexed from, address indexed to, uint256 amount, bytes extraData); ++ ++ function depositERC20( ++ address _l1Token, ++ address _l2Token, ++ uint256 _amount, ++ uint32 _minGasLimit, ++ bytes memory _extraData ++ ) ++ external; ++ function depositERC20To( ++ address _l1Token, ++ address _l2Token, ++ address _to, ++ uint256 _amount, ++ uint32 _minGasLimit, ++ bytes memory _extraData ++ ) ++ external; ++ function depositETH(uint32 _minGasLimit, bytes memory _extraData) external payable; ++ function depositETHTo(address _to, uint32 _minGasLimit, bytes memory _extraData) external payable; ++ function finalizeERC20Withdrawal( ++ address _l1Token, ++ address _l2Token, ++ address _from, ++ address _to, ++ uint256 _amount, ++ bytes memory _extraData ++ ) ++ external; ++ function finalizeETHWithdrawal( ++ address _from, ++ address _to, ++ uint256 _amount, ++ bytes memory _extraData ++ ) ++ external ++ payable; ++ function initialize( ++ ICrossDomainMessenger _messenger, ++ ISuperchainConfig _superchainConfig, ++ ISystemConfig _systemConfig ++ ) ++ external; ++ function l2TokenBridge() external view returns (address); ++ function superchainConfig() external view returns (ISuperchainConfig); ++ function systemConfig() external view returns (ISystemConfig); ++ function version() external view returns (string memory); ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+55
+
-0
+ +
+ +
+
+
diff --git OP/packages/contracts-bedrock/src/L1/interfaces/IL2OutputOracle.sol CELO/packages/contracts-bedrock/src/L1/interfaces/IL2OutputOracle.sol +new file mode 100644 +index 0000000000000000000000000000000000000000..408c53c8515645cd6cbd6e6902a25071f4300fd9 +--- /dev/null ++++ CELO/packages/contracts-bedrock/src/L1/interfaces/IL2OutputOracle.sol +@@ -0,0 +1,55 @@ ++// SPDX-License-Identifier: MIT ++pragma solidity ^0.8.0; ++ ++import { Types } from "src/libraries/Types.sol"; ++ ++interface IL2OutputOracle { ++ event Initialized(uint8 version); ++ event OutputProposed( ++ bytes32 indexed outputRoot, uint256 indexed l2OutputIndex, uint256 indexed l2BlockNumber, uint256 l1Timestamp ++ ); ++ event OutputsDeleted(uint256 indexed prevNextOutputIndex, uint256 indexed newNextOutputIndex); ++ ++ function CHALLENGER() external view returns (address); ++ function FINALIZATION_PERIOD_SECONDS() external view returns (uint256); ++ function L2_BLOCK_TIME() external view returns (uint256); ++ function PROPOSER() external view returns (address); ++ function SUBMISSION_INTERVAL() external view returns (uint256); ++ function challenger() external view returns (address); ++ function computeL2Timestamp(uint256 _l2BlockNumber) external view returns (uint256); ++ function deleteL2Outputs(uint256 _l2OutputIndex) external; ++ function finalizationPeriodSeconds() external view returns (uint256); ++ function getL2Output(uint256 _l2OutputIndex) external view returns (Types.OutputProposal memory); ++ function getL2OutputAfter(uint256 _l2BlockNumber) external view returns (Types.OutputProposal memory); ++ function getL2OutputIndexAfter(uint256 _l2BlockNumber) external view returns (uint256); ++ function initialize( ++ uint256 _submissionInterval, ++ uint256 _l2BlockTime, ++ uint256 _startingBlockNumber, ++ uint256 _startingTimestamp, ++ address _proposer, ++ address _challenger, ++ uint256 _finalizationPeriodSeconds ++ ) ++ external; ++ function l2BlockTime() external view returns (uint256); ++ function latestBlockNumber() external view returns (uint256); ++ function latestOutputIndex() external view returns (uint256); ++ function nextBlockNumber() external view returns (uint256); ++ function nextOutputIndex() external view returns (uint256); ++ function proposeL2Output( ++ bytes32 _outputRoot, ++ uint256 _l2BlockNumber, ++ bytes32 _l1BlockHash, ++ uint256 _l1BlockNumber ++ ) ++ external ++ payable; ++ function proposer() external view returns (address); ++ function startingBlockNumber() external view returns (uint256); ++ function startingTimestamp() external view returns (uint256); ++ function submissionInterval() external view returns (uint256); ++ function version() external view returns (string memory); ++ ++ function __constructor__() external; ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+85
+
-0
+ +
+ +
+
+
diff --git OP/packages/contracts-bedrock/src/L1/interfaces/IOptimismPortal.sol CELO/packages/contracts-bedrock/src/L1/interfaces/IOptimismPortal.sol +new file mode 100644 +index 0000000000000000000000000000000000000000..e80bad00b910a907f4b0c7c952bef86d83d5c334 +--- /dev/null ++++ CELO/packages/contracts-bedrock/src/L1/interfaces/IOptimismPortal.sol +@@ -0,0 +1,85 @@ ++// SPDX-License-Identifier: MIT ++pragma solidity ^0.8.0; ++ ++import { Types } from "src/libraries/Types.sol"; ++import { ISystemConfig } from "src/L1/interfaces/ISystemConfig.sol"; ++import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol"; ++import { IL2OutputOracle } from "src/L1/interfaces/IL2OutputOracle.sol"; ++ ++interface IOptimismPortal { ++ error BadTarget(); ++ error CallPaused(); ++ error ContentLengthMismatch(); ++ error EmptyItem(); ++ error GasEstimation(); ++ error InvalidDataRemainder(); ++ error InvalidHeader(); ++ error LargeCalldata(); ++ error NoValue(); ++ error NonReentrant(); ++ error OnlyCustomGasToken(); ++ error OutOfGas(); ++ error SmallGasLimit(); ++ error TransferFailed(); ++ error Unauthorized(); ++ error UnexpectedList(); ++ error UnexpectedString(); ++ ++ event Initialized(uint8 version); ++ event TransactionDeposited(address indexed from, address indexed to, uint256 indexed version, bytes opaqueData); ++ event WithdrawalFinalized(bytes32 indexed withdrawalHash, bool success); ++ event WithdrawalProven(bytes32 indexed withdrawalHash, address indexed from, address indexed to); ++ ++ receive() external payable; ++ ++ function balance() external view returns (uint256); ++ function depositERC20Transaction( ++ address _to, ++ uint256 _mint, ++ uint256 _value, ++ uint64 _gasLimit, ++ bool _isCreation, ++ bytes memory _data ++ ) ++ external; ++ function depositTransaction( ++ address _to, ++ uint256 _value, ++ uint64 _gasLimit, ++ bool _isCreation, ++ bytes memory _data ++ ) ++ external ++ payable; ++ function donateETH() external payable; ++ function finalizeWithdrawalTransaction(Types.WithdrawalTransaction memory _tx) external; ++ function finalizedWithdrawals(bytes32) external view returns (bool); ++ function guardian() external view returns (address); ++ function initialize( ++ IL2OutputOracle _l2Oracle, ++ ISystemConfig _systemConfig, ++ ISuperchainConfig _superchainConfig ++ ) ++ external; ++ function isOutputFinalized(uint256 _l2OutputIndex) external view returns (bool); ++ function l2Oracle() external view returns (IL2OutputOracle); ++ function l2Sender() external view returns (address); ++ function minimumGasLimit(uint64 _byteCount) external pure returns (uint64); ++ function params() external view returns (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum); ++ function paused() external view returns (bool paused_); ++ function proveWithdrawalTransaction( ++ Types.WithdrawalTransaction memory _tx, ++ uint256 _l2OutputIndex, ++ Types.OutputRootProof memory _outputRootProof, ++ bytes[] memory _withdrawalProof ++ ) ++ external; ++ function provenWithdrawals(bytes32) ++ external ++ view ++ returns (bytes32 outputRoot, uint128 timestamp, uint128 l2OutputIndex); ++ function setGasPayingToken(address _token, uint8 _decimals, bytes32 _name, bytes32 _symbol) external; ++ function superchainConfig() external view returns (ISuperchainConfig); ++ function systemConfig() external view returns (ISystemConfig); ++ function version() external pure returns (string memory); ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+118
+
-0
+ +
+ +
+
+
diff --git OP/packages/contracts-bedrock/src/L1/interfaces/IOptimismPortal2.sol CELO/packages/contracts-bedrock/src/L1/interfaces/IOptimismPortal2.sol +new file mode 100644 +index 0000000000000000000000000000000000000000..551bd2832b055d15d78ebfef5f23e2caa50a6faa +--- /dev/null ++++ CELO/packages/contracts-bedrock/src/L1/interfaces/IOptimismPortal2.sol +@@ -0,0 +1,118 @@ ++// SPDX-License-Identifier: MIT ++pragma solidity ^0.8.0; ++ ++import { Types } from "src/libraries/Types.sol"; ++import { GameType, Timestamp } from "src/dispute/lib/LibUDT.sol"; ++import { IDisputeGame } from "src/dispute/interfaces/IDisputeGame.sol"; ++import { IDisputeGameFactory } from "src/dispute/interfaces/IDisputeGameFactory.sol"; ++import { ISystemConfig } from "src/L1/interfaces/ISystemConfig.sol"; ++import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol"; ++ ++interface IOptimismPortal2 { ++ error AlreadyFinalized(); ++ error BadTarget(); ++ error Blacklisted(); ++ error CallPaused(); ++ error ContentLengthMismatch(); ++ error EmptyItem(); ++ error GasEstimation(); ++ error InvalidDataRemainder(); ++ error InvalidDisputeGame(); ++ error InvalidGameType(); ++ error InvalidHeader(); ++ error InvalidMerkleProof(); ++ error InvalidProof(); ++ error LargeCalldata(); ++ error NoValue(); ++ error NonReentrant(); ++ error OnlyCustomGasToken(); ++ error OutOfGas(); ++ error ProposalNotValidated(); ++ error SmallGasLimit(); ++ error TransferFailed(); ++ error Unauthorized(); ++ error UnexpectedList(); ++ error UnexpectedString(); ++ error Unproven(); ++ ++ event DisputeGameBlacklisted(IDisputeGame indexed disputeGame); ++ event Initialized(uint8 version); ++ event RespectedGameTypeSet(GameType indexed newGameType, Timestamp indexed updatedAt); ++ event TransactionDeposited(address indexed from, address indexed to, uint256 indexed version, bytes opaqueData); ++ event WithdrawalFinalized(bytes32 indexed withdrawalHash, bool success); ++ event WithdrawalProven(bytes32 indexed withdrawalHash, address indexed from, address indexed to); ++ event WithdrawalProvenExtension1(bytes32 indexed withdrawalHash, address indexed proofSubmitter); ++ ++ receive() external payable; ++ ++ function balance() external view returns (uint256); ++ function blacklistDisputeGame(IDisputeGame _disputeGame) external; ++ function checkWithdrawal(bytes32 _withdrawalHash, address _proofSubmitter) external view; ++ function depositERC20Transaction( ++ address _to, ++ uint256 _mint, ++ uint256 _value, ++ uint64 _gasLimit, ++ bool _isCreation, ++ bytes memory _data ++ ) ++ external; ++ function depositTransaction( ++ address _to, ++ uint256 _value, ++ uint64 _gasLimit, ++ bool _isCreation, ++ bytes memory _data ++ ) ++ external ++ payable; ++ function disputeGameBlacklist(IDisputeGame) external view returns (bool); ++ function disputeGameFactory() external view returns (IDisputeGameFactory); ++ function disputeGameFinalityDelaySeconds() external view returns (uint256); ++ function donateETH() external payable; ++ function finalizeWithdrawalTransaction(Types.WithdrawalTransaction memory _tx) external; ++ function finalizeWithdrawalTransactionExternalProof( ++ Types.WithdrawalTransaction memory _tx, ++ address _proofSubmitter ++ ) ++ external; ++ function finalizedWithdrawals(bytes32) external view returns (bool); ++ function guardian() external view returns (address); ++ function initialize( ++ IDisputeGameFactory _disputeGameFactory, ++ ISystemConfig _systemConfig, ++ ISuperchainConfig _superchainConfig, ++ GameType _initialRespectedGameType ++ ) ++ external; ++ function l2Sender() external view returns (address); ++ function minimumGasLimit(uint64 _byteCount) external pure returns (uint64); ++ function numProofSubmitters(bytes32 _withdrawalHash) external view returns (uint256); ++ function params() external view returns (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum); ++ function paused() external view returns (bool); ++ function proofMaturityDelaySeconds() external view returns (uint256); ++ function proofSubmitters(bytes32, uint256) external view returns (address); ++ function proveWithdrawalTransaction( ++ Types.WithdrawalTransaction memory _tx, ++ uint256 _disputeGameIndex, ++ Types.OutputRootProof memory _outputRootProof, ++ bytes[] memory _withdrawalProof ++ ) ++ external; ++ function provenWithdrawals( ++ bytes32, ++ address ++ ) ++ external ++ view ++ returns (IDisputeGame disputeGameProxy, uint64 timestamp); ++ function respectedGameType() external view returns (GameType); ++ function respectedGameTypeUpdatedAt() external view returns (uint64); ++ function setGasPayingToken(address _token, uint8 _decimals, bytes32 _name, bytes32 _symbol) external; ++ function setRespectedGameType(GameType _gameType) external; ++ function superchainConfig() external view returns (ISuperchainConfig); ++ function systemConfig() external view returns (ISystemConfig); ++ function version() external pure returns (string memory); ++ ++ function __constructor__(uint256 _proofMaturityDelaySeconds, uint256 _disputeGameFinalityDelaySeconds) external; ++}
@@ -24265,7 +125321,7 @@
@@ -24275,89 +125331,138 @@
-
+71
+
+120
-0
-
diff --git OP/op-e2e/celo/src/chain.js CELO/op-e2e/celo/src/chain.js +
diff --git OP/packages/contracts-bedrock/src/L1/interfaces/IOptimismPortalInterop.sol CELO/packages/contracts-bedrock/src/L1/interfaces/IOptimismPortalInterop.sol new file mode 100644 -index 0000000000000000000000000000000000000000..25dac875054ddd90fd871937d6ee39946c60f81b +index 0000000000000000000000000000000000000000..682518897362ad2ab99e20894678adea78d83ab6 --- /dev/null -+++ CELO/op-e2e/celo/src/chain.js -@@ -0,0 +1,71 @@ -+import { chainConfig } from 'viem/op-stack' -+import { defineChain } from 'viem' ++++ CELO/packages/contracts-bedrock/src/L1/interfaces/IOptimismPortalInterop.sol +@@ -0,0 +1,120 @@ ++// SPDX-License-Identifier: MIT ++pragma solidity ^0.8.0; + -+export function makeChainConfigs(l1ChainID, l2ChainID, contractAddresses) { -+ console.log(process.env) -+ return { -+ l2: defineChain({ -+ formatters: { -+ ...chainConfig.formatters, -+ }, -+ serializers: { -+ ...chainConfig.serializers, -+ }, -+ id: l2ChainID, -+ name: 'Celo', -+ nativeCurrency: { -+ decimals: 18, -+ name: 'Celo - native currency', -+ symbol: 'CELO', -+ }, -+ rpcUrls: { -+ default: { -+ http: [process.env.ETH_RPC_URL], -+ }, -+ }, -+ contracts: { -+ ...chainConfig.contracts, -+ l2OutputOracle: { -+ [l1ChainID]: { -+ address: contractAddresses.L2OutputOracleProxy, -+ }, -+ }, -+ disputeGameFactory: { -+ [l1ChainID]: { -+ address: contractAddresses.DisputeGameFactoryProxy, -+ }, -+ }, -+ portal: { -+ [l1ChainID]: { -+ address: contractAddresses.OptimismPortalProxy, -+ }, -+ }, -+ l1StandardBridge: { -+ [l1ChainID]: { -+ address: contractAddresses.L1StandardBridgeProxy, -+ }, -+ }, -+ }, -+ }), -+ l1: defineChain({ -+ id: l1ChainID, -+ testnet: true, -+ name: 'Ethereum L1', -+ nativeCurrency: { -+ decimals: 18, -+ name: 'Ether', -+ symbol: 'ETH', -+ }, -+ rpcUrls: { -+ default: { -+ http: [process.env.ETH_RPC_URL_L1], -+ }, -+ }, -+ contracts: { -+ multicall3: { -+ address: contractAddresses.Multicall3, -+ }, -+ }, -+ }), -+ } ++import { Types } from "src/libraries/Types.sol"; ++import { GameType, Timestamp } from "src/dispute/lib/LibUDT.sol"; ++import { IDisputeGame } from "src/dispute/interfaces/IDisputeGame.sol"; ++import { IDisputeGameFactory } from "src/dispute/interfaces/IDisputeGameFactory.sol"; ++import { ISystemConfig } from "src/L1/interfaces/ISystemConfig.sol"; ++import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol"; ++import { ConfigType } from "src/L2/L1BlockIsthmus.sol"; ++ ++interface IOptimismPortalInterop { ++ error AlreadyFinalized(); ++ error BadTarget(); ++ error Blacklisted(); ++ error CallPaused(); ++ error ContentLengthMismatch(); ++ error EmptyItem(); ++ error GasEstimation(); ++ error InvalidDataRemainder(); ++ error InvalidDisputeGame(); ++ error InvalidGameType(); ++ error InvalidHeader(); ++ error InvalidMerkleProof(); ++ error InvalidProof(); ++ error LargeCalldata(); ++ error NoValue(); ++ error NonReentrant(); ++ error OnlyCustomGasToken(); ++ error OutOfGas(); ++ error ProposalNotValidated(); ++ error SmallGasLimit(); ++ error TransferFailed(); ++ error Unauthorized(); ++ error UnexpectedList(); ++ error UnexpectedString(); ++ error Unproven(); ++ ++ event DisputeGameBlacklisted(IDisputeGame indexed disputeGame); ++ event Initialized(uint8 version); ++ event RespectedGameTypeSet(GameType indexed newGameType, Timestamp indexed updatedAt); ++ event TransactionDeposited(address indexed from, address indexed to, uint256 indexed version, bytes opaqueData); ++ event WithdrawalFinalized(bytes32 indexed withdrawalHash, bool success); ++ event WithdrawalProven(bytes32 indexed withdrawalHash, address indexed from, address indexed to); ++ event WithdrawalProvenExtension1(bytes32 indexed withdrawalHash, address indexed proofSubmitter); ++ ++ receive() external payable; ++ ++ function balance() external view returns (uint256); ++ function blacklistDisputeGame(IDisputeGame _disputeGame) external; ++ function checkWithdrawal(bytes32 _withdrawalHash, address _proofSubmitter) external view; ++ function depositERC20Transaction( ++ address _to, ++ uint256 _mint, ++ uint256 _value, ++ uint64 _gasLimit, ++ bool _isCreation, ++ bytes memory _data ++ ) ++ external; ++ function depositTransaction( ++ address _to, ++ uint256 _value, ++ uint64 _gasLimit, ++ bool _isCreation, ++ bytes memory _data ++ ) ++ external ++ payable; ++ function disputeGameBlacklist(IDisputeGame) external view returns (bool); ++ function disputeGameFactory() external view returns (IDisputeGameFactory); ++ function disputeGameFinalityDelaySeconds() external view returns (uint256); ++ function donateETH() external payable; ++ function finalizeWithdrawalTransaction(Types.WithdrawalTransaction memory _tx) external; ++ function finalizeWithdrawalTransactionExternalProof( ++ Types.WithdrawalTransaction memory _tx, ++ address _proofSubmitter ++ ) ++ external; ++ function finalizedWithdrawals(bytes32) external view returns (bool); ++ function guardian() external view returns (address); ++ function initialize( ++ IDisputeGameFactory _disputeGameFactory, ++ ISystemConfig _systemConfig, ++ ISuperchainConfig _superchainConfig, ++ GameType _initialRespectedGameType ++ ) ++ external; ++ function l2Sender() external view returns (address); ++ function minimumGasLimit(uint64 _byteCount) external pure returns (uint64); ++ function numProofSubmitters(bytes32 _withdrawalHash) external view returns (uint256); ++ function params() external view returns (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum); ++ function paused() external view returns (bool); ++ function proofMaturityDelaySeconds() external view returns (uint256); ++ function proofSubmitters(bytes32, uint256) external view returns (address); ++ function proveWithdrawalTransaction( ++ Types.WithdrawalTransaction memory _tx, ++ uint256 _disputeGameIndex, ++ Types.OutputRootProof memory _outputRootProof, ++ bytes[] memory _withdrawalProof ++ ) ++ external; ++ function provenWithdrawals( ++ bytes32, ++ address ++ ) ++ external ++ view ++ returns (IDisputeGame disputeGameProxy, uint64 timestamp); ++ function respectedGameType() external view returns (GameType); ++ function respectedGameTypeUpdatedAt() external view returns (uint64); ++ function setConfig(ConfigType _type, bytes memory _value) external; ++ function setGasPayingToken(address _token, uint8 _decimals, bytes32 _name, bytes32 _symbol) external; ++ function setRespectedGameType(GameType _gameType) external; ++ function superchainConfig() external view returns (ISuperchainConfig); ++ function systemConfig() external view returns (ISystemConfig); ++ function version() external pure returns (string memory); ++ ++ function __constructor__(uint256 _proofMaturityDelaySeconds, uint256 _disputeGameFinalityDelaySeconds) external; +}
@@ -24365,9 +125470,9 @@
@@ -24382,7 +125487,7 @@
@@ -24392,116 +125497,119 @@
-
+98
+
+30
-0
-
diff --git OP/op-e2e/celo/src/config.js CELO/op-e2e/celo/src/config.js +
diff --git OP/packages/contracts-bedrock/src/L1/interfaces/IProtocolVersions.sol CELO/packages/contracts-bedrock/src/L1/interfaces/IProtocolVersions.sol new file mode 100644 -index 0000000000000000000000000000000000000000..7e410dffbdd0de20f4dc8b781d6aabcd21f7448f +index 0000000000000000000000000000000000000000..aa2de51d48464c174f6192066ed6f12ff464f410 --- /dev/null -+++ CELO/op-e2e/celo/src/config.js -@@ -0,0 +1,98 @@ -+import { createPublicClient, createWalletClient, http } from 'viem' -+import { readContract } from 'viem/actions' -+import { constructDepositCustomGas } from './deposit.js' -+import { -+ getERC20, -+ simulateERC20Transfer, -+ getERC20BalanceOf, -+ getERC20Symbol, -+ getERC20Decimals, -+ simulateERC20Approve, -+} from 'reverse-mirage' -+import { -+ publicActionsL1, -+ publicActionsL2, -+ walletActionsL1, -+ walletActionsL2, -+} from 'viem/op-stack' ++++ CELO/packages/contracts-bedrock/src/L1/interfaces/IProtocolVersions.sol +@@ -0,0 +1,30 @@ ++// SPDX-License-Identifier: MIT ++pragma solidity ^0.8.0; + -+export function makeReadContract(contractAddress, contractABI) { -+ return (client) => { -+ return { -+ readContract: (args) => { -+ const rcArgs = { -+ address: contractAddress, -+ abi: contractABI, -+ functionName: args.functionName, -+ args: args.args, -+ } -+ return readContract(client, rcArgs) -+ }, ++type ProtocolVersion is uint256; ++ ++interface IProtocolVersions { ++ enum UpdateType { ++ REQUIRED_PROTOCOL_VERSION, ++ RECOMMENDED_PROTOCOL_VERSION + } -+ } -+} + -+export function erc20PublicActions(client) { -+ return { -+ getERC20: (args) => getERC20(client, args), -+ getERC20Symbol: (args) => getERC20Symbol(client, args), -+ getERC20BalanceOf: (args) => getERC20BalanceOf(client, args), -+ getERC20Decimals: (args) => getERC20Decimals(client, args), -+ } -+} -+export function erc20WalletActions(client) { -+ return { -+ simulateERC20Transfer: (args) => { -+ return simulateERC20Transfer(client, { args: args }) -+ }, -+ simulateERC20Approve: (args) => { -+ return simulateERC20Approve(client, { args: args }) -+ }, -+ } -+} ++ event ConfigUpdate(uint256 indexed version, UpdateType indexed updateType, bytes data); ++ event Initialized(uint8 version); ++ event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); ++ ++ function RECOMMENDED_SLOT() external view returns (bytes32); ++ function REQUIRED_SLOT() external view returns (bytes32); ++ function VERSION() external view returns (uint256); ++ function initialize(address _owner, ProtocolVersion _required, ProtocolVersion _recommended) external; ++ function owner() external view returns (address); ++ function recommended() external view returns (ProtocolVersion out_); ++ function renounceOwnership() external; ++ function required() external view returns (ProtocolVersion out_); ++ function setRecommended(ProtocolVersion _recommended) external; ++ function setRequired(ProtocolVersion _required) external; ++ function transferOwnership(address newOwner) external; ++ function version() external view returns (string memory); ++ ++ function __constructor__() external; ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+25
+
-0
+ +
+ +
+
+
diff --git OP/packages/contracts-bedrock/src/L1/interfaces/IResourceMetering.sol CELO/packages/contracts-bedrock/src/L1/interfaces/IResourceMetering.sol +new file mode 100644 +index 0000000000000000000000000000000000000000..4a4ccc133bb86c6b41232cba44072e0910226735 +--- /dev/null ++++ CELO/packages/contracts-bedrock/src/L1/interfaces/IResourceMetering.sol +@@ -0,0 +1,25 @@ ++// SPDX-License-Identifier: MIT ++pragma solidity ^0.8.0; + -+export function celoL1PublicActions(client) { -+ return { -+ prepareDepositGasPayingTokenERC20: (args) => { -+ return constructDepositCustomGas(client, args) -+ }, -+ } -+} ++interface IResourceMetering { ++ struct ResourceParams { ++ uint128 prevBaseFee; ++ uint64 prevBoughtGas; ++ uint64 prevBlockNum; ++ } + -+export function setupClients(l1ChainConfig, l2ChainConfig, account) { -+ return { -+ l1: { -+ public: createPublicClient({ -+ account, -+ chain: l1ChainConfig, -+ transport: http(), -+ }) -+ .extend(publicActionsL1()) -+ .extend(celoL1PublicActions) -+ .extend(erc20PublicActions), -+ wallet: createWalletClient({ -+ account, -+ chain: l1ChainConfig, -+ transport: http(), -+ }) -+ .extend(erc20WalletActions) -+ .extend(walletActionsL1()), -+ }, -+ l2: { -+ public: createPublicClient({ -+ account, -+ chain: l2ChainConfig, -+ transport: http(), -+ }) -+ .extend(publicActionsL2()) -+ .extend(erc20PublicActions), -+ wallet: createWalletClient({ -+ account, -+ chain: l2ChainConfig, -+ transport: http(), -+ }) -+ .extend(erc20WalletActions) -+ .extend(walletActionsL2()), -+ }, -+ } ++ struct ResourceConfig { ++ uint32 maxResourceLimit; ++ uint8 elasticityMultiplier; ++ uint8 baseFeeMaxChangeDenominator; ++ uint32 minimumBaseFee; ++ uint32 systemTxMaxGas; ++ uint128 maximumBaseFee; ++ } ++ ++ error OutOfGas(); ++ ++ event Initialized(uint8 version); ++ ++ function params() external view returns (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum); +}
@@ -24509,9 +125617,9 @@
@@ -24526,7 +125634,7 @@
@@ -24536,145 +125644,360 @@
-
+127
+
+24
-0
-
diff --git OP/op-e2e/celo/src/deposit.js CELO/op-e2e/celo/src/deposit.js +
diff --git OP/packages/contracts-bedrock/src/L1/interfaces/ISuperchainConfig.sol CELO/packages/contracts-bedrock/src/L1/interfaces/ISuperchainConfig.sol new file mode 100644 -index 0000000000000000000000000000000000000000..2e1f5ef17dbdf0eadd4fba293eba79712a1fd0b2 +index 0000000000000000000000000000000000000000..dc83893958b09910f04bb14875a3505fac82d12c --- /dev/null -+++ CELO/op-e2e/celo/src/deposit.js -@@ -0,0 +1,127 @@ -+import { getL2TransactionHashes } from 'viem/op-stack' -+import { OptimismPortalABI } from './OptimismPortal.js' ++++ CELO/packages/contracts-bedrock/src/L1/interfaces/ISuperchainConfig.sol +@@ -0,0 +1,24 @@ ++// SPDX-License-Identifier: MIT ++pragma solidity ^0.8.0; + -+// public client functionality -+export async function constructDepositCustomGas(client, parameters) { -+ const { -+ account, -+ chain = client.chain, -+ gas, -+ maxFeePerGas, -+ maxPriorityFeePerGas, -+ nonce, -+ request: { -+ data = '0x', -+ gas: l2Gas, -+ isCreation = false, -+ mint, -+ to = '0x', -+ value, -+ }, -+ targetChain, -+ } = parameters ++interface ISuperchainConfig { ++ enum UpdateType { ++ GUARDIAN ++ } + -+ const portalAddress = (() => { -+ if (parameters.portalAddress) return parameters.portalAddress -+ if (chain) return targetChain.contracts.portal[chain.id].address -+ return Object.values(targetChain.contracts.portal)[0].address -+ })() -+ const callArgs = { -+ account: account, -+ abi: OptimismPortalABI, -+ address: portalAddress, -+ chain, -+ functionName: 'depositERC20Transaction', -+ /// @notice Entrypoint to depositing an ERC20 token as a custom gas token. -+ /// This function depends on a well formed ERC20 token. There are only -+ /// so many checks that can be done on chain for this so it is assumed -+ /// that chain operators will deploy chains with well formed ERC20 tokens. -+ /// @param _to Target address on L2. -+ /// @param _mint Units of ERC20 token to deposit into L2. -+ /// @param _value Units of ERC20 token to send on L2 to the recipient. -+ /// @param _gasLimit Amount of L2 gas to purchase by burning gas on L1. -+ /// @param _isCreation Whether or not the transaction is a contract creation. -+ /// @param _data Data to trigger the recipient with. -+ args: [ -+ isCreation ? zeroAddress : to, -+ mint ?? value ?? 0n, -+ value ?? mint ?? 0n, -+ l2Gas, -+ isCreation, -+ data, -+ ], -+ maxFeePerGas, -+ maxPriorityFeePerGas, -+ nonce, -+ } -+ const gas_ = -+ typeof gas !== 'number' && gas !== null -+ ? await client.estimateContractGas(callArgs) -+ : undefined -+ callArgs.gas = gas_ -+ const result = client.simulateContract(callArgs) -+ return { result: result, args: callArgs } -+} ++ event ConfigUpdate(UpdateType indexed updateType, bytes data); ++ event Initialized(uint8 version); ++ event Paused(string identifier); ++ event Unpaused(); ++ ++ function GUARDIAN_SLOT() external view returns (bytes32); ++ function PAUSED_SLOT() external view returns (bytes32); ++ function guardian() external view returns (address guardian_); ++ function initialize(address _guardian, bool _paused) external; ++ function pause(string memory _identifier) external; ++ function paused() external view returns (bool paused_); ++ function unpause() external; ++ function version() external view returns (string memory); ++ ++ function __constructor__() external; ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+83
+
-0
+ +
+ +
+
+
diff --git OP/packages/contracts-bedrock/src/L1/interfaces/ISystemConfig.sol CELO/packages/contracts-bedrock/src/L1/interfaces/ISystemConfig.sol +new file mode 100644 +index 0000000000000000000000000000000000000000..59ae98668cf076f2edfd4fcdc4544018a5f6cbe1 +--- /dev/null ++++ CELO/packages/contracts-bedrock/src/L1/interfaces/ISystemConfig.sol +@@ -0,0 +1,83 @@ ++// SPDX-License-Identifier: MIT ++pragma solidity ^0.8.0; + -+export async function deposit(args, config) { -+ var spentGas = BigInt(0) -+ const depositArgs = await config.client.l2.public.buildDepositTransaction({ -+ mint: args.mint, -+ to: args.to, -+ }) ++import { IResourceMetering } from "src/L1/interfaces/IResourceMetering.sol"; + -+ const celoToken = await config.client.l1.public.getERC20({ -+ erc20: { -+ address: config.addresses.CustomGasTokenProxy, -+ chainID: config.client.l1.public.chain.id, -+ }, -+ }) -+ const portalAddress = -+ config.client.l2.public.chain.contracts.portal[ -+ config.client.l1.public.chain.id -+ ].address -+ const approve = await config.client.l1.wallet.simulateERC20Approve({ -+ amount: { amount: args.mint, token: celoToken }, -+ spender: portalAddress, -+ }) -+ if (!approve.result) { -+ return { -+ success: false, -+ l1GasPayment: spentGas, ++interface ISystemConfig { ++ enum UpdateType { ++ BATCHER, ++ GAS_CONFIG, ++ GAS_LIMIT, ++ UNSAFE_BLOCK_SIGNER + } -+ } -+ -+ const approveHash = await config.client.l1.wallet.writeContract( -+ approve.request -+ ) -+ // Wait for the L1 transaction to be processed. -+ const approveReceipt = -+ await config.client.l1.public.waitForTransactionReceipt({ -+ hash: approveHash, -+ }) + -+ spentGas += approveReceipt.gasUsed * approveReceipt.effectiveGasPrice -+ const dep = -+ await config.client.l1.public.prepareDepositGasPayingTokenERC20(depositArgs) -+ const hash = await config.client.l1.wallet.writeContract(dep.args) ++ struct Addresses { ++ address l1CrossDomainMessenger; ++ address l1ERC721Bridge; ++ address l1StandardBridge; ++ address disputeGameFactory; ++ address optimismPortal; ++ address optimismMintableERC20Factory; ++ address gasPayingToken; ++ } + -+ // Wait for the L1 transaction to be processed. -+ const receipt = await config.client.l1.public.waitForTransactionReceipt({ -+ hash: hash, -+ }) ++ event ConfigUpdate(uint256 indexed version, UpdateType indexed updateType, bytes data); ++ event Initialized(uint8 version); ++ event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); ++ ++ function BATCH_INBOX_SLOT() external view returns (bytes32); ++ function DISPUTE_GAME_FACTORY_SLOT() external view returns (bytes32); ++ function L1_CROSS_DOMAIN_MESSENGER_SLOT() external view returns (bytes32); ++ function L1_ERC_721_BRIDGE_SLOT() external view returns (bytes32); ++ function L1_STANDARD_BRIDGE_SLOT() external view returns (bytes32); ++ function OPTIMISM_MINTABLE_ERC20_FACTORY_SLOT() external view returns (bytes32); ++ function OPTIMISM_PORTAL_SLOT() external view returns (bytes32); ++ function START_BLOCK_SLOT() external view returns (bytes32); ++ function UNSAFE_BLOCK_SIGNER_SLOT() external view returns (bytes32); ++ function VERSION() external view returns (uint256); ++ function basefeeScalar() external view returns (uint32); ++ function batchInbox() external view returns (address addr_); ++ function batcherHash() external view returns (bytes32); ++ function blobbasefeeScalar() external view returns (uint32); ++ function disputeGameFactory() external view returns (address addr_); ++ function gasLimit() external view returns (uint64); ++ function gasPayingToken() external view returns (address addr_, uint8 decimals_); ++ function gasPayingTokenName() external view returns (string memory name_); ++ function gasPayingTokenSymbol() external view returns (string memory symbol_); ++ function initialize( ++ address _owner, ++ uint32 _basefeeScalar, ++ uint32 _blobbasefeeScalar, ++ bytes32 _batcherHash, ++ uint64 _gasLimit, ++ address _unsafeBlockSigner, ++ IResourceMetering.ResourceConfig memory _config, ++ address _batchInbox, ++ Addresses memory _addresses ++ ) ++ external; ++ function isCustomGasToken() external view returns (bool); ++ function l1CrossDomainMessenger() external view returns (address addr_); ++ function l1ERC721Bridge() external view returns (address addr_); ++ function l1StandardBridge() external view returns (address addr_); ++ function maximumGasLimit() external pure returns (uint64); ++ function minimumGasLimit() external view returns (uint64); ++ function optimismMintableERC20Factory() external view returns (address addr_); ++ function optimismPortal() external view returns (address addr_); ++ function overhead() external view returns (uint256); ++ function owner() external view returns (address); ++ function renounceOwnership() external; ++ function resourceConfig() external view returns (IResourceMetering.ResourceConfig memory); ++ function scalar() external view returns (uint256); ++ function setBatcherHash(bytes32 _batcherHash) external; ++ function setGasConfig(uint256 _overhead, uint256 _scalar) external; ++ function setGasConfigEcotone(uint32 _basefeeScalar, uint32 _blobbasefeeScalar) external; ++ function setGasLimit(uint64 _gasLimit) external; ++ function setUnsafeBlockSigner(address _unsafeBlockSigner) external; ++ function startBlock() external view returns (uint256 startBlock_); ++ function transferOwnership(address newOwner) external; ++ function unsafeBlockSigner() external view returns (address addr_); ++ function version() external pure returns (string memory); ++ ++ function __constructor__() external; ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+82
+
-0
+ +
+ +
+
+
diff --git OP/packages/contracts-bedrock/src/L1/interfaces/ISystemConfigInterop.sol CELO/packages/contracts-bedrock/src/L1/interfaces/ISystemConfigInterop.sol +new file mode 100644 +index 0000000000000000000000000000000000000000..cffa30dd3efc0dbcf326e8a4c2220dfc4c270063 +--- /dev/null ++++ CELO/packages/contracts-bedrock/src/L1/interfaces/ISystemConfigInterop.sol +@@ -0,0 +1,82 @@ ++// SPDX-License-Identifier: MIT ++pragma solidity ^0.8.0; + -+ spentGas += receipt.gasUsed * receipt.effectiveGasPrice ++import { ISystemConfig } from "src/L1/interfaces/ISystemConfig.sol"; ++import { IResourceMetering } from "src/L1/interfaces/IResourceMetering.sol"; ++ ++interface ISystemConfigInterop { ++ event ConfigUpdate(uint256 indexed version, ISystemConfig.UpdateType indexed updateType, bytes data); ++ event Initialized(uint8 version); ++ event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); ++ ++ function BATCH_INBOX_SLOT() external view returns (bytes32); ++ function DISPUTE_GAME_FACTORY_SLOT() external view returns (bytes32); ++ function L1_CROSS_DOMAIN_MESSENGER_SLOT() external view returns (bytes32); ++ function L1_ERC_721_BRIDGE_SLOT() external view returns (bytes32); ++ function L1_STANDARD_BRIDGE_SLOT() external view returns (bytes32); ++ function OPTIMISM_MINTABLE_ERC20_FACTORY_SLOT() external view returns (bytes32); ++ function OPTIMISM_PORTAL_SLOT() external view returns (bytes32); ++ function START_BLOCK_SLOT() external view returns (bytes32); ++ function UNSAFE_BLOCK_SIGNER_SLOT() external view returns (bytes32); ++ function VERSION() external view returns (uint256); ++ function basefeeScalar() external view returns (uint32); ++ function batchInbox() external view returns (address addr_); ++ function batcherHash() external view returns (bytes32); ++ function blobbasefeeScalar() external view returns (uint32); ++ function disputeGameFactory() external view returns (address addr_); ++ function gasLimit() external view returns (uint64); ++ function gasPayingToken() external view returns (address addr_, uint8 decimals_); ++ function gasPayingTokenName() external view returns (string memory name_); ++ function gasPayingTokenSymbol() external view returns (string memory symbol_); ++ function initialize( ++ address _owner, ++ uint32 _basefeeScalar, ++ uint32 _blobbasefeeScalar, ++ bytes32 _batcherHash, ++ uint64 _gasLimit, ++ address _unsafeBlockSigner, ++ IResourceMetering.ResourceConfig memory _config, ++ address _batchInbox, ++ ISystemConfig.Addresses memory _addresses ++ ) ++ external; ++ function isCustomGasToken() external view returns (bool); ++ function l1CrossDomainMessenger() external view returns (address addr_); ++ function l1ERC721Bridge() external view returns (address addr_); ++ function l1StandardBridge() external view returns (address addr_); ++ function maximumGasLimit() external pure returns (uint64); ++ function minimumGasLimit() external view returns (uint64); ++ function optimismMintableERC20Factory() external view returns (address addr_); ++ function optimismPortal() external view returns (address addr_); ++ function overhead() external view returns (uint256); ++ function owner() external view returns (address); ++ function renounceOwnership() external; ++ function resourceConfig() external view returns (IResourceMetering.ResourceConfig memory); ++ function scalar() external view returns (uint256); ++ function setBatcherHash(bytes32 _batcherHash) external; ++ function setGasConfig(uint256 _overhead, uint256 _scalar) external; ++ function setGasConfigEcotone(uint32 _basefeeScalar, uint32 _blobbasefeeScalar) external; ++ function setGasLimit(uint64 _gasLimit) external; ++ function setUnsafeBlockSigner(address _unsafeBlockSigner) external; ++ function startBlock() external view returns (uint256 startBlock_); ++ function transferOwnership(address newOwner) external; ++ function unsafeBlockSigner() external view returns (address addr_); ++ ++ function addDependency(uint256 _chainId) external; ++ function removeDependency(uint256 _chainId) external; ++ function dependencyManager() external view returns (address); ++ function initialize( ++ address _owner, ++ uint32 _basefeeScalar, ++ uint32 _blobbasefeeScalar, ++ bytes32 _batcherHash, ++ uint64 _gasLimit, ++ address _unsafeBlockSigner, ++ IResourceMetering.ResourceConfig memory _config, ++ address _batchInbox, ++ ISystemConfig.Addresses memory _addresses, ++ address _dependencyManager ++ ) ++ external; ++ function version() external pure returns (string memory); ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+15
+
-0
+ +
+ +
+
+
diff --git OP/packages/contracts-bedrock/src/L2/interfaces/IBaseFeeVault.sol CELO/packages/contracts-bedrock/src/L2/interfaces/IBaseFeeVault.sol +new file mode 100644 +index 0000000000000000000000000000000000000000..9843189bdb1406aa40bae985979bb70d92f52009 +--- /dev/null ++++ CELO/packages/contracts-bedrock/src/L2/interfaces/IBaseFeeVault.sol +@@ -0,0 +1,15 @@ ++// SPDX-License-Identifier: MIT ++pragma solidity ^0.8.0; + -+ // Get the L2 transaction hash from the L1 transaction receipt. -+ const [l2Hash] = getL2TransactionHashes(receipt) ++import { IFeeVault } from "src/universal/interfaces/IFeeVault.sol"; + -+ // Wait for the L2 transaction to be processed. -+ const l2Receipt = await config.client.l2.public.waitForTransactionReceipt({ -+ hash: l2Hash, -+ }) ++interface IBaseFeeVault is IFeeVault { ++ function version() external view returns (string memory); + -+ return { -+ success: l2Receipt.status == 'success', -+ l1GasPayment: spentGas, -+ } ++ function __constructor__( ++ address _recipient, ++ uint256 _minWithdrawalAmount, ++ WithdrawalNetwork _withdrawalNetwork ++ ) ++ external; +}
@@ -24682,9 +126005,52 @@
+ +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+0
+
-0
+ +
+ +
+
+
diff --git OP/packages/contracts-bedrock/src/L2/ICrossL2Inbox.sol CELO/packages/contracts-bedrock/src/L2/interfaces/ICrossL2Inbox.sol +rename from packages/contracts-bedrock/src/L2/ICrossL2Inbox.sol +rename to packages/contracts-bedrock/src/L2/interfaces/ICrossL2Inbox.sol
+
+ + +
+ @@ -24699,7 +126065,7 @@
@@ -24709,88 +126075,32 @@
-
+70
+
+14
-0
-
diff --git OP/op-e2e/celo/src/withdraw.js CELO/op-e2e/celo/src/withdraw.js +
diff --git OP/packages/contracts-bedrock/src/L2/interfaces/IETHLiquidity.sol CELO/packages/contracts-bedrock/src/L2/interfaces/IETHLiquidity.sol new file mode 100644 -index 0000000000000000000000000000000000000000..ca98e43a5a6b93444d9f4eb82a0537c34b87a556 +index 0000000000000000000000000000000000000000..de463f543b711391431018e3bcc7b6b285821f15 --- /dev/null -+++ CELO/op-e2e/celo/src/withdraw.js -@@ -0,0 +1,70 @@ -+export const withdraw = async function (args, config) { -+ const initiateHash = await config.client.l2.wallet.initiateWithdrawal({ -+ request: { -+ gas: args.gas, -+ to: args.to, -+ value: args.amount, -+ }, -+ }) -+ const receipt = await config.client.l2.public.waitForTransactionReceipt({ -+ hash: initiateHash, -+ }) -+ console.log('receipt', receipt) -+ -+ const l2GasPayment = -+ receipt.gasUsed * receipt.effectiveGasPrice + receipt.l1fee -+ -+ // FIXME: this blocks longer, the longer the devnet is running, see -+ // https://github.com/ethereum-optimism/optimism/issues/7668 -+ // NOTE: this function requires the mulitcall contract to be deployed -+ // on the L1 chain. -+ const { output, withdrawal } = await config.client.l1.public.waitToProve({ -+ receipt, -+ targetChain: config.client.l2.public.chain, -+ }) -+ // -+ -+ const proveWithdrawalArgs = -+ await config.client.l2.public.buildProveWithdrawal({ -+ output, -+ withdrawal, -+ }) -+ const proveHash = -+ await config.client.l1.wallet.proveWithdrawal(proveWithdrawalArgs) -+ -+ const proveReceipt = await config.client.l1.public.waitForTransactionReceipt({ -+ hash: proveHash, -+ }) -+ if (proveReceipt.status != 'success') { -+ return { -+ success: false, -+ l2GasPayment: l2GasPayment, -+ } -+ } -+ -+ await config.client.l1.public.waitToFinalize({ -+ withdrawalHash: withdrawal.withdrawalHash, -+ targetChain: config.client.l2.public.chain, -+ }) ++++ CELO/packages/contracts-bedrock/src/L2/interfaces/IETHLiquidity.sol +@@ -0,0 +1,14 @@ ++// SPDX-License-Identifier: MIT ++pragma solidity ^0.8.0; + -+ // HACK: the waitToFinalize does not seem to calculate the wait time -+ // correctly..., lets hardcode a wait time for now to see if it can work. -+ // In theory viem is not waiting an additional DISPUTE_GAME_FINALITY_DELAY_SECONDS. -+ // The current default value for this is 6, but this was not enough in manual testing. -+ // TODO: fix this upstream in viem... -+ await new Promise((res) => setTimeout(res, 16 * 1000)) -+ const finalizeHash = await config.client.l1.wallet.finalizeWithdrawal({ -+ targetChain: config.client.l2.public.chain, -+ withdrawal, -+ }) ++interface IETHLiquidity { ++ error NotCustomGasToken(); ++ error Unauthorized(); + -+ const finalizeReceipt = -+ await config.client.l1.public.waitForTransactionReceipt({ -+ hash: finalizeHash, -+ }) ++ event LiquidityBurned(address indexed caller, uint256 value); ++ event LiquidityMinted(address indexed caller, uint256 value); + -+ return { -+ success: finalizeReceipt.status == 'success', -+ l2GasPayment: l2GasPayment, -+ } ++ function burn() external payable; ++ function mint(uint256 _amount) external; ++ function version() external view returns (string memory); +}
@@ -24798,9 +126108,9 @@
@@ -24815,7 +126125,7 @@
@@ -24825,34 +126135,51 @@
-
+6
+
+23
-0
-
diff --git OP/op-e2e/celo/test_npm.sh CELO/op-e2e/celo/test_npm.sh -new file mode 100755 -index 0000000000000000000000000000000000000000..89783597300cf124d3091a535f3e01473998ae61 +
diff --git OP/packages/contracts-bedrock/src/L2/interfaces/IGasPriceOracle.sol CELO/packages/contracts-bedrock/src/L2/interfaces/IGasPriceOracle.sol +new file mode 100644 +index 0000000000000000000000000000000000000000..4ab0ef854c8ab3d51818bd90685a8d7d4a85bdcc --- /dev/null -+++ CELO/op-e2e/celo/test_npm.sh -@@ -0,0 +1,6 @@ -+#!/bin/bash -+#shellcheck disable=SC1091 -+set -eo pipefail ++++ CELO/packages/contracts-bedrock/src/L2/interfaces/IGasPriceOracle.sol +@@ -0,0 +1,23 @@ ++// SPDX-License-Identifier: MIT ++pragma solidity ^0.8.0; + -+source shared.sh -+npm test
++interface IGasPriceOracle { ++ function DECIMALS() external view returns (uint256); ++ function baseFee() external view returns (uint256); ++ function baseFeeScalar() external view returns (uint32); ++ function blobBaseFee() external view returns (uint256); ++ function blobBaseFeeScalar() external view returns (uint32); ++ function decimals() external pure returns (uint256); ++ function gasPrice() external view returns (uint256); ++ function getL1Fee(bytes memory _data) external view returns (uint256); ++ function getL1FeeUpperBound(uint256 _unsignedTxSize) external view returns (uint256); ++ function getL1GasUsed(bytes memory _data) external view returns (uint256); ++ function isEcotone() external view returns (bool); ++ function isFjord() external view returns (bool); ++ function l1BaseFee() external view returns (uint256); ++ function overhead() external view returns (uint256); ++ function scalar() external view returns (uint256); ++ function setEcotone() external; ++ function setFjord() external; ++ function version() external view returns (string memory); ++}
@@ -24867,7 +126194,7 @@
@@ -24877,70 +126204,67 @@
-
+42
+
+39
-0
-
diff --git OP/op-e2e/celo/test_weth_bridge.sh CELO/op-e2e/celo/test_weth_bridge.sh -new file mode 100755 -index 0000000000000000000000000000000000000000..ce77a5a308b6d1c6a579d7a503ce385ddf48dab0 +
diff --git OP/packages/contracts-bedrock/src/L2/interfaces/IL1Block.sol CELO/packages/contracts-bedrock/src/L2/interfaces/IL1Block.sol +new file mode 100644 +index 0000000000000000000000000000000000000000..6ef4c2984ae40da0c14075b211d3558864bb2f1d --- /dev/null -+++ CELO/op-e2e/celo/test_weth_bridge.sh -@@ -0,0 +1,42 @@ -+#!/bin/bash -+#shellcheck disable=SC2086,SC1091 -+set -eo pipefail -+set -x -+ -+source shared.sh -+SCRIPT_DIR=$(readlink -f "$(dirname "$0")") -+CONTRACTS_DIR=$SCRIPT_DIR/../../packages/contracts-bedrock -+ -+# Deploy WETH -+L1_WETH=$( -+ ETH_RPC_URL=$ETH_RPC_URL_L1 forge create --private-key=$ACC_PRIVKEY --root $CONTRACTS_DIR $CONTRACTS_DIR/src/dispute/weth/WETH98.sol:WETH98 --json | jq .deployedTo -r -+) -+ -+# create ERC20 token on L2 -+L2_TOKEN=$( -+ cast send --private-key $ACC_PRIVKEY 0x4200000000000000000000000000000000000012 "createOptimismMintableERC20(address,string,string)" $L1_WETH "Wrapped Ether" "WETH" --json \ -+ | jq -r '.logs[0].topics[2]' | cast parse-bytes32-address -+) -+ -+# Wrap some ETH -+ETH_RPC_URL=$ETH_RPC_URL_L1 cast send --private-key $ACC_PRIVKEY $L1_WETH --value 1ether -+# Approve transfer to bridge -+L1_BRIDGE_ADDR=$(cast call 0x4200000000000000000000000000000000000010 'otherBridge() returns (address)') -+ETH_RPC_URL=$ETH_RPC_URL_L1 cast send --private-key $ACC_PRIVKEY $L1_WETH 'approve(address, uint256) returns (bool)' $L1_BRIDGE_ADDR 1ether -+# Bridge to L2 -+ETH_RPC_URL=$ETH_RPC_URL_L1 cast send --private-key $ACC_PRIVKEY $L1_BRIDGE_ADDR 'bridgeERC20(address _localToken, address _remoteToken, uint256 _amount, uint32 _minGasLimit, bytes calldata _extraData)' $L1_WETH $L2_TOKEN 0.3ether 50000 0x --gas-limit 6000000 -+ -+# Setup up oracle and FeeCurrencyDirectory -+ORACLE=$(forge create --private-key=$ACC_PRIVKEY --root $CONTRACTS_DIR $CONTRACTS_DIR/src/celo/testing/MockSortedOracles.sol:MockSortedOracles --json | jq .deployedTo -r) -+cast send --private-key $ACC_PRIVKEY $ORACLE 'setMedianRate(address, uint256)' $L2_TOKEN 100000000000000000 -+cast send --private-key $ACC_PRIVKEY $FEE_CURRENCY_DIRECTORY_ADDR 'setCurrencyConfig(address, address, uint256)' $L2_TOKEN $ORACLE 60000 -+ -+# Check balance from bridging (we intentionally don't do this right after bridging, since it takes a bit) -+L2_BALANCE=$(cast call $L2_TOKEN 'balanceOf(address) returns (uint256)' $ACC_ADDR) -+echo L2 balance: $L2_BALANCE -+[[ $(echo $L2_BALANCE | awk '{print $1}') -gt 0 ]] || (echo "Bridging to L2 failed!"; exit 1) ++++ CELO/packages/contracts-bedrock/src/L2/interfaces/IL1Block.sol +@@ -0,0 +1,39 @@ ++// SPDX-License-Identifier: MIT ++pragma solidity ^0.8.0; + -+# Send fee currency tx! -+#TXHASH=$(~/op-geth/e2e_test/js-tests/send_tx.mjs 901 $ACC_PRIVKEY $L2_TOKEN) -+#cast receipt $TXHASH -+echo You can use privkey $ACC_PRIVKEY to pay for txs with $L2_TOKEN, now.
++interface IL1Block { ++ error NotDepositor(); ++ ++ event GasPayingTokenSet(address indexed token, uint8 indexed decimals, bytes32 name, bytes32 symbol); ++ ++ function DEPOSITOR_ACCOUNT() external pure returns (address addr_); ++ function baseFeeScalar() external view returns (uint32); ++ function basefee() external view returns (uint256); ++ function batcherHash() external view returns (bytes32); ++ function blobBaseFee() external view returns (uint256); ++ function blobBaseFeeScalar() external view returns (uint32); ++ function gasPayingToken() external view returns (address addr_, uint8 decimals_); ++ function gasPayingTokenName() external view returns (string memory name_); ++ function gasPayingTokenSymbol() external view returns (string memory symbol_); ++ function hash() external view returns (bytes32); ++ function isCustomGasToken() external view returns (bool); ++ function l1FeeOverhead() external view returns (uint256); ++ function l1FeeScalar() external view returns (uint256); ++ function number() external view returns (uint64); ++ function sequenceNumber() external view returns (uint64); ++ function setGasPayingToken(address _token, uint8 _decimals, bytes32 _name, bytes32 _symbol) external; ++ function setL1BlockValues( ++ uint64 _number, ++ uint64 _timestamp, ++ uint256 _basefee, ++ bytes32 _hash, ++ uint64 _sequenceNumber, ++ bytes32 _batcherHash, ++ uint256 _l1FeeOverhead, ++ uint256 _l1FeeScalar ++ ) ++ external; ++ function setL1BlockValuesEcotone() external; ++ function timestamp() external view returns (uint64); ++ function version() external pure returns (string memory); ++}
@@ -24955,7 +126279,7 @@
@@ -24965,82 +126289,137 @@
-
+64
+
+58
-0
-
diff --git OP/op-e2e/celo/tests/setup.js CELO/op-e2e/celo/tests/setup.js +
diff --git OP/packages/contracts-bedrock/src/L2/interfaces/IL1BlockIsthmus.sol CELO/packages/contracts-bedrock/src/L2/interfaces/IL1BlockIsthmus.sol new file mode 100644 -index 0000000000000000000000000000000000000000..e7400420f6748a8f04bed56a47e6df58d6bdfbc1 +index 0000000000000000000000000000000000000000..7ff15eda51b088d95c38381f829e96fb7f4b7621 --- /dev/null -+++ CELO/op-e2e/celo/tests/setup.js -@@ -0,0 +1,64 @@ -+import { setupClients } from '../src/config.js' -+import { makeChainConfigs } from '../src/chain.js' -+import { privateKeyToAccount } from 'viem/accounts' -+import { readFileSync } from 'fs' -+ -+// Default Anvil dev account that has a pre-allocation on the op-devnet: -+// "test test test test test test test test test test test junk" mnemonic account, -+// on path "m/44'/60'/0'/0/6". -+// Address: 0x976EA74026E726554dB657fA54763abd0C3a0aa9. -+const privKey = -+ '0x92db14e403b83dfe3df233f83dfa3a0d7096f21ca9b0d6d6b8d88b2b4ec1564e' -+ -+async function waitForNoError(func, timeout) { -+ const start = Date.now() -+ while (Date.now() - start < timeout) { -+ try { -+ await func() -+ return true -+ } catch (error) {} -+ await new Promise((r) => setTimeout(r, 1000)) -+ } -+ return false -+} ++++ CELO/packages/contracts-bedrock/src/L2/interfaces/IL1BlockIsthmus.sol +@@ -0,0 +1,58 @@ ++// SPDX-License-Identifier: MIT ++pragma solidity ^0.8.0; + -+async function waitReachable(client, timeout) { -+ const f = async () => client.getChainId() -+ return waitForNoError(f, timeout) ++enum ConfigType { ++ SET_GAS_PAYING_TOKEN, ++ ADD_DEPENDENCY, ++ REMOVE_DEPENDENCY +} + -+async function waitForNextGame(client, l2ChainConfig, timeout) { -+ const f = async () => -+ client.waitForNextGame({ -+ pollingInterval: 500, -+ l2BlockNumber: 0, -+ targetChain: l2ChainConfig, -+ }) -+ return waitForNoError(f, timeout) -+} ++interface IL1BlockIsthmus { ++ error AlreadyDependency(); ++ error CantRemovedDependency(); ++ error DependencySetSizeTooLarge(); ++ error NotCrossL2Inbox(); ++ error NotDependency(); ++ error NotDepositor(); ++ ++ event DependencyAdded(uint256 indexed chainId); ++ event DependencyRemoved(uint256 indexed chainId); ++ event GasPayingTokenSet(address indexed token, uint8 indexed decimals, bytes32 name, bytes32 symbol); ++ ++ function DEPOSITOR_ACCOUNT() external pure returns (address addr_); ++ function baseFeeScalar() external view returns (uint32); ++ function basefee() external view returns (uint256); ++ function batcherHash() external view returns (bytes32); ++ function blobBaseFee() external view returns (uint256); ++ function blobBaseFeeScalar() external view returns (uint32); ++ function dependencySetSize() external view returns (uint8); ++ function depositsComplete() external; ++ function gasPayingToken() external view returns (address addr_, uint8 decimals_); ++ function gasPayingTokenName() external view returns (string memory name_); ++ function gasPayingTokenSymbol() external view returns (string memory symbol_); ++ function hash() external view returns (bytes32); ++ function isCustomGasToken() external view returns (bool); ++ function isDeposit() external view returns (bool isDeposit_); ++ function isInDependencySet(uint256 _chainId) external view returns (bool); ++ function l1FeeOverhead() external view returns (uint256); ++ function l1FeeScalar() external view returns (uint256); ++ function number() external view returns (uint64); ++ function sequenceNumber() external view returns (uint64); ++ function setConfig(ConfigType _type, bytes memory _value) external; ++ function setGasPayingToken(address _token, uint8 _decimals, bytes32 _name, bytes32 _symbol) external; ++ function setL1BlockValues( ++ uint64 _number, ++ uint64 _timestamp, ++ uint256 _basefee, ++ bytes32 _hash, ++ uint64 _sequenceNumber, ++ bytes32 _batcherHash, ++ uint256 _l1FeeOverhead, ++ uint256 _l1FeeScalar ++ ) ++ external; ++ function setL1BlockValuesEcotone() external; ++ function setL1BlockValuesIsthmus() external; ++ function timestamp() external view returns (uint64); ++ function version() external pure returns (string memory); ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+15
+
-0
+ +
+ +
+
+
diff --git OP/packages/contracts-bedrock/src/L2/interfaces/IL1FeeVault.sol CELO/packages/contracts-bedrock/src/L2/interfaces/IL1FeeVault.sol +new file mode 100644 +index 0000000000000000000000000000000000000000..89ac3b782fcaac18603bc7fc88cc83ab57d1d5a1 +--- /dev/null ++++ CELO/packages/contracts-bedrock/src/L2/interfaces/IL1FeeVault.sol +@@ -0,0 +1,15 @@ ++// SPDX-License-Identifier: MIT ++pragma solidity ^0.8.0; + -+export async function setup() { -+ const contractAddrs = JSON.parse( -+ readFileSync('../../.devnet/addresses.json', 'utf8') -+ ) -+ const config = { account: privateKeyToAccount(privKey) } -+ const chainConfig = makeChainConfigs(900, 901, contractAddrs) ++import { IFeeVault } from "src/universal/interfaces/IFeeVault.sol"; + -+ config.client = setupClients( -+ chainConfig.l1, -+ chainConfig.l2, -+ config.account, -+ contractAddrs -+ ) -+ config.addresses = contractAddrs ++interface IL1FeeVault is IFeeVault { ++ function version() external view returns (string memory); + -+ const success = await Promise.all([ -+ waitReachable(config.client.l1.public, 10_000), -+ waitReachable(config.client.l2.public, 10_000), -+ waitForNextGame(config.client.l1.public, chainConfig.l2, 60_000), -+ ]) -+ if (success.every((v) => v == true)) { -+ return config -+ } -+ throw new Error('l1 and l2 clients not reachable within the deadline') ++ function __constructor__( ++ address _recipient, ++ uint256 _minWithdrawalAmount, ++ WithdrawalNetwork _withdrawalNetwork ++ ) ++ external; +}
@@ -25048,9 +126427,9 @@
@@ -25065,7 +126444,7 @@
@@ -25075,70 +126454,41 @@
-
+42
+
+13
-0
-
diff --git OP/op-e2e/celo/tests/tokenduality.test.js CELO/op-e2e/celo/tests/tokenduality.test.js +
diff --git OP/packages/contracts-bedrock/src/L2/interfaces/IL2CrossDomainMessenger.sol CELO/packages/contracts-bedrock/src/L2/interfaces/IL2CrossDomainMessenger.sol new file mode 100644 -index 0000000000000000000000000000000000000000..9980c81fece42a92f061e53be6cec62627a944f2 +index 0000000000000000000000000000000000000000..1cb49f674ec0b261adcd1c99a66fe32f7d34b3a1 --- /dev/null -+++ CELO/op-e2e/celo/tests/tokenduality.test.js -@@ -0,0 +1,42 @@ -+import { createAmountFromString } from 'reverse-mirage' -+import { setup } from './setup.js' -+ -+const minute = 60 * 1000 -+let config = {} -+ -+beforeAll(async () => { -+ config = await setup() -+}, 30_000) ++++ CELO/packages/contracts-bedrock/src/L2/interfaces/IL2CrossDomainMessenger.sol +@@ -0,0 +1,13 @@ ++// SPDX-License-Identifier: MIT ++pragma solidity ^0.8.0; + -+test( -+ 'test token duality', -+ async () => { -+ const receiverAddr = '0x000000000000000000000000000000000000dEaD' -+ const dualityToken = await config.client.l2.public.getERC20({ -+ erc20: { -+ address: '0x471ece3750da237f93b8e339c536989b8978a438', -+ chainID: config.client.l2.public.chain.id, -+ }, -+ }) -+ const balanceBefore = await config.client.l2.public.getBalance({ -+ address: receiverAddr, -+ }) ++import { ICrossDomainMessenger } from "src/universal/interfaces/ICrossDomainMessenger.sol"; + -+ const sendAmount = createAmountFromString(dualityToken, '100') -+ const { request } = await config.client.l2.wallet.simulateERC20Transfer({ -+ to: receiverAddr, -+ amount: sendAmount, -+ }) -+ const transferHash = await config.client.l2.wallet.writeContract(request) -+ const receipt = await config.client.l2.public.waitForTransactionReceipt({ -+ hash: transferHash, -+ }) -+ expect(receipt.status).toBe('success') -+ const balanceAfter = await config.client.l2.public.getBalance({ -+ address: receiverAddr, -+ }) ++interface IL2CrossDomainMessenger is ICrossDomainMessenger { ++ function MESSAGE_VERSION() external view returns (uint16); ++ function initialize(ICrossDomainMessenger _l1CrossDomainMessenger) external; ++ function l1CrossDomainMessenger() external view returns (ICrossDomainMessenger); ++ function version() external view returns (string memory); + -+ expect(balanceAfter).toBe(balanceBefore + sendAmount.amount) -+ }, -+ 1 * minute -+)
++ function __constructor__() external; ++}
@@ -25153,7 +126503,7 @@
@@ -25163,105 +126513,48 @@
-
+77
+
+20
-0
-
diff --git OP/op-e2e/celo/tests/withdraw_deposit.test.js CELO/op-e2e/celo/tests/withdraw_deposit.test.js +
diff --git OP/packages/contracts-bedrock/src/L2/interfaces/IL2ERC721Bridge.sol CELO/packages/contracts-bedrock/src/L2/interfaces/IL2ERC721Bridge.sol new file mode 100644 -index 0000000000000000000000000000000000000000..b7235239f4d1ff2653420f7406c322cbd4ceb83e +index 0000000000000000000000000000000000000000..a760ce1d803c9798892f8c9bfbb4811f8ba80297 --- /dev/null -+++ CELO/op-e2e/celo/tests/withdraw_deposit.test.js -@@ -0,0 +1,77 @@ -+import { withdraw } from '../src/withdraw.js' -+import { deposit } from '../src/deposit.js' -+import { parseEther } from 'viem' -+import { setup } from './setup.js' -+ -+const minute = 60 * 1000 -+var config = {} ++++ CELO/packages/contracts-bedrock/src/L2/interfaces/IL2ERC721Bridge.sol +@@ -0,0 +1,20 @@ ++// SPDX-License-Identifier: MIT ++pragma solidity ^0.8.0; + -+beforeAll(async () => { -+ config = await setup() -+}, minute) ++import { IERC721Bridge } from "src/universal/interfaces/IERC721Bridge.sol"; + -+test( -+ 'execute a withdraw and a deposit in succession', -+ async () => { -+ const celoToken = await config.client.l1.public.getERC20({ -+ erc20: { -+ address: config.addresses.CustomGasTokenProxy, -+ chainID: config.client.l1.public.chain.id, -+ }, -+ }) -+ const balanceL1Before = await config.client.l1.public.getERC20BalanceOf({ -+ erc20: celoToken, -+ address: config.account.address, -+ }) -+ const balanceL2Before = await config.client.l2.public.getBalance({ -+ address: config.account.address, -+ }) -+ const withdrawAmount = parseEther('1') -+ const withdrawResult = await withdraw( -+ { -+ amount: withdrawAmount, -+ to: config.account.address, -+ gas: 21_000n, -+ }, -+ config -+ ) -+ expect(withdrawResult.success).toBe(true) -+ const balanceL1AfterWithdraw = -+ await config.client.l1.public.getERC20BalanceOf({ -+ erc20: celoToken, -+ address: config.account.address, -+ }) -+ const balanceL2AfterWithdraw = await config.client.l2.public.getBalance({ -+ address: config.account.address, -+ }) -+ expect(balanceL1AfterWithdraw.amount).toBe( -+ balanceL1Before.amount + BigInt(withdrawAmount) -+ ) -+ expect(balanceL2AfterWithdraw).toBe( -+ balanceL2Before - BigInt(withdrawAmount) - withdrawResult.l2GasPayment -+ ) -+ const depositResult = await deposit( -+ { -+ mint: withdrawAmount, -+ to: config.account.address, -+ }, -+ config ++interface IL2ERC721Bridge is IERC721Bridge { ++ function finalizeBridgeERC721( ++ address _localToken, ++ address _remoteToken, ++ address _from, ++ address _to, ++ uint256 _tokenId, ++ bytes memory _extraData + ) -+ expect(depositResult.success).toBe(true) -+ -+ const balanceL1AfterDeposit = -+ await config.client.l1.public.getERC20BalanceOf({ -+ erc20: celoToken, -+ address: config.account.address, -+ }) -+ const balanceL2AfterDeposit = await config.client.l2.public.getBalance({ -+ address: config.account.address, -+ }) ++ external; ++ function initialize(address payable _l1ERC721Bridge) external; ++ function version() external view returns (string memory); + -+ expect(balanceL1AfterDeposit.amount).toBe(balanceL1Before.amount) -+ expect(balanceL2AfterDeposit).toBe( -+ balanceL2Before - withdrawResult.l2GasPayment -+ ) -+ }, -+ 15 * minute -+)
++ function __constructor__() external; ++}
@@ -25270,13 +126563,13 @@
- OP + (new)
@@ -25286,35 +126579,76 @@
-
+1
-
-1
+
+48
+
-0
-
diff --git OP/op-e2e/custom_gas_token_test.go CELO/op-e2e/custom_gas_token_test.go -index 454e73439aec222aa1c26eb58083421e3557e1ab..34db19f2300ef56f17109c261a536dfb6b964204 100644 ---- OP/op-e2e/custom_gas_token_test.go -+++ CELO/op-e2e/custom_gas_token_test.go -@@ -158,7 +158,7 @@ - // Take fee into account - diff := new(big.Int).Sub(startBalanceBeforeWithdrawal, endBalanceAfterWithdrawal) - fees := calcGasFees(receipt.GasUsed, tx.GasTipCap(), tx.GasFeeCap(), header.BaseFee) -- fees = fees.Add(fees, receipt.L1Fee) -+ // fees = fees.Add(fees, receipt.L1Fee) - diff = diff.Sub(diff, fees) - require.Equal(t, withdrawAmount, diff) -
+
diff --git OP/packages/contracts-bedrock/src/L2/interfaces/IL2StandardBridge.sol CELO/packages/contracts-bedrock/src/L2/interfaces/IL2StandardBridge.sol +new file mode 100644 +index 0000000000000000000000000000000000000000..9f9ce1a85621dd8c2e2df50009da21e44646f6e9 +--- /dev/null ++++ CELO/packages/contracts-bedrock/src/L2/interfaces/IL2StandardBridge.sol +@@ -0,0 +1,48 @@ ++// SPDX-License-Identifier: MIT ++pragma solidity ^0.8.0; ++ ++import { IStandardBridge } from "src/universal/interfaces/IStandardBridge.sol"; ++ ++interface IL2StandardBridge is IStandardBridge { ++ event DepositFinalized( ++ address indexed l1Token, ++ address indexed l2Token, ++ address indexed from, ++ address to, ++ uint256 amount, ++ bytes extraData ++ ); ++ event WithdrawalInitiated( ++ address indexed l1Token, ++ address indexed l2Token, ++ address indexed from, ++ address to, ++ uint256 amount, ++ bytes extraData ++ ); ++ ++ receive() external payable; ++ ++ function initialize(IStandardBridge _otherBridge) external; ++ function l1TokenBridge() external view returns (address); ++ function version() external pure returns (string memory); ++ function withdraw( ++ address _l2Token, ++ uint256 _amount, ++ uint32 _minGasLimit, ++ bytes memory _extraData ++ ) ++ external ++ payable; ++ function withdrawTo( ++ address _l2Token, ++ address _to, ++ uint256 _amount, ++ uint32 _minGasLimit, ++ bytes memory _extraData ++ ) ++ external ++ payable; ++ ++ function __constructor__() external; ++}
@@ -25329,7 +126663,7 @@
@@ -25339,39 +126673,186 @@
-
+21
+
+98
-0
-
diff --git OP/op-e2e/e2eutils/transactions/count.go CELO/op-e2e/e2eutils/transactions/count.go +
diff --git OP/packages/contracts-bedrock/src/L2/interfaces/IL2StandardBridgeInterop.sol CELO/packages/contracts-bedrock/src/L2/interfaces/IL2StandardBridgeInterop.sol new file mode 100644 -index 0000000000000000000000000000000000000000..0f4d41fe04786da83030e0f3465f48f7c4fd812c +index 0000000000000000000000000000000000000000..227b48881fa6a64559a562de978ab4bf38931ec5 --- /dev/null -+++ CELO/op-e2e/e2eutils/transactions/count.go -@@ -0,0 +1,21 @@ -+package transactions ++++ CELO/packages/contracts-bedrock/src/L2/interfaces/IL2StandardBridgeInterop.sol +@@ -0,0 +1,98 @@ ++// SPDX-License-Identifier: MIT ++pragma solidity ^0.8.0; + -+import ( -+ "github.com/ethereum/go-ethereum/common" -+ "github.com/ethereum/go-ethereum/core/types" -+) ++import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; ++import { IStandardBridge } from "src/universal/interfaces/IStandardBridge.sol"; ++import { ICrossDomainMessenger } from "src/universal/interfaces/ICrossDomainMessenger.sol"; + -+func TransactionsBySender(block *types.Block, sender common.Address) (int64, error) { -+ txCount := int64(0) -+ for _, tx := range block.Transactions() { -+ signer := types.NewCancunSigner(tx.ChainId()) -+ txSender, err := types.Sender(signer, tx) -+ if err != nil { -+ return 0, err -+ } -+ if txSender == sender { -+ txCount++ -+ } -+ } -+ return txCount, nil ++interface IMintableAndBurnable is IERC20 { ++ function mint(address, uint256) external; ++ function burn(address, uint256) external; ++} ++ ++interface IL2StandardBridgeInterop is IStandardBridge { ++ error InvalidDecimals(); ++ error InvalidLegacyERC20Address(); ++ error InvalidSuperchainERC20Address(); ++ error InvalidTokenPair(); ++ ++ event Converted(address indexed from, address indexed to, address indexed caller, uint256 amount); ++ ++ receive() external payable; ++ ++ event DepositFinalized( ++ address indexed l1Token, ++ address indexed l2Token, ++ address indexed from, ++ address to, ++ uint256 amount, ++ bytes extraData ++ ); ++ event WithdrawalInitiated( ++ address indexed l1Token, ++ address indexed l2Token, ++ address indexed from, ++ address to, ++ uint256 amount, ++ bytes extraData ++ ); ++ ++ function MESSENGER() external view returns (ICrossDomainMessenger); ++ function OTHER_BRIDGE() external view returns (IStandardBridge); ++ function bridgeERC20( ++ address _localToken, ++ address _remoteToken, ++ uint256 _amount, ++ uint32 _minGasLimit, ++ bytes memory _extraData ++ ) ++ external; ++ function bridgeERC20To( ++ address _localToken, ++ address _remoteToken, ++ address _to, ++ uint256 _amount, ++ uint32 _minGasLimit, ++ bytes memory _extraData ++ ) ++ external; ++ function bridgeETH(uint32 _minGasLimit, bytes memory _extraData) external payable; ++ function bridgeETHTo(address _to, uint32 _minGasLimit, bytes memory _extraData) external payable; ++ function deposits(address, address) external view returns (uint256); ++ function finalizeBridgeERC20( ++ address _localToken, ++ address _remoteToken, ++ address _from, ++ address _to, ++ uint256 _amount, ++ bytes memory _extraData ++ ) ++ external; ++ function finalizeBridgeETH(address _from, address _to, uint256 _amount, bytes memory _extraData) external payable; ++ function messenger() external view returns (ICrossDomainMessenger); ++ function otherBridge() external view returns (IStandardBridge); ++ function paused() external view returns (bool); ++ ++ function initialize(IStandardBridge _otherBridge) external; ++ function l1TokenBridge() external view returns (address); ++ function withdraw( ++ address _l2Token, ++ uint256 _amount, ++ uint32 _minGasLimit, ++ bytes memory _extraData ++ ) ++ external ++ payable; ++ function withdrawTo( ++ address _l2Token, ++ address _to, ++ uint256 _amount, ++ uint32 _minGasLimit, ++ bytes memory _extraData ++ ) ++ external ++ payable; ++ ++ function convert(address _from, address _to, uint256 _amount) external; ++ function version() external pure returns (string memory); ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+24
+
-0
+ +
+ +
+
+
diff --git OP/packages/contracts-bedrock/src/L2/interfaces/IL2ToL1MessagePasser.sol CELO/packages/contracts-bedrock/src/L2/interfaces/IL2ToL1MessagePasser.sol +new file mode 100644 +index 0000000000000000000000000000000000000000..751cf51a40db374ce1cf12618850a7eae89abd54 +--- /dev/null ++++ CELO/packages/contracts-bedrock/src/L2/interfaces/IL2ToL1MessagePasser.sol +@@ -0,0 +1,24 @@ ++// SPDX-License-Identifier: MIT ++pragma solidity ^0.8.0; ++ ++interface IL2ToL1MessagePasser { ++ event MessagePassed( ++ uint256 indexed nonce, ++ address indexed sender, ++ address indexed target, ++ uint256 value, ++ uint256 gasLimit, ++ bytes data, ++ bytes32 withdrawalHash ++ ); ++ event WithdrawerBalanceBurnt(uint256 indexed amount); ++ ++ receive() external payable; ++ ++ function MESSAGE_VERSION() external view returns (uint16); ++ function burn() external; ++ function initiateWithdrawal(address _target, uint256 _gasLimit, bytes memory _data) external payable; ++ function messageNonce() external view returns (uint256); ++ function sentMessages(bytes32) external view returns (bool); ++ function version() external view returns (string memory); +}
@@ -25379,9 +126860,9 @@
@@ -25390,13 +126871,13 @@
- OP + (new)
@@ -25406,35 +126887,48 @@
-
+1
-
-1
+
+13
+
-0
-
diff --git OP/op-e2e/eip4844_test.go CELO/op-e2e/eip4844_test.go -index 7069fba72afc3e7b7c3bac8ca31026363cc647c8..379e34aa2fb671144038b67e90e82ca78443dbc9 100644 ---- OP/op-e2e/eip4844_test.go -+++ CELO/op-e2e/eip4844_test.go -@@ -126,7 +126,7 @@ opts.Nonce = 1 // Already have deposit - opts.ToAddr = &common.Address{0xff, 0xff} - // put some random data in the tx to make it fill up 6 blobs (multi-blob case) - opts.Data = testutils.RandomData(rand.New(rand.NewSource(420)), 400) -- opts.Gas, err = core.IntrinsicGas(opts.Data, nil, false, true, true, false) -+ opts.Gas, err = core.IntrinsicGas(opts.Data, nil, false, true, true, false, nil, nil) - require.NoError(t, err) - opts.VerifyOnClients(l2Verif) - })
+
diff --git OP/packages/contracts-bedrock/src/L2/IL2ToL2CrossDomainMessenger.sol CELO/packages/contracts-bedrock/src/L2/interfaces/IL2ToL2CrossDomainMessenger.sol +rename from packages/contracts-bedrock/src/L2/IL2ToL2CrossDomainMessenger.sol +rename to packages/contracts-bedrock/src/L2/interfaces/IL2ToL2CrossDomainMessenger.sol +index 8b6b9d617cf1e6c3acf4e710fa3b44f9ecd12ea3..cb8d1952de656012aa64de5020c67a8781c58bb2 100644 +--- OP/packages/contracts-bedrock/src/L2/IL2ToL2CrossDomainMessenger.sol ++++ CELO/packages/contracts-bedrock/src/L2/interfaces/IL2ToL2CrossDomainMessenger.sol +@@ -4,6 +4,19 @@ + /// @title IL2ToL2CrossDomainMessenger + /// @notice Interface for the L2ToL2CrossDomainMessenger contract. + interface IL2ToL2CrossDomainMessenger { ++ /// @notice Mapping of message hashes to boolean receipt values. Note that a message will only ++ /// be present in this mapping if it has successfully been relayed on this chain, and ++ /// can therefore not be relayed again. ++ /// @param _msgHash message hash to check. ++ /// @return Returns true if the message corresponding to the `_msgHash` was successfully relayed. ++ function successfulMessages(bytes32 _msgHash) external view returns (bool); ++ ++ /// @notice Retrieves the next message nonce. Message version will be added to the upper two ++ /// bytes of the message nonce. Message version allows us to treat messages as having ++ /// different structures. ++ /// @return Nonce of the next message to be sent, with added message version. ++ function messageNonce() external view returns (uint256); ++ + /// @notice Retrieves the sender of the current cross domain message. + /// @return _sender Address of the sender of the current cross domain message. + function crossDomainMessageSender() external view returns (address _sender);
@@ -25443,13 +126937,13 @@
- OP + (new)
@@ -25459,158 +126953,25 @@
-
+52
-
-16
+
+0
+
-0
-
diff --git OP/op-e2e/setup.go CELO/op-e2e/setup.go -index cd07e081d0dd4b96d27feb28c1f694a6b9f14559..b97d3780587a8d45f84ef562b2ba4fe49e910188 100644 ---- OP/op-e2e/setup.go -+++ CELO/op-e2e/setup.go -@@ -39,6 +39,7 @@ "github.com/ethereum/go-ethereum/node" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rpc" -  -+ altda "github.com/ethereum-optimism/optimism/op-alt-da" - bss "github.com/ethereum-optimism/optimism/op-batcher/batcher" - batcherFlags "github.com/ethereum-optimism/optimism/op-batcher/flags" - "github.com/ethereum-optimism/optimism/op-chain-ops/genesis" -@@ -164,18 +165,19 @@ Sync: sync.Config{SyncMode: sync.CLSync}, - }, - }, - Loggers: map[string]log.Logger{ -- RoleVerif: testlog.Logger(t, log.LevelInfo).New("role", RoleVerif), -- RoleSeq: testlog.Logger(t, log.LevelInfo).New("role", RoleSeq), -- "batcher": testlog.Logger(t, log.LevelInfo).New("role", "batcher"), -- "proposer": testlog.Logger(t, log.LevelInfo).New("role", "proposer"), -+ RoleVerif: testlog.Logger(t, log.LevelInfo).New("role", RoleVerif), -+ RoleSeq: testlog.Logger(t, log.LevelInfo).New("role", RoleSeq), -+ "batcher": testlog.Logger(t, log.LevelInfo).New("role", "batcher"), -+ "proposer": testlog.Logger(t, log.LevelInfo).New("role", "proposer"), -+ "da-server": testlog.Logger(t, log.LevelInfo).New("role", "da-server"), - }, -- GethOptions: map[string][]geth.GethOption{}, -- P2PTopology: nil, // no P2P connectivity by default -- NonFinalizedProposals: false, -- ExternalL2Shim: config.ExternalL2Shim, -- DataAvailabilityType: batcherFlags.CalldataType, -- MaxPendingTransactions: 1, -- BatcherTargetNumFrames: 1, -+ GethOptions: map[string][]geth.GethOption{}, -+ P2PTopology: nil, // no P2P connectivity by default -+ NonFinalizedProposals: false, -+ ExternalL2Shim: config.ExternalL2Shim, -+ DataAvailabilityType: batcherFlags.CalldataType, -+ BatcherMaxPendingTransactions: 1, -+ BatcherTargetNumFrames: 1, - } - } -  -@@ -298,12 +300,16 @@ - // If >0, limits the number of blocks per span batch - BatcherMaxBlocksPerSpanBatch int -  -+ // BatcherMaxPendingTransactions determines how many transactions the batcher will try to send -+ // concurrently. 0 means unlimited. -+ BatcherMaxPendingTransactions uint64 -+ -+ // BatcherMaxConcurrentDARequest determines how many DAserver requests the batcher is allowed to -+ // make concurrently. 0 means unlimited. -+ BatcherMaxConcurrentDARequest uint64 -+ - // SupportL1TimeTravel determines if the L1 node supports quickly skipping forward in time - SupportL1TimeTravel bool -- -- // MaxPendingTransactions determines how many transactions the batcher will try to send -- // concurrently. 0 means unlimited. -- MaxPendingTransactions uint64 - } -  - type System struct { -@@ -319,6 +325,7 @@ RollupNodes map[string]services.RollupNode - L2OutputSubmitter *l2os.ProposerService - BatchSubmitter *bss.BatcherService - Mocknet mocknet.Mocknet -+ FakeAltDAServer *altda.FakeDAServer -  - L1BeaconAPIAddr endpoint.RestHTTP -  -@@ -543,6 +550,16 @@ } - } - } -  -+ var rollupAltDAConfig *rollup.AltDAConfig -+ if cfg.DeployConfig.UseAltDA { -+ rollupAltDAConfig = &rollup.AltDAConfig{ -+ DAChallengeAddress: cfg.L1Deployments.DataAvailabilityChallengeProxy, -+ DAChallengeWindow: cfg.DeployConfig.DAChallengeWindow, -+ DAResolveWindow: cfg.DeployConfig.DAResolveWindow, -+ CommitmentType: altda.GenericCommitmentString, -+ } -+ } -+ - makeRollupConfig := func() rollup.Config { - return rollup.Config{ - Genesis: rollup.Genesis{ -@@ -573,7 +590,9 @@ EcotoneTime: cfg.DeployConfig.EcotoneTime(uint64(cfg.DeployConfig.L1GenesisBlockTimestamp)), - FjordTime: cfg.DeployConfig.FjordTime(uint64(cfg.DeployConfig.L1GenesisBlockTimestamp)), - GraniteTime: cfg.DeployConfig.GraniteTime(uint64(cfg.DeployConfig.L1GenesisBlockTimestamp)), - InteropTime: cfg.DeployConfig.InteropTime(uint64(cfg.DeployConfig.L1GenesisBlockTimestamp)), -+ Cel2Time: cfg.DeployConfig.RegolithTime(uint64(cfg.DeployConfig.L1GenesisBlockTimestamp)), - ProtocolVersionsAddress: cfg.L1Deployments.ProtocolVersionsProxy, -+ AltDAConfig: rollupAltDAConfig, - } - } - defaultConfig := makeRollupConfig() -@@ -819,11 +838,27 @@ if _, ok := opts.Get("compressionAlgo", "brotli"); ok { - compressionAlgo = derive.Brotli10 - } -  -+ var batcherAltDACLIConfig altda.CLIConfig -+ if cfg.DeployConfig.UseAltDA { -+ fakeAltDAServer := altda.NewFakeDAServer("127.0.0.1", 0, sys.Cfg.Loggers["da-server"]) -+ if err := fakeAltDAServer.Start(); err != nil { -+ return nil, fmt.Errorf("failed to start fake altDA server: %w", err) -+ } -+ sys.FakeAltDAServer = fakeAltDAServer -+ -+ batcherAltDACLIConfig = altda.CLIConfig{ -+ Enabled: cfg.DeployConfig.UseAltDA, -+ DAServerURL: fakeAltDAServer.HttpEndpoint(), -+ VerifyOnRead: true, -+ GenericDA: true, -+ MaxConcurrentRequests: cfg.BatcherMaxConcurrentDARequest, -+ } -+ } - batcherCLIConfig := &bss.CLIConfig{ - L1EthRpc: sys.EthInstances[RoleL1].UserRPC().RPC(), - L2EthRpc: sys.EthInstances[RoleSeq].UserRPC().RPC(), - RollupRpc: sys.RollupNodes[RoleSeq].UserRPC().RPC(), -- MaxPendingTransactions: cfg.MaxPendingTransactions, -+ MaxPendingTransactions: cfg.BatcherMaxPendingTransactions, - MaxChannelDuration: 1, - MaxL1TxSize: batcherMaxL1TxSizeBytes, - TestUseMaxTxSizeForBlobs: cfg.BatcherUseMaxTxSizeForBlobs, -@@ -841,6 +876,7 @@ BatchType: cfg.BatcherBatchType, - MaxBlocksPerSpanBatch: cfg.BatcherMaxBlocksPerSpanBatch, - DataAvailabilityType: sys.Cfg.DataAvailabilityType, - CompressionAlgo: compressionAlgo, -+ AltDA: batcherAltDACLIConfig, - } - // Batch Submitter - batcher, err := bss.BatcherServiceFromCLIConfig(context.Background(), "0.0.1", batcherCLIConfig, sys.Cfg.Loggers["batcher"])
+
diff --git OP/packages/contracts-bedrock/src/L2/IOptimismERC20Factory.sol CELO/packages/contracts-bedrock/src/L2/interfaces/IOptimismERC20Factory.sol +rename from packages/contracts-bedrock/src/L2/IOptimismERC20Factory.sol +rename to packages/contracts-bedrock/src/L2/interfaces/IOptimismERC20Factory.sol
@@ -25619,13 +126980,13 @@
- OP + (new)
@@ -25635,176 +126996,55 @@
-
+86
-
-10
+
+6
+
-5
-
diff --git OP/op-e2e/system_test.go CELO/op-e2e/system_test.go -index a168a8c90df624eb5ac99507a3c4f95fd4379e7f..dd0780b86314aa8f0650c82616c2db9797555c4c 100644 ---- OP/op-e2e/system_test.go -+++ CELO/op-e2e/system_test.go -@@ -14,6 +14,7 @@ - "github.com/libp2p/go-libp2p/core/peer" - "github.com/stretchr/testify/require" -  -+ "github.com/ethereum-optimism/optimism/op-batcher/flags" - "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" -@@ -1057,6 +1058,9 @@ } -  - // TestFees checks that L1/L2 fees are handled. - func TestFees(t *testing.T) { -+ -+ t.Skipf("Skipping fee tests until they support Celo's zero L1 fees.") -+ - t.Run("pre-regolith", func(t *testing.T) { - InitParallel(t) - cfg := RegolithSystemConfig(t, nil) -@@ -1146,8 +1150,16 @@ require.Nil(t, err, "reading gpo decimals") -  - require.Equal(t, decimals.Uint64(), uint64(6), "wrong gpo decimals") -  -+ // Celo changes the base fee recipient -+ var baseFeeRecipient common.Address -+ if sys.RollupConfig.Cel2Time == nil { -+ baseFeeRecipient = predeploys.BaseFeeVaultAddr -+ } else { -+ baseFeeRecipient = predeploys.FeeHandlerAddr -+ } -+ - // BaseFee Recipient -- baseFeeRecipientStartBalance, err := l2Seq.BalanceAt(context.Background(), predeploys.BaseFeeVaultAddr, big.NewInt(rpc.EarliestBlockNumber.Int64())) -+ baseFeeRecipientStartBalance, err := l2Seq.BalanceAt(context.Background(), baseFeeRecipient, big.NewInt(rpc.EarliestBlockNumber.Int64())) - require.Nil(t, err) -  - // L1Fee Recipient -@@ -1190,7 +1202,7 @@ - endBalance, err := l2Seq.BalanceAt(context.Background(), fromAddr, header.Number) - require.Nil(t, err) -  -- baseFeeRecipientEndBalance, err := l2Seq.BalanceAt(context.Background(), predeploys.BaseFeeVaultAddr, header.Number) -+ baseFeeRecipientEndBalance, err := l2Seq.BalanceAt(context.Background(), baseFeeRecipient, header.Number) - require.Nil(t, err) -  - l1Header, err := l1.HeaderByNumber(context.Background(), nil) -@@ -1362,7 +1374,7 @@ func TestBatcherMultiTx(t *testing.T) { - InitParallel(t) -  - cfg := DefaultSystemConfig(t) -- cfg.MaxPendingTransactions = 0 // no limit on parallel txs -+ cfg.BatcherMaxPendingTransactions = 0 // no limit on parallel txs - // ensures that batcher txs are as small as possible - cfg.BatcherMaxL1TxSizeBytes = derive.FrameV0OverHeadSize + 1 /*version bytes*/ + 1 - cfg.DisableBatcher = true -@@ -1375,7 +1387,7 @@ - _, err = geth.WaitForBlock(big.NewInt(10), l2Seq, time.Duration(cfg.DeployConfig.L2BlockTime*15)*time.Second) - require.NoError(t, err, "Waiting for L2 blocks") +
diff --git OP/packages/contracts-bedrock/src/L2/IOptimismSuperchainERC20.sol CELO/packages/contracts-bedrock/src/L2/interfaces/IOptimismSuperchainERC20.sol +rename from packages/contracts-bedrock/src/L2/IOptimismSuperchainERC20.sol +rename to packages/contracts-bedrock/src/L2/interfaces/IOptimismSuperchainERC20.sol +index 9b9594e75d781f7b61af0605046de4cc96514508..5f537c1f51ec13a7d1a62e64a29b07140b51db9e 100644 +--- OP/packages/contracts-bedrock/src/L2/IOptimismSuperchainERC20.sol ++++ CELO/packages/contracts-bedrock/src/L2/interfaces/IOptimismSuperchainERC20.sol +@@ -1,14 +1,15 @@ + // SPDX-License-Identifier: MIT + pragma solidity ^0.8.0;   -- ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) -+ ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) - defer cancel() - l1Number, err := l1Client.BlockNumber(ctx) - require.NoError(t, err) -@@ -1385,16 +1397,80 @@ driver := sys.BatchSubmitter.TestDriver() - err = driver.StartBatchSubmitting() - require.NoError(t, err) +-import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +-import { ISuperchainERC20Extensions } from "./ISuperchainERC20.sol"; ++// Interfaces ++import { IERC20Solady } from "src/vendor/interfaces/IERC20Solady.sol"; ++import { ISuperchainERC20Extensions, ISuperchainERC20Errors } from "src/L2/interfaces/ISuperchainERC20.sol";   -- totalTxCount := 0 -- // wait for up to 10 L1 blocks, usually only 3 is required, but it's -+ totalBatcherTxsCount := int64(0) -+ // wait for up to 5 L1 blocks, usually only 3 is required, but it's - // possible additional L1 blocks will be created before the batcher starts, - // so we wait additional blocks. -- for i := int64(0); i < 10; i++ { -- block, err := geth.WaitForBlock(big.NewInt(int64(l1Number)+i), l1Client, time.Duration(cfg.DeployConfig.L1BlockTime*5)*time.Second) -+ for i := int64(0); i < 5; i++ { -+ block, err := geth.WaitForBlock(big.NewInt(int64(l1Number)+i), l1Client, time.Duration(cfg.DeployConfig.L1BlockTime*2)*time.Second) -+ require.NoError(t, err, "Waiting for l1 blocks") -+ // there are possibly other services (proposer/challenger) in the background sending txs -+ // so we only count the batcher txs -+ batcherTxCount, err := transactions.TransactionsBySender(block, cfg.DeployConfig.BatchSenderAddress) -+ require.NoError(t, err) -+ totalBatcherTxsCount += int64(batcherTxCount) -+ -+ if totalBatcherTxsCount >= 10 { -+ return -+ } -+ } -+ -+ t.Fatal("Expected at least 10 transactions from the batcher") -+} -+ -+func TestBatcherConcurrentAltDARequests(t *testing.T) { -+ InitParallel(t) -+ -+ numL1TxsExpected := int64(10) -+ -+ cfg := DefaultSystemConfig(t) -+ cfg.DeployConfig.UseAltDA = true -+ cfg.BatcherMaxPendingTransactions = 0 // no limit on parallel txs -+ // ensures that batcher txs are as small as possible -+ cfg.BatcherMaxL1TxSizeBytes = derive.FrameV0OverHeadSize + 1 /*version bytes*/ + 1 -+ cfg.BatcherBatchType = 0 -+ cfg.DataAvailabilityType = flags.CalldataType -+ cfg.BatcherMaxConcurrentDARequest = uint64(numL1TxsExpected) -+ -+ // disable batcher because we start it manually below -+ cfg.DisableBatcher = true -+ sys, err := cfg.Start(t) -+ require.NoError(t, err, "Error starting up system") -+ defer sys.Close() -+ -+ // make every request take 5 seconds, such that only concurrent requests will be able to make progress fast enough -+ sys.FakeAltDAServer.SetPutRequestLatency(5 * time.Second) -+ -+ l1Client := sys.NodeClient("l1") -+ l2Seq := sys.NodeClient("sequencer") -+ -+ // we wait for numL1TxsExpected L2 blocks to have been produced, just to make sure the sequencer is working properly -+ _, err = geth.WaitForBlock(big.NewInt(numL1TxsExpected), l2Seq, time.Duration(cfg.DeployConfig.L2BlockTime*uint64(numL1TxsExpected))*time.Second) -+ require.NoError(t, err, "Waiting for L2 blocks") -+ ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) -+ defer cancel() -+ startingL1BlockNum, err := l1Client.BlockNumber(ctx) -+ require.NoError(t, err) -+ -+ // start batch submission -+ driver := sys.BatchSubmitter.TestDriver() -+ err = driver.StartBatchSubmitting() -+ require.NoError(t, err) -+ -+ totalBatcherTxsCount := int64(0) -+ // wait for up to 5 L1 blocks, expecting 10 L2 batcher txs in them. -+ // usually only 3 is required, but it's possible additional L1 blocks will be created -+ // before the batcher starts, so we wait additional blocks. -+ for i := int64(0); i < 5; i++ { -+ block, err := geth.WaitForBlock(big.NewInt(int64(startingL1BlockNum)+i), l1Client, time.Duration(cfg.DeployConfig.L1BlockTime*2)*time.Second) - require.NoError(t, err, "Waiting for l1 blocks") -- totalTxCount += len(block.Transactions()) -+ // there are possibly other services (proposer/challenger) in the background sending txs -+ // so we only count the batcher txs -+ batcherTxCount, err := transactions.TransactionsBySender(block, cfg.DeployConfig.BatchSenderAddress) -+ require.NoError(t, err) -+ totalBatcherTxsCount += int64(batcherTxCount) + /// @title IOptimismSuperchainERC20Extension + /// @notice This interface is available on the OptimismSuperchainERC20 contract. + /// We declare it as a separate interface so that it can be used in + /// custom implementations of SuperchainERC20. +-interface IOptimismSuperchainERC20Extension is ISuperchainERC20Extensions { ++interface IOptimismSuperchainERC20Extension is ISuperchainERC20Extensions, ISuperchainERC20Errors { + /// @notice Emitted whenever tokens are minted for an account. + /// @param account Address of the account tokens are being minted for. + /// @param amount Amount of tokens minted. +@@ -34,5 +35,5 @@ function remoteToken() external view returns (address); + }   -- if totalTxCount >= 10 { -+ if totalBatcherTxsCount >= numL1TxsExpected { - return - } - }
+ /// @title IOptimismSuperchainERC20 +-/// @notice Combines the ERC20 interface with the OptimismSuperchainERC20Extension interface. +-interface IOptimismSuperchainERC20 is IERC20, IOptimismSuperchainERC20Extension { } ++/// @notice Combines Solady's ERC20 interface with the OptimismSuperchainERC20Extension interface. ++interface IOptimismSuperchainERC20 is IERC20Solady, IOptimismSuperchainERC20Extension { }
@@ -25813,13 +127053,13 @@
- OP + (new)
@@ -25829,35 +127069,44 @@
-
+2
+
+16
-0
-
diff --git OP/op-e2e/system_tob_test.go CELO/op-e2e/system_tob_test.go -index 99668d995acff65ce6ce7fdcaf43cf42f6e04c2e..c00f6ad09f9ac7d4d517c17950cb8edf0a14c129 100644 ---- OP/op-e2e/system_tob_test.go -+++ CELO/op-e2e/system_tob_test.go -@@ -386,6 +386,8 @@ - // TestMixedWithdrawalValidity makes a number of withdrawal transactions and ensures ones with modified parameters are - // rejected while unmodified ones are accepted. This runs test cases in different systems. - func TestMixedWithdrawalValidity(t *testing.T) { -+ t.Skipf("Skipping withdrawal tests for now, must check in more detail!") +
diff --git OP/packages/contracts-bedrock/src/L2/interfaces/ISequencerFeeVault.sol CELO/packages/contracts-bedrock/src/L2/interfaces/ISequencerFeeVault.sol +new file mode 100644 +index 0000000000000000000000000000000000000000..1987d07bb7f76a47191bd5e64b44ffe826545240 +--- /dev/null ++++ CELO/packages/contracts-bedrock/src/L2/interfaces/ISequencerFeeVault.sol +@@ -0,0 +1,16 @@ ++// SPDX-License-Identifier: MIT ++pragma solidity ^0.8.0; + - InitParallel(t) -  - // There are 7 different fields we try modifying to cause a failure, plus one "good" test result we test.
++import { IFeeVault } from "src/universal/interfaces/IFeeVault.sol"; ++ ++interface ISequencerFeeVault is IFeeVault { ++ function version() external view returns (string memory); ++ function l1FeeWallet() external view returns (address); ++ ++ function __constructor__( ++ address _recipient, ++ uint256 _minWithdrawalAmount, ++ WithdrawalNetwork _withdrawalNetwork ++ ) ++ external; ++}
@@ -25866,13 +127115,13 @@
- OP + (new)
@@ -25882,102 +127131,62 @@
-
+1
-
-1
+
+19
+
-3
-
diff --git OP/op-e2e/withdrawal.go CELO/op-e2e/withdrawal.go -index a5f44434a8eede400b1ac22aea6f2cbb554a1442..49ccac8ba1ee46ac0f293080ae85f2d1042b72b9 100644 ---- OP/op-e2e/withdrawal.go -+++ CELO/op-e2e/withdrawal.go -@@ -98,7 +98,7 @@ - // Take fee into account - diff = new(big.Int).Sub(startBalanceBeforeWithdrawal, endBalanceAfterWithdrawal) - fees := calcGasFees(receipt.GasUsed, tx.GasTipCap(), tx.GasFeeCap(), header.BaseFee) -- fees = fees.Add(fees, receipt.L1Fee) -+ // fees = fees.Add(fees, receipt.L1Fee) // Skip L1 fees on Celo - diff = diff.Sub(diff, fees) - require.Equal(t, withdrawAmount, diff) -
- - - - - -
- -
- - - - -
- -
-
-
- - -
-
- -
-
-
- - -
-
-
-
@@ -25986,13 +127195,13 @@
- OP + (new)
@@ -26002,48 +127211,61 @@
-
+8
+
+33
-0
-
diff --git OP/op-node/flags/flags.go CELO/op-node/flags/flags.go -index b3af25d661433b5078d02861be604c1953dc4c67..0ddc6e67ec3f7789f010ea9462049dd8820fc017 100644 ---- OP/op-node/flags/flags.go -+++ CELO/op-node/flags/flags.go -@@ -229,6 +229,13 @@ EnvVars: prefixEnvVars("SEQUENCER_L1_CONFS"), - Value: 4, - Category: SequencerCategory, - } -+ SequencerUseFinalizedL1Flag = &cli.BoolFlag{ -+ Name: "sequencer.use-finalized", -+ Usage: "Enable use of only finalized L1 blocks as L1 origin. Overwrites the value of 'sequencer.l1-confs'.", -+ EnvVars: prefixEnvVars("SEQUENCER_USE_FINALIZED"), -+ Value: false, -+ Category: SequencerCategory, -+ } - L1EpochPollIntervalFlag = &cli.DurationFlag{ - Name: "l1.epoch-poll-interval", - Usage: "Poll interval for retrieving new L1 epoch updates such as safe and finalized block changes. Disabled if 0 or negative.", -@@ -388,6 +395,7 @@ L1RPCRateLimit, - L1RPCMaxBatchSize, - L1RPCMaxConcurrency, - L1HTTPPollInterval, -+ SequencerUseFinalizedL1Flag, - VerifierL1Confs, - SequencerEnabledFlag, - SequencerStoppedFlag,
+
diff --git OP/packages/contracts-bedrock/src/L2/interfaces/ISuperchainWETH.sol CELO/packages/contracts-bedrock/src/L2/interfaces/ISuperchainWETH.sol +new file mode 100644 +index 0000000000000000000000000000000000000000..7c755e11e8693da7223a131dc92e71feaa48d687 +--- /dev/null ++++ CELO/packages/contracts-bedrock/src/L2/interfaces/ISuperchainWETH.sol +@@ -0,0 +1,33 @@ ++// SPDX-License-Identifier: MIT ++pragma solidity ^0.8.0; ++ ++interface ISuperchainWETH { ++ error NotCustomGasToken(); ++ error Unauthorized(); ++ ++ event Approval(address indexed src, address indexed guy, uint256 wad); ++ event Deposit(address indexed dst, uint256 wad); ++ event RelayERC20(address indexed from, address indexed to, uint256 amount, uint256 source); ++ event SendERC20(address indexed from, address indexed to, uint256 amount, uint256 destination); ++ event Transfer(address indexed src, address indexed dst, uint256 wad); ++ event Withdrawal(address indexed src, uint256 wad); ++ ++ fallback() external payable; ++ ++ receive() external payable; ++ ++ function allowance(address, address) external view returns (uint256); ++ function approve(address guy, uint256 wad) external returns (bool); ++ function balanceOf(address) external view returns (uint256); ++ function decimals() external view returns (uint8); ++ function deposit() external payable; ++ function name() external view returns (string memory); ++ function relayERC20(address from, address dst, uint256 wad) external; ++ function sendERC20(address dst, uint256 wad, uint256 chainId) external; ++ function symbol() external view returns (string memory); ++ function totalSupply() external view returns (uint256); ++ function transfer(address dst, uint256 wad) external returns (bool); ++ function transferFrom(address src, address dst, uint256 wad) external returns (bool); ++ function version() external view returns (string memory); ++ function withdraw(uint256 wad) external; ++}
@@ -26052,13 +127274,13 @@ @@ -26068,42 +127290,35 @@
-
+11
+
+6
-1
-
diff --git OP/op-node/rollup/chain_spec.go CELO/op-node/rollup/chain_spec.go -index 95d9c3b1979832a8800bb9c1266c90a97881cb14..31d9c1f58ec502c8ef2e2a008449784361725ee0 100644 ---- OP/op-node/rollup/chain_spec.go -+++ CELO/op-node/rollup/chain_spec.go -@@ -27,6 +27,12 @@ // From Fjord, the max sequencer drift for a given block timestamp should be learned via the - // ChainSpec instead of reading the rollup configuration field directly. - const maxSequencerDriftFjord = 1800 +
diff --git OP/packages/contracts-bedrock/src/cannon/interfaces/IMIPS.sol CELO/packages/contracts-bedrock/src/cannon/interfaces/IMIPS.sol +index 9617ddb9c0108c5e796fcaf68bc9f29cbb41b663..75f4e50f3ba31fe9f2ea141768ab8c1c835efb53 100644 +--- OP/packages/contracts-bedrock/src/cannon/interfaces/IMIPS.sol ++++ CELO/packages/contracts-bedrock/src/cannon/interfaces/IMIPS.sol +@@ -1,12 +1,17 @@ + // SPDX-License-Identifier: MIT + pragma solidity ^0.8.0;   -+// Normal OP chains wait for five confirmations while Celo waits for finalization, which can take -+// up to 3 * 32 blocks. So we should allow for more drift to compensate. -+// 3 * 32 - 5 = 91 blocks -+// 91 * 12s block time = 1092 -+const maxSequencerDriftCelo = maxSequencerDriftFjord + 1092 -+ - type ForkName string +-import { ISemver } from "src/universal/ISemver.sol"; ++import { ISemver } from "src/universal/interfaces/ISemver.sol"; + import { IPreimageOracle } from "src/cannon/interfaces/IPreimageOracle.sol";   - const ( -@@ -105,7 +111,11 @@ // this was a rollup configuration parameter. Since Fjord, it is a constant, so its effective value - // should always be queried via the ChainSpec. - func (s *ChainSpec) MaxSequencerDrift(t uint64) uint64 { - if s.IsFeatMaxSequencerDriftConstant(t) { -- return maxSequencerDriftFjord -+ if s.config.IsCel2(t) { -+ return maxSequencerDriftCelo -+ } else { -+ return maxSequencerDriftFjord -+ } - } - return s.config.MaxSequencerDrift + /// @title IMIPS + /// @notice Interface for the MIPS contract. + interface IMIPS is ISemver { ++ error InvalidMemoryProof(); ++ error InvalidRMWInstruction(); ++ + function oracle() external view returns (IPreimageOracle oracle_); + function step(bytes memory _stateData, bytes memory _proof, bytes32 _localContext) external returns (bytes32); ++ ++ function __constructor__(IPreimageOracle _oracle) external; }
@@ -26111,9 +127326,9 @@
@@ -26122,13 +127337,13 @@ @@ -26138,48 +127353,47 @@
-
+3
-
-3
+
+10
+
-1
-
diff --git OP/op-node/rollup/derive/frame.go CELO/op-node/rollup/derive/frame.go -index 0baa1e120a14e3439b6b185fe97da5845424eeac..7547aca7531d95b2d212e069a24150a689715303 100644 ---- OP/op-node/rollup/derive/frame.go -+++ CELO/op-node/rollup/derive/frame.go -@@ -8,10 +8,10 @@ "fmt" - "io" - ) -  --// Frames cannot be larger than 1 MB. - // Data transactions that carry frames are generally not larger than 128 KB due to L1 network conditions, - // but we leave space to grow larger anyway (gas limit allows for more data). --const MaxFrameLen = 1_000_000 -+// For AltDA, frames size can be larger. Setting to 16 MB as current blob limit for EigenDA. -+const MaxFrameLen = 16_000_000 +
diff --git OP/packages/contracts-bedrock/src/cannon/interfaces/IMIPS2.sol CELO/packages/contracts-bedrock/src/cannon/interfaces/IMIPS2.sol +index ea7033aea9074cf5f698300722df4a5ab9cc877b..8f57c0f636952fcbbb2d06097ddfde6ae2874d7c 100644 +--- OP/packages/contracts-bedrock/src/cannon/interfaces/IMIPS2.sol ++++ CELO/packages/contracts-bedrock/src/cannon/interfaces/IMIPS2.sol +@@ -1,10 +1,19 @@ + // SPDX-License-Identifier: MIT + pragma solidity ^0.8.0;   - // Data Format - // -@@ -85,7 +85,7 @@ if err := binary.Read(r, binary.BigEndian, &frameLength); err != nil { - return fmt.Errorf("reading frame_data_length: %w", eofAsUnexpectedMissing(err)) - } +-import { ISemver } from "src/universal/ISemver.sol"; ++import { ISemver } from "src/universal/interfaces/ISemver.sol"; ++import { IPreimageOracle } from "src/cannon/interfaces/IPreimageOracle.sol";   -- // Cap frame length to MaxFrameLen (currently 1MB) -+ // Cap frame length to MaxFrameLen - if frameLength > MaxFrameLen { - return fmt.Errorf("frame_data_length is too large: %d", frameLength) - }
+ /// @title IMIPS2 + /// @notice Interface for the MIPS2 contract. + interface IMIPS2 is ISemver { ++ error InvalidExitedValue(); ++ error InvalidMemoryProof(); ++ error InvalidSecondMemoryProof(); ++ error InvalidRMWInstruction(); ++ ++ function oracle() external view returns (IPreimageOracle oracle_); + function step(bytes memory _stateData, bytes memory _proof, bytes32 _localContext) external returns (bytes32); ++ ++ function __constructor__(IPreimageOracle _oracle) external; + }
-
diff --git OP/op-node/rollup/driver/config.go CELO/op-node/rollup/driver/config.go -index f4013b95e1de67a3c00c6d01d2886d2dc065e56e..3353db1eabe4dfc34880c1b03bf0c3d11d824ccc 100644 ---- OP/op-node/rollup/driver/config.go -+++ CELO/op-node/rollup/driver/config.go -@@ -20,4 +20,8 @@ - // SequencerMaxSafeLag is the maximum number of L2 blocks for restricting the distance between L2 safe and unsafe. - // Disabled if 0. - SequencerMaxSafeLag uint64 `json:"sequencer_max_safe_lag"` +
diff --git OP/packages/contracts-bedrock/src/cannon/libraries/CannonErrors.sol CELO/packages/contracts-bedrock/src/cannon/libraries/CannonErrors.sol +index e45cbaf9d8de6931c68fd349e9507a7070778984..3649852cec6f2fbc9654d614c8a7994e52f40659 100644 +--- OP/packages/contracts-bedrock/src/cannon/libraries/CannonErrors.sol ++++ CELO/packages/contracts-bedrock/src/cannon/libraries/CannonErrors.sol +@@ -54,3 +54,12 @@ error BondTransferFailed(); +  + /// @notice Thrown when the value of the exited boolean is not 0 or 1. + error InvalidExitedValue(); + -+ // SequencerUseFinalized is true when sequencer should use only finalized L1 blocks as origin. -+ // If this is set to true, the value of `SequencerConfDepth` is ignored. -+ SequencerUseFinalized bool `json:"sequencer_use_finalized"` - }
++/// @notice Thrown when reading an invalid memory ++error InvalidMemoryProof(); ++ ++/// @notice Thrown when the second memory location is invalid ++error InvalidSecondMemoryProof(); ++ ++/// @notice Thrown when an RMW instruction is expected, but a different instruction is provided. ++error InvalidRMWInstruction();
@@ -26241,13 +127459,13 @@ @@ -26257,51 +127475,274 @@
-
+9
-
-2
+
+84
+
-74
-
diff --git OP/op-node/rollup/driver/driver.go CELO/op-node/rollup/driver/driver.go -index 3a3272387821babf62f5b7d69f871f98d3fa8825..703579c4def3236fa3027958c380a1d4d749930e 100644 ---- OP/op-node/rollup/driver/driver.go -+++ CELO/op-node/rollup/driver/driver.go -@@ -17,6 +17,7 @@ "github.com/ethereum-optimism/optimism/op-node/rollup/derive" - "github.com/ethereum-optimism/optimism/op-node/rollup/engine" - "github.com/ethereum-optimism/optimism/op-node/rollup/event" - "github.com/ethereum-optimism/optimism/op-node/rollup/finality" -+ "github.com/ethereum-optimism/optimism/op-node/rollup/finalized" - "github.com/ethereum-optimism/optimism/op-node/rollup/sequencing" - "github.com/ethereum-optimism/optimism/op-node/rollup/status" - "github.com/ethereum-optimism/optimism/op-node/rollup/sync" -@@ -239,8 +240,14 @@ var sequencer sequencing.SequencerIface - if driverCfg.SequencerEnabled { - asyncGossiper := async.NewAsyncGossiper(driverCtx, network, log, metrics) - attrBuilder := derive.NewFetchingAttributesBuilder(cfg, l1, l2) -- sequencerConfDepth := confdepth.NewConfDepth(driverCfg.SequencerConfDepth, statusTracker.L1Head, l1) -- findL1Origin := sequencing.NewL1OriginSelector(log, cfg, sequencerConfDepth) +
diff --git OP/packages/contracts-bedrock/src/cannon/libraries/MIPSInstructions.sol CELO/packages/contracts-bedrock/src/cannon/libraries/MIPSInstructions.sol +index 0652bea0d0e1f723699446f66aa9b284fd43b322..a2402531c82d178e5aa9594536c061b37070030c 100644 +--- OP/packages/contracts-bedrock/src/cannon/libraries/MIPSInstructions.sol ++++ CELO/packages/contracts-bedrock/src/cannon/libraries/MIPSInstructions.sol +@@ -5,6 +5,26 @@ import { MIPSMemory } from "src/cannon/libraries/MIPSMemory.sol"; + import { MIPSState as st } from "src/cannon/libraries/MIPSState.sol"; +  + library MIPSInstructions { ++ uint32 internal constant OP_LOAD_LINKED = 0x30; ++ uint32 internal constant OP_STORE_CONDITIONAL = 0x38; ++ ++ struct CoreStepLogicParams { ++ /// @param opcode The opcode value parsed from insn_. ++ st.CpuScalars cpu; ++ /// @param registers The CPU registers. ++ uint32[32] registers; ++ /// @param memRoot The current merkle root of the memory. ++ bytes32 memRoot; ++ /// @param memProofOffset The offset in calldata specify where the memory merkle proof is located. ++ uint256 memProofOffset; ++ /// @param insn The current 32-bit instruction at the pc. ++ uint32 insn; ++ /// @param cpu The CPU scalar fields. ++ uint32 opcode; ++ /// @param fun The function value parsed from insn_. ++ uint32 fun; ++ } ++ + /// @param _pc The program counter. + /// @param _memRoot The current memory root. + /// @param _insnProofOffset The calldata offset of the memory proof for the current instruction. +@@ -30,91 +50,80 @@ } + } +  + /// @notice Execute core MIPS step logic. +- /// @notice _cpu The CPU scalar fields. +- /// @notice _registers The CPU registers. +- /// @notice _memRoot The current merkle root of the memory. +- /// @notice _memProofOffset The offset in calldata specify where the memory merkle proof is located. +- /// @param _insn The current 32-bit instruction at the pc. +- /// @param _opcode The opcode value parsed from insn_. +- /// @param _fun The function value parsed from insn_. + /// @return newMemRoot_ The updated merkle root of memory after any modifications, may be unchanged. +- function execMipsCoreStepLogic( +- st.CpuScalars memory _cpu, +- uint32[32] memory _registers, +- bytes32 _memRoot, +- uint256 _memProofOffset, +- uint32 _insn, +- uint32 _opcode, +- uint32 _fun +- ) ++ /// @return memUpdated_ True if memory was modified. ++ /// @return memAddr_ Holds the memory address that was updated if memUpdated_ is true. ++ function execMipsCoreStepLogic(CoreStepLogicParams memory _args) + internal + pure +- returns (bytes32 newMemRoot_) ++ returns (bytes32 newMemRoot_, bool memUpdated_, uint32 memAddr_) + { + unchecked { +- newMemRoot_ = _memRoot; ++ newMemRoot_ = _args.memRoot; ++ memUpdated_ = false; ++ memAddr_ = 0; +  + // j-type j/jal +- if (_opcode == 2 || _opcode == 3) { ++ if (_args.opcode == 2 || _args.opcode == 3) { + // Take top 4 bits of the next PC (its 256 MB region), and concatenate with the 26-bit offset +- uint32 target = (_cpu.nextPC & 0xF0000000) | (_insn & 0x03FFFFFF) << 2; +- handleJump(_cpu, _registers, _opcode == 2 ? 0 : 31, target); +- return newMemRoot_; ++ uint32 target = (_args.cpu.nextPC & 0xF0000000) | (_args.insn & 0x03FFFFFF) << 2; ++ handleJump(_args.cpu, _args.registers, _args.opcode == 2 ? 0 : 31, target); ++ return (newMemRoot_, memUpdated_, memAddr_); + } +  + // register fetch + uint32 rs = 0; // source register 1 value + uint32 rt = 0; // source register 2 / temp value +- uint32 rtReg = (_insn >> 16) & 0x1F; ++ uint32 rtReg = (_args.insn >> 16) & 0x1F; +  + // R-type or I-type (stores rt) +- rs = _registers[(_insn >> 21) & 0x1F]; ++ rs = _args.registers[(_args.insn >> 21) & 0x1F]; + uint32 rdReg = rtReg; +  +- if (_opcode == 0 || _opcode == 0x1c) { ++ if (_args.opcode == 0 || _args.opcode == 0x1c) { + // R-type (stores rd) +- rt = _registers[rtReg]; +- rdReg = (_insn >> 11) & 0x1F; +- } else if (_opcode < 0x20) { ++ rt = _args.registers[rtReg]; ++ rdReg = (_args.insn >> 11) & 0x1F; ++ } else if (_args.opcode < 0x20) { + // rt is SignExtImm + // don't sign extend for andi, ori, xori +- if (_opcode == 0xC || _opcode == 0xD || _opcode == 0xe) { ++ if (_args.opcode == 0xC || _args.opcode == 0xD || _args.opcode == 0xe) { + // ZeroExtImm +- rt = _insn & 0xFFFF; ++ rt = _args.insn & 0xFFFF; + } else { + // SignExtImm +- rt = signExtend(_insn & 0xFFFF, 16); ++ rt = signExtend(_args.insn & 0xFFFF, 16); + } +- } else if (_opcode >= 0x28 || _opcode == 0x22 || _opcode == 0x26) { ++ } else if (_args.opcode >= 0x28 || _args.opcode == 0x22 || _args.opcode == 0x26) { + // store rt value with store +- rt = _registers[rtReg]; ++ rt = _args.registers[rtReg]; +  + // store actual rt with lwl and lwr + rdReg = rtReg; + } +  +- if ((_opcode >= 4 && _opcode < 8) || _opcode == 1) { ++ if ((_args.opcode >= 4 && _args.opcode < 8) || _args.opcode == 1) { + handleBranch({ +- _cpu: _cpu, +- _registers: _registers, +- _opcode: _opcode, +- _insn: _insn, ++ _cpu: _args.cpu, ++ _registers: _args.registers, ++ _opcode: _args.opcode, ++ _insn: _args.insn, + _rtReg: rtReg, + _rs: rs + }); +- return newMemRoot_; ++ return (newMemRoot_, memUpdated_, memAddr_); + } +  + uint32 storeAddr = 0xFF_FF_FF_FF; + // memory fetch (all I-type) + // we do the load for stores also + uint32 mem = 0; +- if (_opcode >= 0x20) { ++ if (_args.opcode >= 0x20) { + // M[R[rs]+SignExtImm] +- rs += signExtend(_insn & 0xFFFF, 16); ++ rs += signExtend(_args.insn & 0xFFFF, 16); + uint32 addr = rs & 0xFFFFFFFC; +- mem = MIPSMemory.readMem(_memRoot, addr, _memProofOffset); +- if (_opcode >= 0x28 && _opcode != 0x30) { ++ mem = MIPSMemory.readMem(_args.memRoot, addr, _args.memProofOffset); ++ if (_args.opcode >= 0x28) { + // store + storeAddr = addr; + // store opcodes don't write back to a register +@@ -124,49 +133,58 @@ } +  + // ALU + // Note: swr outputs more than 4 bytes without the mask 0xffFFffFF +- uint32 val = executeMipsInstruction(_insn, _opcode, _fun, rs, rt, mem) & 0xffFFffFF; ++ uint32 val = executeMipsInstruction(_args.insn, _args.opcode, _args.fun, rs, rt, mem) & 0xffFFffFF; +  +- if (_opcode == 0 && _fun >= 8 && _fun < 0x1c) { +- if (_fun == 8 || _fun == 9) { ++ if (_args.opcode == 0 && _args.fun >= 8 && _args.fun < 0x1c) { ++ if (_args.fun == 8 || _args.fun == 9) { + // jr/jalr +- handleJump(_cpu, _registers, _fun == 8 ? 0 : rdReg, rs); +- return newMemRoot_; ++ handleJump(_args.cpu, _args.registers, _args.fun == 8 ? 0 : rdReg, rs); ++ return (newMemRoot_, memUpdated_, memAddr_); + } +  +- if (_fun == 0xa) { ++ if (_args.fun == 0xa) { + // movz +- handleRd(_cpu, _registers, rdReg, rs, rt == 0); +- return newMemRoot_; ++ handleRd(_args.cpu, _args.registers, rdReg, rs, rt == 0); ++ return (newMemRoot_, memUpdated_, memAddr_); + } +- if (_fun == 0xb) { ++ if (_args.fun == 0xb) { + // movn +- handleRd(_cpu, _registers, rdReg, rs, rt != 0); +- return newMemRoot_; ++ handleRd(_args.cpu, _args.registers, rdReg, rs, rt != 0); ++ return (newMemRoot_, memUpdated_, memAddr_); + } +  + // lo and hi registers + // can write back +- if (_fun >= 0x10 && _fun < 0x1c) { +- handleHiLo({ _cpu: _cpu, _registers: _registers, _fun: _fun, _rs: rs, _rt: rt, _storeReg: rdReg }); +- +- return newMemRoot_; ++ if (_args.fun >= 0x10 && _args.fun < 0x1c) { ++ handleHiLo({ ++ _cpu: _args.cpu, ++ _registers: _args.registers, ++ _fun: _args.fun, ++ _rs: rs, ++ _rt: rt, ++ _storeReg: rdReg ++ }); ++ return (newMemRoot_, memUpdated_, memAddr_); + } + } +  +- // stupid sc, write a 1 to rt +- if (_opcode == 0x38 && rtReg != 0) { +- _registers[rtReg] = 1; +- } +- + // write memory + if (storeAddr != 0xFF_FF_FF_FF) { +- newMemRoot_ = MIPSMemory.writeMem(storeAddr, _memProofOffset, val); ++ newMemRoot_ = MIPSMemory.writeMem(storeAddr, _args.memProofOffset, val); ++ memUpdated_ = true; ++ memAddr_ = storeAddr; + } +  + // write back the value to destination register +- handleRd(_cpu, _registers, rdReg, val, true); ++ handleRd(_args.cpu, _args.registers, rdReg, val, true); + -+ var seqL1Blocks sequencing.L1Blocks -+ if driverCfg.SequencerUseFinalized { -+ seqL1Blocks = finalized.NewFinalized(statusTracker.L1Finalized, l1) -+ } else { -+ seqL1Blocks = confdepth.NewConfDepth(driverCfg.SequencerConfDepth, statusTracker.L1Head, l1) -+ } -+ findL1Origin := sequencing.NewL1OriginSelector(log, cfg, seqL1Blocks) - sequencer = sequencing.NewSequencer(driverCtx, log, cfg, attrBuilder, findL1Origin, - sequencerStateListener, sequencerConductor, asyncGossiper, metrics) - sys.Register("sequencer", sequencer, opts)
++ return (newMemRoot_, memUpdated_, memAddr_); ++ } ++ } +  +- return newMemRoot_; ++ function signExtendImmediate(uint32 _insn) internal pure returns (uint32 offset_) { ++ unchecked { ++ return signExtend(_insn & 0xFFFF, 16); + } + } +  +@@ -417,14 +435,6 @@ else if (_opcode == 0x2e) { + uint32 val = _rt << (24 - (_rs & 3) * 8); + uint32 mask = uint32(0xFFFFFFFF) << (24 - (_rs & 3) * 8); + return (_mem & ~mask) | val; +- } +- // ll +- else if (_opcode == 0x30) { +- return _mem; +- } +- // sc +- else if (_opcode == 0x38) { +- return _rt; + } else { + revert("invalid instruction"); + }
@@ -26310,13 +127751,13 @@
- (new) + OP
@@ -26326,57 +127767,100 @@
-
+29
-
-0
+
+38
+
-7
-
diff --git OP/op-node/rollup/finalized/finalized.go CELO/op-node/rollup/finalized/finalized.go -new file mode 100644 -index 0000000000000000000000000000000000000000..47fbcc077e4f3726ce6ae66ad678ee3f5d21e149 ---- /dev/null -+++ CELO/op-node/rollup/finalized/finalized.go -@@ -0,0 +1,29 @@ -+package finalized -+ -+import ( -+ "context" -+ -+ "github.com/ethereum/go-ethereum" -+ -+ "github.com/ethereum-optimism/optimism/op-node/rollup/derive" -+ "github.com/ethereum-optimism/optimism/op-service/eth" -+) -+ -+type finalized struct { -+ derive.L1Fetcher -+ l1Finalized func() eth.L1BlockRef -+} -+ -+func NewFinalized(l1Finalized func() eth.L1BlockRef, fetcher derive.L1Fetcher) *finalized { -+ return &finalized{L1Fetcher: fetcher, l1Finalized: l1Finalized} -+} +
diff --git OP/packages/contracts-bedrock/src/cannon/libraries/MIPSMemory.sol CELO/packages/contracts-bedrock/src/cannon/libraries/MIPSMemory.sol +index 12106ed23ecc1f6ce5bf9e28ce207c2171ae665d..e88f51438ef4849b865c15c339b0ab8936b0757c 100644 +--- OP/packages/contracts-bedrock/src/cannon/libraries/MIPSMemory.sol ++++ CELO/packages/contracts-bedrock/src/cannon/libraries/MIPSMemory.sol +@@ -1,6 +1,8 @@ + // SPDX-License-Identifier: MIT + pragma solidity 0.8.15; +  ++import "src/cannon/libraries/CannonErrors.sol"; ++ + library MIPSMemory { + /// @notice Reads a 32-bit value from memory. + /// @param _memRoot The current memory root +@@ -8,6 +10,28 @@ /// @param _addr The address to read from. + /// @param _proofOffset The offset of the memory proof in calldata. + /// @return out_ The hashed MIPS state. + function readMem(bytes32 _memRoot, uint32 _addr, uint256 _proofOffset) internal pure returns (uint32 out_) { ++ bool valid; ++ (out_, valid) = readMemUnchecked(_memRoot, _addr, _proofOffset); ++ if (!valid) { ++ revert InvalidMemoryProof(); ++ } ++ } + -+func (f *finalized) L1BlockRefByNumber(ctx context.Context, num uint64) (eth.L1BlockRef, error) { -+ l1Finalized := f.l1Finalized() -+ if num == 0 || num <= l1Finalized.Number { -+ return f.L1Fetcher.L1BlockRefByNumber(ctx, num) -+ } -+ return eth.L1BlockRef{}, ethereum.NotFound -+} ++ /// @notice Reads a 32-bit value from memory. ++ /// @param _memRoot The current memory root ++ /// @param _addr The address to read from. ++ /// @param _proofOffset The offset of the memory proof in calldata. ++ /// @return out_ The hashed MIPS state. ++ /// valid_ Whether the proof is valid. ++ function readMemUnchecked( ++ bytes32 _memRoot, ++ uint32 _addr, ++ uint256 _proofOffset ++ ) ++ internal ++ pure ++ returns (uint32 out_, bool valid_) ++ { + unchecked { + validateMemoryProofAvailability(_proofOffset); + assembly { +@@ -38,14 +62,12 @@ case 1 { node := hashPair(sibling, node) } + } +  + // Verify the root matches. +- if iszero(eq(node, _memRoot)) { +- mstore(0, 0x0badf00d) +- revert(0, 32) ++ valid_ := eq(node, _memRoot) ++ if valid_ { ++ // Bits to shift = (32 - 4 - (addr % 32)) * 8 ++ let shamt := shl(3, sub(sub(32, 4), and(_addr, 31))) ++ out_ := and(shr(shamt, leaf), 0xFFffFFff) + } +- +- // Bits to shift = (32 - 4 - (addr % 32)) * 8 +- let shamt := shl(3, sub(sub(32, 4), and(_addr, 31))) +- out_ := and(shr(shamt, leaf), 0xFFffFFff) + } + } + } +@@ -95,6 +117,15 @@ newMemRoot_ := node + } + return newMemRoot_; + } ++ } + -+var _ derive.L1Fetcher = (*finalized)(nil)
++ /// @notice Verifies a memory proof. ++ /// @param _memRoot The expected memory root ++ /// @param _addr The _addr proven. ++ /// @param _proofOffset The offset of the memory proof in calldata. ++ /// @return valid_ True iff it is a valid proof. ++ function isValidProof(bytes32 _memRoot, uint32 _addr, uint256 _proofOffset) internal pure returns (bool valid_) { ++ (, valid_) = readMemUnchecked(_memRoot, _addr, _proofOffset); + } +  + /// @notice Computes the offset of a memory proof in the calldata.
@@ -26385,13 +127869,13 @@
- (new) + OP
@@ -26401,86 +127885,46 @@
-
+58
+
+8
-0
-
diff --git OP/op-node/rollup/finalized/finalized_test.go CELO/op-node/rollup/finalized/finalized_test.go -new file mode 100644 -index 0000000000000000000000000000000000000000..8fa397bf076ce5bbe754438d56d0dd13664c0be7 ---- /dev/null -+++ CELO/op-node/rollup/finalized/finalized_test.go -@@ -0,0 +1,58 @@ -+package finalized -+ -+import ( -+ "context" -+ "testing" -+ -+ "github.com/ethereum/go-ethereum" -+ "github.com/ethereum/go-ethereum/common" -+ "github.com/stretchr/testify/require" -+ -+ "github.com/ethereum-optimism/optimism/op-service/eth" -+ "github.com/ethereum-optimism/optimism/op-service/testutils" -+) -+ -+var testFinalHash = common.Hash{0x01} -+ -+type finalizedTest struct { -+ name string -+ final uint64 -+ hash common.Hash // hash of finalized block -+ req uint64 -+ pass bool -+} -+ -+func (ft *finalizedTest) Run(t *testing.T) { -+ l1Fetcher := &testutils.MockL1Source{} -+ l1Finalized := eth.L1BlockRef{Number: ft.final, Hash: ft.hash} -+ l1FinalizedGetter := func() eth.L1BlockRef { return l1Finalized } -+ -+ f := NewFinalized(l1FinalizedGetter, l1Fetcher) -+ -+ if ft.pass { -+ // no calls to the l1Fetcher are made if the block number is not finalized yet -+ l1Fetcher.ExpectL1BlockRefByNumber(ft.req, eth.L1BlockRef{Number: ft.req}, nil) -+ } -+ -+ out, err := f.L1BlockRefByNumber(context.Background(), ft.req) -+ l1Fetcher.AssertExpectations(t) -+ -+ if ft.pass { -+ require.NoError(t, err) -+ require.Equal(t, out, eth.L1BlockRef{Number: ft.req}) -+ } else { -+ require.Equal(t, ethereum.NotFound, err) -+ } -+} +
diff --git OP/packages/contracts-bedrock/src/cannon/libraries/MIPSState.sol CELO/packages/contracts-bedrock/src/cannon/libraries/MIPSState.sol +index d4431765c5b0c7805428840c86be40b72c6c54ea..2f76a2e0dda5d32e081ce8904aee5604a5e495d6 100644 +--- OP/packages/contracts-bedrock/src/cannon/libraries/MIPSState.sol ++++ CELO/packages/contracts-bedrock/src/cannon/libraries/MIPSState.sol +@@ -1,11 +1,19 @@ + // SPDX-License-Identifier: MIT + pragma solidity 0.8.15; +  ++import { InvalidExitedValue } from "src/cannon/libraries/CannonErrors.sol"; ++ + library MIPSState { + struct CpuScalars { + uint32 pc; + uint32 nextPC; + uint32 lo; + uint32 hi; ++ } + -+func TestFinalized(t *testing.T) { -+ testCases := []finalizedTest{ -+ {name: "finalized", final: 10, hash: testFinalHash, req: 10, pass: true}, -+ {name: "finalized past", final: 10, hash: testFinalHash, req: 8, pass: true}, -+ {name: "not finalized", final: 10, hash: testFinalHash, req: 11, pass: false}, -+ {name: "no L1 state", req: 10, pass: false}, -+ } -+ for _, tc := range testCases { -+ t.Run(tc.name, tc.Run) -+ } -+}
++ function assertExitedIsValid(uint32 exited) internal pure { ++ if (exited > 1) { ++ revert InvalidExitedValue(); ++ } + } + }
@@ -26489,13 +127933,13 @@ @@ -26505,35 +127949,109 @@
-
+5
-
-0
+
+21
+
-5
-
diff --git OP/op-node/rollup/status/status.go CELO/op-node/rollup/status/status.go -index b14f93843f721b7e0d991310ed1a130a46ddb664..1e7b97dccdec7717980a5707f60393930ca9f0c0 100644 ---- OP/op-node/rollup/status/status.go -+++ CELO/op-node/rollup/status/status.go -@@ -133,3 +133,8 @@ // L1Head is a helper function; the L1 head is closely monitored for confirmation-distance logic. - func (st *StatusTracker) L1Head() eth.L1BlockRef { - return st.SyncStatus().HeadL1 - } -+ -+// L1Finalized is a helper function to get the latest known finalized L1 block. -+func (st *StatusTracker) L1Finalized() eth.L1BlockRef { -+ return st.SyncStatus().FinalizedL1 -+}
+
diff --git OP/packages/contracts-bedrock/src/cannon/libraries/MIPSSyscalls.sol CELO/packages/contracts-bedrock/src/cannon/libraries/MIPSSyscalls.sol +index 0576dbc7ae2c7d87a2c1f2158bd7a9f71cb748ab..a835b6feef586e23cca6aef0b4588b4effd72eb4 100644 +--- OP/packages/contracts-bedrock/src/cannon/libraries/MIPSSyscalls.sol ++++ CELO/packages/contracts-bedrock/src/cannon/libraries/MIPSSyscalls.sol +@@ -41,6 +41,8 @@ uint32 internal constant SYS_GETTID = 4222; + uint32 internal constant SYS_FUTEX = 4238; + uint32 internal constant SYS_OPEN = 4005; + uint32 internal constant SYS_NANOSLEEP = 4166; ++ uint32 internal constant SYS_CLOCKGETTIME = 4263; ++ uint32 internal constant SYS_GETPID = 4020; + // unused syscalls + uint32 internal constant SYS_MUNMAP = 4091; + uint32 internal constant SYS_GETAFFINITY = 4240; +@@ -74,7 +76,6 @@ uint32 internal constant SYS_SETITIMER = 4104; + uint32 internal constant SYS_TIMERCREATE = 4257; + uint32 internal constant SYS_TIMERSETTIME = 4258; + uint32 internal constant SYS_TIMERDELETE = 4261; +- uint32 internal constant SYS_CLOCKGETTIME = 4263; +  + uint32 internal constant FD_STDIN = 0; + uint32 internal constant FD_STDOUT = 1; +@@ -97,6 +98,9 @@ uint64 internal constant FUTEX_NO_TIMEOUT = type(uint64).max; + uint32 internal constant FUTEX_EMPTY_ADDR = 0xFF_FF_FF_FF; +  + uint32 internal constant SCHED_QUANTUM = 100_000; ++ uint32 internal constant HZ = 10_000_000; ++ uint32 internal constant CLOCK_GETTIME_REALTIME_FLAG = 0; ++ uint32 internal constant CLOCK_GETTIME_MONOTONIC_FLAG = 1; + /// @notice Start of the data segment. + uint32 internal constant PROGRAM_BREAK = 0x40000000; + uint32 internal constant HEAP_END = 0x60000000; +@@ -198,13 +202,22 @@ /// @return newMemRoot_ The new memory root. + function handleSysRead(SysReadParams memory _args) + internal + view +- returns (uint32 v0_, uint32 v1_, uint32 newPreimageOffset_, bytes32 newMemRoot_) ++ returns ( ++ uint32 v0_, ++ uint32 v1_, ++ uint32 newPreimageOffset_, ++ bytes32 newMemRoot_, ++ bool memUpdated_, ++ uint32 memAddr_ ++ ) + { + unchecked { + v0_ = uint32(0); + v1_ = uint32(0); + newMemRoot_ = _args.memRoot; + newPreimageOffset_ = _args.preimageOffset; ++ memUpdated_ = false; ++ memAddr_ = 0; +  + // args: _a0 = fd, _a1 = addr, _a2 = count + // returns: v0_ = read, v1_ = err code +@@ -213,9 +226,10 @@ // Leave v0_ and v1_ zero: read nothing, no error + } + // pre-image oracle read + else if (_args.a0 == FD_PREIMAGE_READ) { ++ uint32 effAddr = _args.a1 & 0xFFffFFfc; + // verify proof is correct, and get the existing memory. + // mask the addr to align it to 4 bytes +- uint32 mem = MIPSMemory.readMem(_args.memRoot, _args.a1 & 0xFFffFFfc, _args.proofOffset); ++ uint32 mem = MIPSMemory.readMem(_args.memRoot, effAddr, _args.proofOffset); + // If the preimage key is a local key, localize it in the context of the caller. + if (uint8(_args.preimageKey[0]) == 1) { + _args.preimageKey = PreimageKeyLib.localize(_args.preimageKey, _args.localContext); +@@ -242,7 +256,9 @@ mem := or(and(mem, not(mask)), dat) // clear masked part of original memory, and insert data + } +  + // Write memory back +- newMemRoot_ = MIPSMemory.writeMem(_args.a1 & 0xFFffFFfc, _args.proofOffset, mem); ++ newMemRoot_ = MIPSMemory.writeMem(effAddr, _args.proofOffset, mem); ++ memUpdated_ = true; ++ memAddr_ = effAddr; + newPreimageOffset_ += uint32(datLen); + v0_ = uint32(datLen); + } +@@ -256,7 +272,7 @@ v0_ = 0xFFffFFff; + v1_ = EBADF; + } +  +- return (v0_, v1_, newPreimageOffset_, newMemRoot_); ++ return (v0_, v1_, newPreimageOffset_, newMemRoot_, memUpdated_, memAddr_); + } + } +
@@ -26542,13 +128060,13 @@
- OP + (new)
@@ -26558,53 +128076,316 @@
-
+6
+
+288
-0
-
diff --git OP/op-node/rollup/types.go CELO/op-node/rollup/types.go -index fec118567c569ce6b307410f04c67b166d893718..8ae0c17a3034ba338247cd126548963de5fafeb2 100644 ---- OP/op-node/rollup/types.go -+++ CELO/op-node/rollup/types.go -@@ -93,6 +93,7 @@ // a pre-mainnet Bedrock change that addresses findings of the Sherlock contest related to deposit attributes. - // "Regolith" is the loose deposited rock that sits on top of Bedrock. - // Active if RegolithTime != nil && L2 block timestamp >= *RegolithTime, inactive otherwise. - RegolithTime *uint64 `json:"regolith_time,omitempty"` -+ Cel2Time *uint64 `json:"cel2_time,omitempty"` -  - // CanyonTime sets the activation time of the Canyon network upgrade. - // Active if CanyonTime != nil && L2 block timestamp >= *CanyonTime, inactive otherwise. -@@ -407,6 +408,10 @@ func (c *Config) IsInterop(timestamp uint64) bool { - return c.InteropTime != nil && timestamp >= *c.InteropTime - } -  -+func (c *Config) IsCel2(timestamp uint64) bool { -+ return c.Cel2Time != nil && timestamp >= *c.Cel2Time -+} +
diff --git OP/packages/contracts-bedrock/src/celo/common/FixidityLib.sol CELO/packages/contracts-bedrock/src/celo/common/FixidityLib.sol +new file mode 100644 +index 0000000000000000000000000000000000000000..613da18562198968356b17cffa9890cb364b2063 +--- /dev/null ++++ CELO/packages/contracts-bedrock/src/celo/common/FixidityLib.sol +@@ -0,0 +1,288 @@ ++// SPDX-License-Identifier: LGPL-3.0-only ++pragma solidity ^0.8.15; + - func (c *Config) IsRegolithActivationBlock(l2BlockTime uint64) bool { - return c.IsRegolith(l2BlockTime) && - l2BlockTime >= c.BlockTime && -@@ -612,6 +617,7 @@ "granite_time", fmtForkTimeOrUnset(c.GraniteTime), - "holocene_time", fmtForkTimeOrUnset(c.HoloceneTime), - "interop_time", fmtForkTimeOrUnset(c.InteropTime), - "alt_da", c.AltDAConfig != nil, -+ "cel2_time", fmtForkTimeOrUnset(c.Cel2Time), - ) - } -
++/** ++ * @title FixidityLib ++ * @author Gadi Guy, Alberto Cuesta Canada ++ * @notice This library provides fixed point arithmetic with protection against ++ * overflow. ++ * All operations are done with uint256 and the operands must have been created ++ * with any of the newFrom* functions, which shift the comma digits() to the ++ * right and check for limits, or with wrap() which expects a number already ++ * in the internal representation of a fraction. ++ * When using this library be sure to use maxNewFixed() as the upper limit for ++ * creation of fixed point numbers. ++ * @dev All contained functions are pure and thus marked internal to be inlined ++ * on consuming contracts at compile time for gas efficiency. ++ */ ++library FixidityLib { ++ struct Fraction { ++ uint256 value; ++ } ++ ++ /** ++ * @notice Number of positions that the comma is shifted to the right. ++ */ ++ function digits() internal pure returns (uint8) { ++ return 24; ++ } ++ ++ uint256 private constant FIXED1_UINT = 1000000000000000000000000; ++ ++ /** ++ * @notice This is 1 in the fixed point units used in this library. ++ * @dev Test fixed1() equals 10^digits() ++ * Hardcoded to 24 digits. ++ */ ++ function fixed1() internal pure returns (Fraction memory) { ++ return Fraction(FIXED1_UINT); ++ } ++ ++ /** ++ * @notice Wrap a uint256 that represents a 24-decimal fraction in a Fraction ++ * struct. ++ * @param x Number that already represents a 24-decimal fraction. ++ * @return A Fraction struct with contents x. ++ */ ++ function wrap(uint256 x) internal pure returns (Fraction memory) { ++ return Fraction(x); ++ } ++ ++ /** ++ * @notice Unwraps the uint256 inside of a Fraction struct. ++ */ ++ function unwrap(Fraction memory x) internal pure returns (uint256) { ++ return x.value; ++ } ++ ++ /** ++ * @notice The amount of decimals lost on each multiplication operand. ++ * @dev Test mulPrecision() equals sqrt(fixed1) ++ */ ++ function mulPrecision() internal pure returns (uint256) { ++ return 1000000000000; ++ } ++ ++ /** ++ * @notice Maximum value that can be converted to fixed point. Optimize for deployment. ++ * @dev ++ * Test maxNewFixed() equals maxUint256() / fixed1() ++ */ ++ function maxNewFixed() internal pure returns (uint256) { ++ return 115792089237316195423570985008687907853269984665640564; ++ } ++ ++ /** ++ * @notice Converts a uint256 to fixed point Fraction ++ * @dev Test newFixed(0) returns 0 ++ * Test newFixed(1) returns fixed1() ++ * Test newFixed(maxNewFixed()) returns maxNewFixed() * fixed1() ++ * Test newFixed(maxNewFixed()+1) fails ++ */ ++ function newFixed(uint256 x) internal pure returns (Fraction memory) { ++ require(x <= maxNewFixed(), "can't create fixidity number larger than maxNewFixed()"); ++ return Fraction(x * FIXED1_UINT); ++ } ++ ++ /** ++ * @notice Converts a uint256 in the fixed point representation of this ++ * library to a non decimal. All decimal digits will be truncated. ++ */ ++ function fromFixed(Fraction memory x) internal pure returns (uint256) { ++ return x.value / FIXED1_UINT; ++ } ++ ++ /** ++ * @notice Converts two uint256 representing a fraction to fixed point units, ++ * equivalent to multiplying dividend and divisor by 10^digits(). ++ * @param numerator numerator must be <= maxNewFixed() ++ * @param denominator denominator must be <= maxNewFixed() and denominator can't be 0 ++ * @dev ++ * Test newFixedFraction(1,0) fails ++ * Test newFixedFraction(0,1) returns 0 ++ * Test newFixedFraction(1,1) returns fixed1() ++ * Test newFixedFraction(1,fixed1()) returns 1 ++ */ ++ function newFixedFraction(uint256 numerator, uint256 denominator) internal pure returns (Fraction memory) { ++ Fraction memory convertedNumerator = newFixed(numerator); ++ Fraction memory convertedDenominator = newFixed(denominator); ++ return divide(convertedNumerator, convertedDenominator); ++ } ++ ++ /** ++ * @notice Returns the integer part of a fixed point number. ++ * @dev ++ * Test integer(0) returns 0 ++ * Test integer(fixed1()) returns fixed1() ++ * Test integer(newFixed(maxNewFixed())) returns maxNewFixed()*fixed1() ++ */ ++ function integer(Fraction memory x) internal pure returns (Fraction memory) { ++ return Fraction((x.value / FIXED1_UINT) * FIXED1_UINT); // Can't overflow ++ } ++ ++ /** ++ * @notice Returns the fractional part of a fixed point number. ++ * In the case of a negative number the fractional is also negative. ++ * @dev ++ * Test fractional(0) returns 0 ++ * Test fractional(fixed1()) returns 0 ++ * Test fractional(fixed1()-1) returns 10^24-1 ++ */ ++ function fractional(Fraction memory x) internal pure returns (Fraction memory) { ++ return Fraction(x.value - (x.value / FIXED1_UINT) * FIXED1_UINT); // Can't overflow ++ } ++ ++ /** ++ * @notice x+y. ++ * @dev The maximum value that can be safely used as an addition operator is defined as ++ * maxFixedAdd = maxUint256()-1 / 2, or ++ * 57896044618658097711785492504343953926634992332820282019728792003956564819967. ++ * Test add(maxFixedAdd,maxFixedAdd) equals maxFixedAdd + maxFixedAdd ++ * Test add(maxFixedAdd+1,maxFixedAdd+1) throws ++ */ ++ function add(Fraction memory x, Fraction memory y) internal pure returns (Fraction memory) { ++ uint256 z = x.value + y.value; ++ require(z >= x.value, "add overflow detected"); ++ return Fraction(z); ++ } ++ ++ /** ++ * @notice x-y. ++ * @dev ++ * Test subtract(6, 10) fails ++ */ ++ function subtract(Fraction memory x, Fraction memory y) internal pure returns (Fraction memory) { ++ require(x.value >= y.value, "substraction underflow detected"); ++ return Fraction(x.value - y.value); ++ } ++ ++ /** ++ * @notice x*y. If any of the operators is higher than the max multiplier value it ++ * might overflow. ++ * @dev The maximum value that can be safely used as a multiplication operator ++ * (maxFixedMul) is calculated as sqrt(maxUint256()*fixed1()), ++ * or 340282366920938463463374607431768211455999999999999 ++ * Test multiply(0,0) returns 0 ++ * Test multiply(maxFixedMul,0) returns 0 ++ * Test multiply(0,maxFixedMul) returns 0 ++ * Test multiply(fixed1()/mulPrecision(),fixed1()*mulPrecision()) returns fixed1() ++ * Test multiply(maxFixedMul,maxFixedMul) is around maxUint256() ++ * Test multiply(maxFixedMul+1,maxFixedMul+1) fails ++ */ ++ function multiply(Fraction memory x, Fraction memory y) internal pure returns (Fraction memory) { ++ if (x.value == 0 || y.value == 0) return Fraction(0); ++ if (y.value == FIXED1_UINT) return x; ++ if (x.value == FIXED1_UINT) return y; ++ ++ // Separate into integer and fractional parts ++ // x = x1 + x2, y = y1 + y2 ++ uint256 x1 = integer(x).value / FIXED1_UINT; ++ uint256 x2 = fractional(x).value; ++ uint256 y1 = integer(y).value / FIXED1_UINT; ++ uint256 y2 = fractional(y).value; ++ ++ // (x1 + x2) * (y1 + y2) = (x1 * y1) + (x1 * y2) + (x2 * y1) + (x2 * y2) ++ uint256 x1y1 = x1 * y1; ++ if (x1 != 0) require(x1y1 / x1 == y1, "overflow x1y1 detected"); ++ ++ // x1y1 needs to be multiplied back by fixed1 ++ // solium-disable-next-line mixedcase ++ uint256 fixed_x1y1 = x1y1 * FIXED1_UINT; ++ if (x1y1 != 0) require(fixed_x1y1 / x1y1 == FIXED1_UINT, "overflow x1y1 * fixed1 detected"); ++ x1y1 = fixed_x1y1; ++ ++ uint256 x2y1 = x2 * y1; ++ if (x2 != 0) require(x2y1 / x2 == y1, "overflow x2y1 detected"); ++ ++ uint256 x1y2 = x1 * y2; ++ if (x1 != 0) require(x1y2 / x1 == y2, "overflow x1y2 detected"); ++ ++ x2 = x2 / mulPrecision(); ++ y2 = y2 / mulPrecision(); ++ uint256 x2y2 = x2 * y2; ++ if (x2 != 0) require(x2y2 / x2 == y2, "overflow x2y2 detected"); ++ ++ // result = fixed1() * x1 * y1 + x1 * y2 + x2 * y1 + x2 * y2 / fixed1(); ++ Fraction memory result = Fraction(x1y1); ++ result = add(result, Fraction(x2y1)); // Add checks for overflow ++ result = add(result, Fraction(x1y2)); // Add checks for overflow ++ result = add(result, Fraction(x2y2)); // Add checks for overflow ++ return result; ++ } ++ ++ /** ++ * @notice 1/x ++ * @dev ++ * Test reciprocal(0) fails ++ * Test reciprocal(fixed1()) returns fixed1() ++ * Test reciprocal(fixed1()*fixed1()) returns 1 // Testing how the fractional is truncated ++ * Test reciprocal(1+fixed1()*fixed1()) returns 0 // Testing how the fractional is truncated ++ * Test reciprocal(newFixedFraction(1, 1e24)) returns newFixed(1e24) ++ */ ++ function reciprocal(Fraction memory x) internal pure returns (Fraction memory) { ++ require(x.value != 0, "can't call reciprocal(0)"); ++ return Fraction((FIXED1_UINT * FIXED1_UINT) / x.value); // Can't overflow ++ } ++ ++ /** ++ * @notice x/y. If the dividend is higher than the max dividend value, it ++ * might overflow. You can use multiply(x,reciprocal(y)) instead. ++ * @dev The maximum value that can be safely used as a dividend (maxNewFixed) is defined as ++ * divide(maxNewFixed,newFixedFraction(1,fixed1())) is around maxUint256(). ++ * This yields the value 115792089237316195423570985008687907853269984665640564. ++ * Test maxNewFixed equals maxUint256()/fixed1() ++ * Test divide(maxNewFixed,1) equals maxNewFixed*(fixed1) ++ * Test divide(maxNewFixed+1,multiply(mulPrecision(),mulPrecision())) throws ++ * Test divide(fixed1(),0) fails ++ * Test divide(maxNewFixed,1) = maxNewFixed*(10^digits()) ++ * Test divide(maxNewFixed+1,1) throws ++ */ ++ function divide(Fraction memory x, Fraction memory y) internal pure returns (Fraction memory) { ++ require(y.value != 0, "can't divide by 0"); ++ uint256 X = x.value * FIXED1_UINT; ++ require(X / FIXED1_UINT == x.value, "overflow at divide"); ++ return Fraction(X / y.value); ++ } ++ ++ /** ++ * @notice x > y ++ */ ++ function gt(Fraction memory x, Fraction memory y) internal pure returns (bool) { ++ return x.value > y.value; ++ } ++ ++ /** ++ * @notice x >= y ++ */ ++ function gte(Fraction memory x, Fraction memory y) internal pure returns (bool) { ++ return x.value >= y.value; ++ } ++ ++ /** ++ * @notice x < y ++ */ ++ function lt(Fraction memory x, Fraction memory y) internal pure returns (bool) { ++ return x.value < y.value; ++ } ++ ++ /** ++ * @notice x <= y ++ */ ++ function lte(Fraction memory x, Fraction memory y) internal pure returns (bool) { ++ return x.value <= y.value; ++ } ++ ++ /** ++ * @notice x == y ++ */ ++ function equals(Fraction memory x, Fraction memory y) internal pure returns (bool) { ++ return x.value == y.value; ++ } ++ ++ /** ++ * @notice x <= 1 ++ */ ++ function isProperFraction(Fraction memory x) internal pure returns (bool) { ++ return lte(x, fixed1()); ++ } ++}
@@ -26613,13 +128394,13 @@
- OP + (new)
@@ -26629,239 +128410,41 @@
-
+6
-
-5
+
+13
+
-0
-
diff --git OP/op-node/service.go CELO/op-node/service.go -index 723c6febb321f3e01ed6db0088879f2cff0af051..2b2f955e2d71ed1396f10c2e4fba5822a8516872 100644 ---- OP/op-node/service.go -+++ CELO/op-node/service.go -@@ -191,11 +191,12 @@ } -  - func NewDriverConfig(ctx *cli.Context) *driver.Config { - return &driver.Config{ -- VerifierConfDepth: ctx.Uint64(flags.VerifierL1Confs.Name), -- SequencerConfDepth: ctx.Uint64(flags.SequencerL1Confs.Name), -- SequencerEnabled: ctx.Bool(flags.SequencerEnabledFlag.Name), -- SequencerStopped: ctx.Bool(flags.SequencerStoppedFlag.Name), -- SequencerMaxSafeLag: ctx.Uint64(flags.SequencerMaxSafeLagFlag.Name), -+ VerifierConfDepth: ctx.Uint64(flags.VerifierL1Confs.Name), -+ SequencerConfDepth: ctx.Uint64(flags.SequencerL1Confs.Name), -+ SequencerEnabled: ctx.Bool(flags.SequencerEnabledFlag.Name), -+ SequencerStopped: ctx.Bool(flags.SequencerStoppedFlag.Name), -+ SequencerMaxSafeLag: ctx.Uint64(flags.SequencerMaxSafeLagFlag.Name), -+ SequencerUseFinalized: ctx.Bool(flags.SequencerUseFinalizedL1Flag.Name), - } - } -
- - - - - -
- -
- - - - -
- -
-
-
- - -
-
- -
-
-
- - -
- -
-
-
- - -
-
- -
-
-
- - -
- -
-
-
- - -
-
- -
-
-
- - -
- -
-
-
- - -
-
- -
-
-
- - -
- -
-
-
- - -
-
- -
-
-
- - -
-
-
-
@@ -26870,13 +128453,13 @@
- OP + (new)
@@ -26886,163 +128469,106 @@
-
+1
-
-1
+
+18
+
-0
-
diff --git OP/ops-bedrock/l2-op-geth.Dockerfile CELO/ops-bedrock/l2-op-geth.Dockerfile -index c66bac56da81bde5eeba4231b01a43d8ddff37a7..e3138abb9be1ade7e2a4a029c3d0ccc173f422df 100644 ---- OP/ops-bedrock/l2-op-geth.Dockerfile -+++ CELO/ops-bedrock/l2-op-geth.Dockerfile -@@ -1,4 +1,4 @@ --FROM us-docker.pkg.dev/oplabs-tools-artifacts/images/op-geth:optimism -+FROM --platform=linux/amd64 us-west1-docker.pkg.dev/blockchaintestsglobaltestnet/dev-images/op-geth@sha256:fab76a990c21271419a40dfe5d28e30905869183b18ee9e6f711fe562365bc8e -  - RUN apk add --no-cache jq -
-
- - - -
-
- -
-
- - - -
- -
-
-
- - -
-
- -
+
diff --git OP/packages/contracts-bedrock/src/celo/common/Initializable.sol CELO/packages/contracts-bedrock/src/celo/common/Initializable.sol +new file mode 100644 +index 0000000000000000000000000000000000000000..92baac5494d3b0324d3d506d0607f38199028b30 +--- /dev/null ++++ CELO/packages/contracts-bedrock/src/celo/common/Initializable.sol +@@ -0,0 +1,18 @@ ++// SPDX-License-Identifier: MIT ++pragma solidity ^0.8.15; ++ ++contract Initializable { ++ bool public initialized; ++ ++ constructor(bool testingDeployment) { ++ if (!testingDeployment) { ++ initialized = true; ++ } ++ } ++ ++ modifier initializer() { ++ require(!initialized, "contract already initialized"); ++ initialized = true; ++ _; ++ } ++}
-
-
@@ -27633,13 +129775,13 @@
- OP + (new)
@@ -27649,114 +129791,271 @@
-
+85
+
+253
-0
-
diff --git OP/op-alt-da/damock.go CELO/op-alt-da/damock.go -index b56b73fdfcc90519bcd4fad6290f0868d3ee9ec9..0db129171a82232b45a1e8c256d663fa4eba67d5 100644 ---- OP/op-alt-da/damock.go -+++ CELO/op-alt-da/damock.go -@@ -4,8 +4,12 @@ import ( - "context" - "errors" - "io" -+ "net/http" -+ "sync" -+ "time" -  - "github.com/ethereum-optimism/optimism/op-service/eth" -+ "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/ethdb/memorydb" - "github.com/ethereum/go-ethereum/log" -@@ -99,3 +103,84 @@ - func (d *AltDADisabled) AdvanceL1Origin(ctx context.Context, l1 L1Fetcher, blockId eth.BlockID) error { - return ErrNotEnabled - } +
diff --git OP/packages/contracts-bedrock/src/celo/common/linkedlists/SortedLinkedListWithMedian.sol CELO/packages/contracts-bedrock/src/celo/common/linkedlists/SortedLinkedListWithMedian.sol +new file mode 100644 +index 0000000000000000000000000000000000000000..458ef554220772c97273526478a794885fa6ac45 +--- /dev/null ++++ CELO/packages/contracts-bedrock/src/celo/common/linkedlists/SortedLinkedListWithMedian.sol +@@ -0,0 +1,253 @@ ++// SPDX-License-Identifier: MIT ++pragma solidity ^0.8.15; + -+// FakeDAServer is a fake DA server for e2e tests. -+// It is a small wrapper around DAServer that allows for setting request latencies, -+// to mimic a DA service with slow responses (eg. eigenDA with 10 min batching interval). -+type FakeDAServer struct { -+ *DAServer -+ putRequestLatency time.Duration -+ getRequestLatency time.Duration -+} ++import "./LinkedList.sol"; ++import "./SortedLinkedList.sol"; + -+func NewFakeDAServer(host string, port int, log log.Logger) *FakeDAServer { -+ store := NewMemStore() -+ fakeDAServer := &FakeDAServer{ -+ DAServer: NewDAServer(host, port, store, log, true), -+ putRequestLatency: 0, -+ getRequestLatency: 0, -+ } -+ return fakeDAServer -+} ++/** ++ * @title Maintains a sorted list of unsigned ints keyed by bytes32. ++ */ ++library SortedLinkedListWithMedian { ++ using SortedLinkedList for SortedLinkedList.List; + -+func (s *FakeDAServer) HandleGet(w http.ResponseWriter, r *http.Request) { -+ time.Sleep(s.getRequestLatency) -+ s.DAServer.HandleGet(w, r) -+} ++ enum MedianAction { ++ None, ++ Lesser, ++ Greater ++ } + -+func (s *FakeDAServer) HandlePut(w http.ResponseWriter, r *http.Request) { -+ time.Sleep(s.putRequestLatency) -+ s.DAServer.HandlePut(w, r) -+} ++ enum MedianRelation { ++ Undefined, ++ Lesser, ++ Greater, ++ Equal ++ } + -+func (s *FakeDAServer) Start() error { -+ err := s.DAServer.Start() -+ if err != nil { -+ return err -+ } -+ // Override the HandleGet/Put method registrations -+ mux := http.NewServeMux() -+ mux.HandleFunc("/get/", s.HandleGet) -+ mux.HandleFunc("/put/", s.HandlePut) -+ s.httpServer.Handler = mux -+ return nil -+} ++ struct List { ++ SortedLinkedList.List list; ++ bytes32 median; ++ mapping(bytes32 => MedianRelation) relation; ++ } + -+func (s *FakeDAServer) SetPutRequestLatency(latency time.Duration) { -+ s.putRequestLatency = latency -+} ++ /** ++ * @notice Inserts an element into a doubly linked list. ++ * @param list A storage pointer to the underlying list. ++ * @param key The key of the element to insert. ++ * @param value The element value. ++ * @param lesserKey The key of the element less than the element to insert. ++ * @param greaterKey The key of the element greater than the element to insert. ++ */ ++ function insert(List storage list, bytes32 key, uint256 value, bytes32 lesserKey, bytes32 greaterKey) internal { ++ list.list.insert(key, value, lesserKey, greaterKey); ++ LinkedList.Element storage element = list.list.list.elements[key]; + -+func (s *FakeDAServer) SetGetRequestLatency(latency time.Duration) { -+ s.getRequestLatency = latency -+} ++ MedianAction action = MedianAction.None; ++ if (list.list.list.numElements == 1) { ++ list.median = key; ++ list.relation[key] = MedianRelation.Equal; ++ } else if (list.list.list.numElements % 2 == 1) { ++ // When we have an odd number of elements, and the element that we inserted is less than ++ // the previous median, we need to slide the median down one element, since we had previously ++ // selected the greater of the two middle elements. ++ if (element.previousKey == bytes32(0) || list.relation[element.previousKey] == MedianRelation.Lesser) { ++ action = MedianAction.Lesser; ++ list.relation[key] = MedianRelation.Lesser; ++ } else { ++ list.relation[key] = MedianRelation.Greater; ++ } ++ } else { ++ // When we have an even number of elements, and the element that we inserted is greater than ++ // the previous median, we need to slide the median up one element, since we always select ++ // the greater of the two middle elements. ++ if (element.nextKey == bytes32(0) || list.relation[element.nextKey] == MedianRelation.Greater) { ++ action = MedianAction.Greater; ++ list.relation[key] = MedianRelation.Greater; ++ } else { ++ list.relation[key] = MedianRelation.Lesser; ++ } ++ } ++ updateMedian(list, action); ++ } + -+type MemStore struct { -+ db map[string][]byte -+ lock sync.RWMutex -+} ++ /** ++ * @notice Removes an element from the doubly linked list. ++ * @param list A storage pointer to the underlying list. ++ * @param key The key of the element to remove. ++ */ ++ function remove(List storage list, bytes32 key) internal { ++ MedianAction action = MedianAction.None; ++ if (list.list.list.numElements == 0) { ++ list.median = bytes32(0); ++ } else if (list.list.list.numElements % 2 == 0) { ++ // When we have an even number of elements, we always choose the higher of the two medians. ++ // Thus, if the element we're removing is greaterKey than or equal to the median we need to ++ // slide the median left by one. ++ if (list.relation[key] == MedianRelation.Greater || list.relation[key] == MedianRelation.Equal) { ++ action = MedianAction.Lesser; ++ } ++ } else { ++ // When we don't have an even number of elements, we just choose the median value. ++ // Thus, if the element we're removing is less than or equal to the median, we need to slide ++ // median right by one. ++ if (list.relation[key] == MedianRelation.Lesser || list.relation[key] == MedianRelation.Equal) { ++ action = MedianAction.Greater; ++ } ++ } ++ updateMedian(list, action); + -+func NewMemStore() *MemStore { -+ return &MemStore{ -+ db: make(map[string][]byte), -+ } -+} ++ list.list.remove(key); ++ } + -+// Get retrieves the given key if it's present in the key-value store. -+func (s *MemStore) Get(ctx context.Context, key []byte) ([]byte, error) { -+ s.lock.RLock() -+ defer s.lock.RUnlock() ++ /** ++ * @notice Updates an element in the list. ++ * @param list A storage pointer to the underlying list. ++ * @param key The element key. ++ * @param value The element value. ++ * @param lesserKey The key of the element will be just left of `key` after the update. ++ * @param greaterKey The key of the element will be just right of `key` after the update. ++ * @dev Note that only one of "lesserKey" or "greaterKey" needs to be correct to reduce friction. ++ */ ++ function update(List storage list, bytes32 key, uint256 value, bytes32 lesserKey, bytes32 greaterKey) internal { ++ remove(list, key); ++ insert(list, key, value, lesserKey, greaterKey); ++ } + -+ if entry, ok := s.db[string(key)]; ok { -+ return common.CopyBytes(entry), nil -+ } -+ return nil, ErrNotFound -+} ++ /** ++ * @notice Inserts an element at the tail of the doubly linked list. ++ * @param list A storage pointer to the underlying list. ++ * @param key The key of the element to insert. ++ */ ++ function push(List storage list, bytes32 key) internal { ++ insert(list, key, 0, bytes32(0), list.list.list.tail); ++ } + -+// Put inserts the given value into the key-value store. -+func (s *MemStore) Put(ctx context.Context, key []byte, value []byte) error { -+ s.lock.Lock() -+ defer s.lock.Unlock() ++ /** ++ * @notice Removes N elements from the head of the list and returns their keys. ++ * @param list A storage pointer to the underlying list. ++ * @param n The number of elements to pop. ++ * @return The keys of the popped elements. ++ */ ++ function popN(List storage list, uint256 n) internal returns (bytes32[] memory) { ++ require(n <= list.list.list.numElements, "not enough elements"); ++ bytes32[] memory keys = new bytes32[](n); ++ for (uint256 i = 0; i < n; i++) { ++ bytes32 key = list.list.list.head; ++ keys[i] = key; ++ remove(list, key); ++ } ++ return keys; ++ } + -+ s.db[string(key)] = common.CopyBytes(value) -+ return nil ++ /** ++ * @notice Returns whether or not a particular key is present in the sorted list. ++ * @param list A storage pointer to the underlying list. ++ * @param key The element key. ++ * @return Whether or not the key is in the sorted list. ++ */ ++ function contains(List storage list, bytes32 key) internal view returns (bool) { ++ return list.list.contains(key); ++ } ++ ++ /** ++ * @notice Returns the value for a particular key in the sorted list. ++ * @param list A storage pointer to the underlying list. ++ * @param key The element key. ++ * @return The element value. ++ */ ++ function getValue(List storage list, bytes32 key) internal view returns (uint256) { ++ return list.list.values[key]; ++ } ++ ++ /** ++ * @notice Returns the median value of the sorted list. ++ * @param list A storage pointer to the underlying list. ++ * @return The median value. ++ */ ++ function getMedianValue(List storage list) internal view returns (uint256) { ++ return getValue(list, list.median); ++ } ++ ++ /** ++ * @notice Returns the key of the first element in the list. ++ * @param list A storage pointer to the underlying list. ++ * @return The key of the first element in the list. ++ */ ++ function getHead(List storage list) internal view returns (bytes32) { ++ return list.list.list.head; ++ } ++ ++ /** ++ * @notice Returns the key of the median element in the list. ++ * @param list A storage pointer to the underlying list. ++ * @return The key of the median element in the list. ++ */ ++ function getMedian(List storage list) internal view returns (bytes32) { ++ return list.median; ++ } ++ ++ /** ++ * @notice Returns the key of the last element in the list. ++ * @param list A storage pointer to the underlying list. ++ * @return The key of the last element in the list. ++ */ ++ function getTail(List storage list) internal view returns (bytes32) { ++ return list.list.list.tail; ++ } ++ ++ /** ++ * @notice Returns the number of elements in the list. ++ * @param list A storage pointer to the underlying list. ++ * @return The number of elements in the list. ++ */ ++ function getNumElements(List storage list) internal view returns (uint256) { ++ return list.list.list.numElements; ++ } ++ ++ /** ++ * @notice Gets all elements from the doubly linked list. ++ * @param list A storage pointer to the underlying list. ++ * @return Array of all keys in the list. ++ * @return Values corresponding to keys, which will be ordered largest to smallest. ++ * @return Array of relations to median of corresponding list elements. ++ */ ++ function getElements(List storage list) ++ internal ++ view ++ returns (bytes32[] memory, uint256[] memory, MedianRelation[] memory) ++ { ++ bytes32[] memory keys = getKeys(list); ++ uint256[] memory values = new uint256[](keys.length); ++ MedianRelation[] memory relations = new MedianRelation[](keys.length); ++ for (uint256 i = 0; i < keys.length; i++) { ++ values[i] = list.list.values[keys[i]]; ++ relations[i] = list.relation[keys[i]]; ++ } ++ return (keys, values, relations); ++ } ++ ++ /** ++ * @notice Gets all element keys from the doubly linked list. ++ * @param list A storage pointer to the underlying list. ++ * @return All element keys from head to tail. ++ */ ++ function getKeys(List storage list) internal view returns (bytes32[] memory) { ++ return list.list.getKeys(); ++ } ++ ++ /** ++ * @notice Moves the median pointer right or left of its current value. ++ * @param list A storage pointer to the underlying list. ++ * @param action Which direction to move the median pointer. ++ */ ++ function updateMedian(List storage list, MedianAction action) private { ++ LinkedList.Element storage previousMedian = list.list.list.elements[list.median]; ++ if (action == MedianAction.Lesser) { ++ list.relation[list.median] = MedianRelation.Greater; ++ list.median = previousMedian.previousKey; ++ } else if (action == MedianAction.Greater) { ++ list.relation[list.median] = MedianRelation.Lesser; ++ list.median = previousMedian.nextKey; ++ } ++ list.relation[list.median] = MedianRelation.Equal; ++ } +}
@@ -27764,9 +130063,9 @@
@@ -27775,13 +130074,13 @@
- OP + (new)
@@ -27791,37 +130090,86 @@
-
+2
-
-2
+
+58
+
-0
-
diff --git OP/op-alt-da/daserver.go CELO/op-alt-da/daserver.go -index ef43fd27fef3c8cfbff2b08795c16be3088ed078..94446944b5430fbc3026da31196e23ccee169ad2 100644 ---- OP/op-alt-da/daserver.go -+++ CELO/op-alt-da/daserver.go -@@ -187,8 +187,8 @@ w.WriteHeader(http.StatusOK) - } - } -  --func (b *DAServer) Endpoint() string { -- return b.listener.Addr().String() -+func (b *DAServer) HttpEndpoint() string { -+ return fmt.Sprintf("http://%s", b.listener.Addr().String()) - } -  - func (b *DAServer) Stop() error {
+
diff --git OP/packages/contracts-bedrock/src/celo/governance/interfaces/IElection.sol CELO/packages/contracts-bedrock/src/celo/governance/interfaces/IElection.sol +new file mode 100644 +index 0000000000000000000000000000000000000000..f099ce364a2705987e0b242c07fbc1871371077b +--- /dev/null ++++ CELO/packages/contracts-bedrock/src/celo/governance/interfaces/IElection.sol +@@ -0,0 +1,58 @@ ++// SPDX-License-Identifier: LGPL-3.0-only ++pragma solidity ^0.8.15; ++ ++interface IElection { ++ function electValidatorSigners() external view returns (address[] memory); ++ function electNValidatorSigners(uint256, uint256) external view returns (address[] memory); ++ function vote(address, uint256, address, address) external returns (bool); ++ function activate(address) external returns (bool); ++ function revokeActive(address, uint256, address, address, uint256) external returns (bool); ++ function revokeAllActive(address, address, address, uint256) external returns (bool); ++ function revokePending(address, uint256, address, address, uint256) external returns (bool); ++ function markGroupIneligible(address) external; ++ function markGroupEligible(address, address, address) external; ++ function allowedToVoteOverMaxNumberOfGroups(address) external returns (bool); ++ function forceDecrementVotes( ++ address, ++ uint256, ++ address[] calldata, ++ address[] calldata, ++ uint256[] calldata ++ ) ++ external ++ returns (uint256); ++ function setAllowedToVoteOverMaxNumberOfGroups(bool flag) external; ++ ++ // view functions ++ function getElectableValidators() external view returns (uint256, uint256); ++ function getElectabilityThreshold() external view returns (uint256); ++ function getNumVotesReceivable(address) external view returns (uint256); ++ function getTotalVotes() external view returns (uint256); ++ function getActiveVotes() external view returns (uint256); ++ function getTotalVotesByAccount(address) external view returns (uint256); ++ function getPendingVotesForGroupByAccount(address, address) external view returns (uint256); ++ function getActiveVotesForGroupByAccount(address, address) external view returns (uint256); ++ function getTotalVotesForGroupByAccount(address, address) external view returns (uint256); ++ function getActiveVoteUnitsForGroupByAccount(address, address) external view returns (uint256); ++ function getTotalVotesForGroup(address) external view returns (uint256); ++ function getActiveVotesForGroup(address) external view returns (uint256); ++ function getPendingVotesForGroup(address) external view returns (uint256); ++ function getGroupEligibility(address) external view returns (bool); ++ function getGroupEpochRewards(address, uint256, uint256[] calldata) external view returns (uint256); ++ function getGroupsVotedForByAccount(address) external view returns (address[] memory); ++ function getEligibleValidatorGroups() external view returns (address[] memory); ++ function getTotalVotesForEligibleValidatorGroups() external view returns (address[] memory, uint256[] memory); ++ function getCurrentValidatorSigners() external view returns (address[] memory); ++ function canReceiveVotes(address, uint256) external view returns (bool); ++ function hasActivatablePendingVotes(address, address) external view returns (bool); ++ function validatorSignerAddressFromCurrentSet(uint256 index) external view returns (address); ++ function numberValidatorsInCurrentSet() external view returns (uint256); ++ ++ // only owner ++ function setElectableValidators(uint256, uint256) external returns (bool); ++ function setMaxNumGroupsVotedFor(uint256) external returns (bool); ++ function setElectabilityThreshold(uint256) external returns (bool); ++ ++ // only VM ++ function distributeEpochRewards(address, uint256, address, address) external; ++}
@@ -27830,13 +130178,13 @@
- OP + (new)
@@ -27846,230 +130194,52 @@
-
+82
-
-26
+
+24
+
-0
-
diff --git OP/op-batcher/batcher/driver.go CELO/op-batcher/batcher/driver.go -index 0af4c86ca40a98d732b28fa706a297ead85fe49e..3fcffa08d127c1f4cb93c889b5e7a94e570a3fc3 100644 ---- OP/op-batcher/batcher/driver.go -+++ CELO/op-batcher/batcher/driver.go -@@ -22,6 +22,7 @@ "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/txpool" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/log" -+ "golang.org/x/sync/errgroup" - ) -  - var ( -@@ -302,6 +303,12 @@ defer l.wg.Done() -  - receiptsCh := make(chan txmgr.TxReceipt[txRef]) - queue := txmgr.NewQueue[txRef](l.killCtx, l.Txmgr, l.Config.MaxPendingTransactions) -+ daGroup := &errgroup.Group{} -+ // errgroup with limit of 0 means no goroutine is able to run concurrently, -+ // so we only set the limit if it is greater than 0. -+ if l.Config.MaxConcurrentDARequests > 0 { -+ daGroup.SetLimit(int(l.Config.MaxConcurrentDARequests)) -+ } -  - // start the receipt/result processing loop - receiptLoopDone := make(chan struct{}) -@@ -339,9 +346,20 @@ ticker := time.NewTicker(l.Config.PollInterval) - defer ticker.Stop() -  - publishAndWait := func() { -- l.publishStateToL1(queue, receiptsCh) -+ l.publishStateToL1(queue, receiptsCh, daGroup) - if !l.Txmgr.IsClosed() { -- queue.Wait() -+ if l.Config.UseAltDA { -+ l.Log.Info("Waiting for altDA writes to complete...") -+ err := daGroup.Wait() -+ if err != nil { -+ l.Log.Error("Error returned by one of the altda goroutines waited on", "err", err) -+ } -+ } -+ l.Log.Info("Waiting for L1 txs to be confirmed...") -+ err := queue.Wait() -+ if err != nil { -+ l.Log.Error("Error returned by one of the txmgr goroutines waited on", "err", err) -+ } - } else { - l.Log.Info("Txmgr is closed, remaining channel data won't be sent") - } -@@ -368,7 +386,7 @@ publishAndWait() - l.clearState(l.shutdownCtx) - continue - } -- l.publishStateToL1(queue, receiptsCh) -+ l.publishStateToL1(queue, receiptsCh, daGroup) - case <-l.shutdownCtx.Done(): - if l.Txmgr.IsClosed() { - l.Log.Info("Txmgr is closed, remaining channel data won't be sent") -@@ -425,7 +443,7 @@ } -  - // publishStateToL1 queues up all pending TxData to be published to the L1, returning when there is - // no more data to queue for publishing or if there was an error queing the data. --func (l *BatchSubmitter) publishStateToL1(queue *txmgr.Queue[txRef], receiptsCh chan txmgr.TxReceipt[txRef]) { -+func (l *BatchSubmitter) publishStateToL1(queue *txmgr.Queue[txRef], receiptsCh chan txmgr.TxReceipt[txRef], daGroup *errgroup.Group) { - for { - // if the txmgr is closed, we stop the transaction sending - if l.Txmgr.IsClosed() { -@@ -436,7 +454,7 @@ if !l.checkTxpool(queue, receiptsCh) { - l.Log.Info("txpool state is not good, aborting state publishing") - return - } -- err := l.publishTxToL1(l.killCtx, queue, receiptsCh) -+ err := l.publishTxToL1(l.killCtx, queue, receiptsCh, daGroup) -  - if err != nil { - if err != io.EOF { -@@ -487,7 +505,7 @@ } - } -  - // publishTxToL1 submits a single state tx to the L1 --func (l *BatchSubmitter) publishTxToL1(ctx context.Context, queue *txmgr.Queue[txRef], receiptsCh chan txmgr.TxReceipt[txRef]) error { -+func (l *BatchSubmitter) publishTxToL1(ctx context.Context, queue *txmgr.Queue[txRef], receiptsCh chan txmgr.TxReceipt[txRef], daGroup *errgroup.Group) error { - // send all available transactions - l1tip, err := l.l1Tip(ctx) - if err != nil { -@@ -496,7 +514,8 @@ return err - } - l.recordL1Tip(l1tip) -  -- // Collect next transaction data -+ // Collect next transaction data. This pulls data out of the channel, so we need to make sure -+ // to put it back if ever da or txmgr requests fail, by calling l.recordFailedDARequest/recordFailedTx. - txdata, err := l.state.TxData(l1tip.ID()) -  - if err == io.EOF { -@@ -507,7 +526,7 @@ l.Log.Error("Unable to get tx data", "err", err) - return err - } -  -- if err = l.sendTransaction(ctx, txdata, queue, receiptsCh); err != nil { -+ if err = l.sendTransaction(txdata, queue, receiptsCh, daGroup); err != nil { - return fmt.Errorf("BatchSubmitter.sendTransaction failed: %w", err) - } - return nil -@@ -552,12 +571,56 @@ l.Log.Warn("sending a cancellation transaction to unblock txpool", "blocked_blob", isBlockedBlob) - l.sendTx(txData{}, true, candidate, queue, receiptsCh) - } -  -+// publishToAltDAAndL1 posts the txdata to the DA Provider and then sends the commitment to L1. -+func (l *BatchSubmitter) publishToAltDAAndL1(txdata txData, queue *txmgr.Queue[txRef], receiptsCh chan txmgr.TxReceipt[txRef], daGroup *errgroup.Group) { -+ // sanity checks -+ if nf := len(txdata.frames); nf != 1 { -+ l.Log.Crit("Unexpected number of frames in calldata tx", "num_frames", nf) -+ } -+ if txdata.asBlob { -+ l.Log.Crit("Unexpected blob txdata with AltDA enabled") -+ } +
diff --git OP/packages/contracts-bedrock/src/celo/governance/interfaces/IGovernance.sol CELO/packages/contracts-bedrock/src/celo/governance/interfaces/IGovernance.sol +new file mode 100644 +index 0000000000000000000000000000000000000000..883844ea8f219feaaa747a6fd61f33424c6828a8 +--- /dev/null ++++ CELO/packages/contracts-bedrock/src/celo/governance/interfaces/IGovernance.sol +@@ -0,0 +1,24 @@ ++// SPDX-License-Identifier: LGPL-3.0-only ++pragma solidity ^0.8.15; + -+ // when posting txdata to an external DA Provider, we use a goroutine to avoid blocking the main loop -+ // since it may take a while for the request to return. -+ goroutineSpawned := daGroup.TryGo(func() error { -+ // TODO: probably shouldn't be using the global shutdownCtx here, see https://go.dev/blog/context-and-structs -+ // but sendTransaction receives l.killCtx as an argument, which currently is only canceled after waiting for the main loop -+ // to exit, which would wait on this DA call to finish, which would take a long time. -+ // So we prefer to mimic the behavior of txmgr and cancel all pending DA/txmgr requests when the batcher is stopped. -+ comm, err := l.AltDA.SetInput(l.shutdownCtx, txdata.CallData()) -+ if err != nil { -+ l.Log.Error("Failed to post input to Alt DA", "error", err) -+ // requeue frame if we fail to post to the DA Provider so it can be retried -+ // note: this assumes that the da server caches requests, otherwise it might lead to resubmissions of the blobs -+ l.recordFailedDARequest(txdata.ID(), err) -+ return nil -+ } -+ l.Log.Info("Set altda input", "commitment", comm, "tx", txdata.ID()) -+ candidate := l.calldataTxCandidate(comm.TxData()) -+ l.sendTx(txdata, false, candidate, queue, receiptsCh) -+ return nil -+ }) -+ if !goroutineSpawned { -+ // We couldn't start the goroutine because the errgroup.Group limit -+ // is already reached. Since we can't send the txdata, we have to -+ // return it for later processing. We use nil error to skip error logging. -+ l.recordFailedDARequest(txdata.ID(), nil) -+ } -+} ++interface IGovernance { ++ function votePartially( ++ uint256 proposalId, ++ uint256 index, ++ uint256 yesVotes, ++ uint256 noVotes, ++ uint256 abstainVotes ++ ) ++ external ++ returns (bool); + - // sendTransaction creates & queues for sending a transaction to the batch inbox address with the given `txData`. - // This call will block if the txmgr queue is at the max-pending limit. - // The method will block if the queue's MaxPendingTransactions is exceeded. --func (l *BatchSubmitter) sendTransaction(ctx context.Context, txdata txData, queue *txmgr.Queue[txRef], receiptsCh chan txmgr.TxReceipt[txRef]) error { -+func (l *BatchSubmitter) sendTransaction(txdata txData, queue *txmgr.Queue[txRef], receiptsCh chan txmgr.TxReceipt[txRef], daGroup *errgroup.Group) error { - var err error -- // Do the gas estimation offline. A value of 0 will cause the [txmgr] to estimate the gas limit. ++ function isVoting(address) external view returns (bool); ++ function getAmountOfGoldUsedForVoting(address account) external view returns (uint256); + -+ // if Alt DA is enabled we post the txdata to the DA Provider and replace it with the commitment. -+ if l.Config.UseAltDA { -+ l.publishToAltDAAndL1(txdata, queue, receiptsCh, daGroup) -+ // we return nil to allow publishStateToL1 to keep processing the next txdata -+ return nil -+ } -  - var candidate *txmgr.TxCandidate - if txdata.asBlob { -@@ -573,21 +636,7 @@ // sanity check - if nf := len(txdata.frames); nf != 1 { - l.Log.Crit("Unexpected number of frames in calldata tx", "num_frames", nf) - } -- data := txdata.CallData() -- // if AltDA is enabled we post the txdata to the DA Provider and replace it with the commitment. -- if l.Config.UseAltDA { -- comm, err := l.AltDA.SetInput(ctx, data) -- if err != nil { -- l.Log.Error("Failed to post input to Alt DA", "error", err) -- // requeue frame if we fail to post to the DA Provider so it can be retried -- l.recordFailedTx(txdata.ID(), err) -- return nil -- } -- l.Log.Info("Set AltDA input", "commitment", comm, "tx", txdata.ID()) -- // signal AltDA commitment tx with TxDataVersion1 -- data = comm.TxData() -- } -- candidate = l.calldataTxCandidate(data) -+ candidate = l.calldataTxCandidate(txdata.CallData()) - } -  - l.sendTx(txdata, false, candidate, queue, receiptsCh) -@@ -597,7 +646,7 @@ - // sendTx uses the txmgr queue to send the given transaction candidate after setting its - // gaslimit. It will block if the txmgr queue has reached its MaxPendingTransactions limit. - func (l *BatchSubmitter) sendTx(txdata txData, isCancel bool, candidate *txmgr.TxCandidate, queue *txmgr.Queue[txRef], receiptsCh chan txmgr.TxReceipt[txRef]) { -- intrinsicGas, err := core.IntrinsicGas(candidate.TxData, nil, false, true, true, false) -+ intrinsicGas, err := core.IntrinsicGas(candidate.TxData, nil, false, true, true, false, nil, nil) - if err != nil { - // we log instead of return an error here because txmgr can do its own gas estimation - l.Log.Error("Failed to calculate intrinsic gas", "err", err) -@@ -647,6 +696,13 @@ return - } - l.lastL1Tip = l1tip - l.Metr.RecordLatestL1Block(l1tip) -+} ++ function getProposal(uint256 proposalId) ++ external ++ view ++ returns (address, uint256, uint256, uint256, string memory, uint256, bool); + -+func (l *BatchSubmitter) recordFailedDARequest(id txID, err error) { -+ if err != nil { -+ l.Log.Warn("DA request failed", logFields(id, err)...) -+ } -+ l.state.TxFailed(id) - } -  - func (l *BatchSubmitter) recordFailedTx(id txID, err error) {
++ function getReferendumStageDuration() external view returns (uint256); ++}
@@ -28078,13 +130248,13 @@
- OP + (new)
@@ -28094,43 +130264,57 @@
-
+3
+
+29
-0
-
diff --git OP/op-batcher/batcher/service.go CELO/op-batcher/batcher/service.go -index 00d3d32071f7fb89a5ad1c3e75d1a06eb0f8fdec..667f75db1016f151c64d61be0bb24e22d25b1577 100644 ---- OP/op-batcher/batcher/service.go -+++ CELO/op-batcher/batcher/service.go -@@ -39,6 +39,8 @@ - // UseAltDA is true if the rollup config has a DA challenge address so the batcher - // will post inputs to the DA server and post commitments to blobs or calldata. - UseAltDA bool -+ // maximum number of concurrent blob put requests to the DA server -+ MaxConcurrentDARequests uint64 -  - WaitNodeSync bool - CheckRecentTxsDepth int -@@ -93,6 +95,7 @@ bs.initMetrics(cfg) -  - bs.PollInterval = cfg.PollInterval - bs.MaxPendingTransactions = cfg.MaxPendingTransactions -+ bs.MaxConcurrentDARequests = cfg.AltDA.MaxConcurrentRequests - bs.NetworkTimeout = cfg.TxMgrConfig.NetworkTimeout - bs.CheckRecentTxsDepth = cfg.CheckRecentTxsDepth - bs.WaitNodeSync = cfg.WaitNodeSync
+
diff --git OP/packages/contracts-bedrock/src/celo/governance/interfaces/ILockedGold.sol CELO/packages/contracts-bedrock/src/celo/governance/interfaces/ILockedGold.sol +new file mode 100644 +index 0000000000000000000000000000000000000000..38002d58914c70665df042ea9e3a3051d2c53091 +--- /dev/null ++++ CELO/packages/contracts-bedrock/src/celo/governance/interfaces/ILockedGold.sol +@@ -0,0 +1,29 @@ ++// SPDX-License-Identifier: LGPL-3.0-only ++pragma solidity ^0.8.15; ++ ++interface ILockedGold { ++ function lock() external payable; ++ function incrementNonvotingAccountBalance(address, uint256) external; ++ function decrementNonvotingAccountBalance(address, uint256) external; ++ function getAccountTotalLockedGold(address) external view returns (uint256); ++ function getTotalLockedGold() external view returns (uint256); ++ function getPendingWithdrawals(address) external view returns (uint256[] memory, uint256[] memory); ++ function getPendingWithdrawal(address account, uint256 index) external view returns (uint256, uint256); ++ function getTotalPendingWithdrawals(address) external view returns (uint256); ++ function unlock(uint256) external; ++ function relock(uint256, uint256) external; ++ function withdraw(uint256) external; ++ function slash( ++ address account, ++ uint256 penalty, ++ address reporter, ++ uint256 reward, ++ address[] calldata lessers, ++ address[] calldata greaters, ++ uint256[] calldata indices ++ ) ++ external; ++ function isSlasher(address) external view returns (bool); ++ function unlockingPeriod() external view returns (uint256); ++ function getAccountNonvotingLockedGold(address account) external view returns (uint256); ++}
@@ -28139,13 +130323,13 @@
- OP + (new)
@@ -28155,35 +130339,82 @@
-
+1
-
-1
+
+54
+
-0
-
diff --git OP/op-batcher/batcher/test_batch_submitter.go CELO/op-batcher/batcher/test_batch_submitter.go -index 8814400f06ca7b5082344f6630c475ac34fe7d37..542cbe5e3372ffbf40610bdd398fb5eeaae8c4b4 100644 ---- OP/op-batcher/batcher/test_batch_submitter.go -+++ CELO/op-batcher/batcher/test_batch_submitter.go -@@ -33,7 +33,7 @@ candidate = l.calldataTxCandidate([]byte{}) - } else if candidate, err = l.blobTxCandidate(emptyTxData); err != nil { - return err - } -- if candidate.GasLimit, err = core.IntrinsicGas(candidate.TxData, nil, false, true, true, false); err != nil { -+ if candidate.GasLimit, err = core.IntrinsicGas(candidate.TxData, nil, false, true, true, false, nil, nil); err != nil { - return err - } -
+
diff --git OP/packages/contracts-bedrock/src/celo/governance/interfaces/IReleaseGold.sol CELO/packages/contracts-bedrock/src/celo/governance/interfaces/IReleaseGold.sol +new file mode 100644 +index 0000000000000000000000000000000000000000..e211ce7399e37478a43b3b5e0335339e5c253265 +--- /dev/null ++++ CELO/packages/contracts-bedrock/src/celo/governance/interfaces/IReleaseGold.sol +@@ -0,0 +1,54 @@ ++// SPDX-License-Identifier: LGPL-3.0-only ++pragma solidity ^0.8.15; ++ ++interface IReleaseGold { ++ function transfer(address, uint256) external; ++ function unlockGold(uint256) external; ++ function withdrawLockedGold(uint256) external; ++ function authorizeVoteSigner(address payable, uint8, bytes32, bytes32) external; ++ function authorizeValidatorSigner(address payable, uint8, bytes32, bytes32) external; ++ function authorizeValidatorSignerWithPublicKey(address payable, uint8, bytes32, bytes32, bytes calldata) external; ++ function authorizeValidatorSignerWithKeys( ++ address payable, ++ uint8, ++ bytes32, ++ bytes32, ++ bytes calldata, ++ bytes calldata, ++ bytes calldata ++ ) ++ external; ++ function authorizeAttestationSigner(address payable, uint8, bytes32, bytes32) external; ++ function revokeActive(address, uint256, address, address, uint256) external; ++ function revokePending(address, uint256, address, address, uint256) external; ++ ++ // view functions ++ function getTotalBalance() external view returns (uint256); ++ function getRemainingTotalBalance() external view returns (uint256); ++ function getRemainingUnlockedBalance() external view returns (uint256); ++ function getRemainingLockedBalance() external view returns (uint256); ++ function getCurrentReleasedTotalAmount() external view returns (uint256); ++ function isRevoked() external view returns (bool); ++ ++ // only beneficiary ++ function setCanExpire(bool) external; ++ function withdraw(uint256) external; ++ function lockGold(uint256) external; ++ function relockGold(uint256, uint256) external; ++ function setAccount(string calldata, bytes calldata, address, uint8, bytes32, bytes32) external; ++ function createAccount() external; ++ function setAccountName(string calldata) external; ++ function setAccountWalletAddress(address, uint8, bytes32, bytes32) external; ++ function setAccountDataEncryptionKey(bytes calldata) external; ++ function setAccountMetadataURL(string calldata) external; ++ ++ // only owner ++ function setBeneficiary(address payable) external; ++ ++ // only release owner ++ function setLiquidityProvision() external; ++ function setMaxDistribution(uint256) external; ++ function refundAndFinalize() external; ++ function revoke() external; ++ function expire() external; ++}
@@ -28198,7 +130429,7 @@
@@ -28208,109 +130439,103 @@
-
+91
+
+85
-0
-
diff --git OP/op-chain-ops/cmd/celo-migrate/testdata/deploy-config-dango.json CELO/op-chain-ops/cmd/celo-migrate/testdata/deploy-config-dango.json +
diff --git OP/packages/contracts-bedrock/src/celo/governance/interfaces/IValidators.sol CELO/packages/contracts-bedrock/src/celo/governance/interfaces/IValidators.sol new file mode 100644 -index 0000000000000000000000000000000000000000..dd69e13ab4f941e212e767152fdb6e2cfb315cfc +index 0000000000000000000000000000000000000000..8a10e91fc8129cfb736057443bbec7c63170921e --- /dev/null -+++ CELO/op-chain-ops/cmd/celo-migrate/testdata/deploy-config-dango.json -@@ -0,0 +1,91 @@ -+ { -+ "l1StartingBlockTag": "0xe18e94c26beea64e318e25c32303c9a1ee2bfcee4492337bb5ac14181e99bd0c", -+ -+ "l1ChainID": 17000, -+ "l2ChainID": 44787, -+ "l2BlockTime": 2, -+ "l1BlockTime": 12, -+ -+ "maxSequencerDrift": 600, -+ "sequencerWindowSize": 3600, -+ "channelTimeout": 300, -+ -+ "p2pSequencerAddress": "0x644C82d76A43Fe9c76eda0EEd0f0DC17235c3005", -+ "batchInboxAddress": "0xff00000000000000000000000000000000044787", -+ "batchSenderAddress": "0x1660B1F70De0f32490b50f976e8983213dCF7FD5", -+ -+ "l2OutputOracleSubmissionInterval": 120, -+ "l2OutputOracleStartingBlockNumber": 26216760, -+ "l2OutputOracleStartingTimestamp": 1726651200, -+ -+ "l2OutputOracleProposer": "0x1BA11Ec6581FC8C3e35D6E345aEC977796Ffe89b", -+ "l2OutputOracleChallenger": "0xc07C5A1fBF6c7BC6b4f321E7dd031c0E1E98d32d", -+ -+ "finalizationPeriodSeconds": 12, -+ -+ "proxyAdminOwner": "0xc07C5A1fBF6c7BC6b4f321E7dd031c0E1E98d32d", -+ "baseFeeVaultRecipient": "0xc07C5A1fBF6c7BC6b4f321E7dd031c0E1E98d32d", -+ "l1FeeVaultRecipient": "0xc07C5A1fBF6c7BC6b4f321E7dd031c0E1E98d32d", -+ "sequencerFeeVaultRecipient": "0xc07C5A1fBF6c7BC6b4f321E7dd031c0E1E98d32d", -+ "finalSystemOwner": "0xc07C5A1fBF6c7BC6b4f321E7dd031c0E1E98d32d", -+ "superchainConfigGuardian": "0xc07C5A1fBF6c7BC6b4f321E7dd031c0E1E98d32d", -+ -+ "baseFeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000", -+ "l1FeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000", -+ "sequencerFeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000", -+ "baseFeeVaultWithdrawalNetwork": 0, -+ "l1FeeVaultWithdrawalNetwork": 0, -+ "sequencerFeeVaultWithdrawalNetwork": 0, -+ -+ "gasPriceOracleOverhead": 0, -+ "gasPriceOracleScalar": 1000000, -+ -+ "deployCeloContracts": false, -+ -+ "enableGovernance": false, -+ "governanceTokenSymbol": "OP", -+ "governanceTokenName": "Optimism", -+ "governanceTokenOwner": "0xc07C5A1fBF6c7BC6b4f321E7dd031c0E1E98d32d", -+ -+ "l2GenesisBlockGasLimit": "0x1c9c380", -+ "l2GenesisBlockBaseFeePerGas": "0x3b9aca00", -+ -+ "eip1559Denominator": 50, -+ "eip1559DenominatorCanyon": 250, -+ "eip1559Elasticity": 6, -+ "l2GenesisFjordTimeOffset": "0x0", -+ "l2GenesisRegolithTimeOffset": "0x0", -+ "l2GenesisEcotoneTimeOffset": "0x0", -+ "l2GenesisDeltaTimeOffset": "0x0", -+ "l2GenesisCanyonTimeOffset": "0x0", -+ "systemConfigStartBlock": 0, ++++ CELO/packages/contracts-bedrock/src/celo/governance/interfaces/IValidators.sol +@@ -0,0 +1,85 @@ ++// SPDX-License-Identifier: LGPL-3.0-only ++pragma solidity ^0.8.15; + -+ "requiredProtocolVersion": "0x0000000000000000000000000000000000000000000000000000000000000000", -+ "recommendedProtocolVersion": "0x0000000000000000000000000000000000000000000000000000000000000000", ++interface IValidators { ++ function registerValidator(bytes calldata, bytes calldata, bytes calldata) external returns (bool); ++ function deregisterValidator(uint256) external returns (bool); ++ function affiliate(address) external returns (bool); ++ function deaffiliate() external returns (bool); ++ function updateBlsPublicKey(bytes calldata, bytes calldata) external returns (bool); ++ function registerValidatorGroup(uint256) external returns (bool); ++ function deregisterValidatorGroup(uint256) external returns (bool); ++ function addMember(address) external returns (bool); ++ function addFirstMember(address, address, address) external returns (bool); ++ function removeMember(address) external returns (bool); ++ function reorderMember(address, address, address) external returns (bool); ++ function updateCommission() external; ++ function setNextCommissionUpdate(uint256) external; ++ function resetSlashingMultiplier() external; + -+ "faultGameAbsolutePrestate": "0x03c7ae758795765c6664a5d39bf63841c71ff191e9189522bad8ebff5d4eca98", -+ "faultGameMaxDepth": 44, -+ "faultGameClockExtension": 0, -+ "faultGameMaxClockDuration": 1200, -+ "faultGameGenesisBlock": 0, -+ "faultGameGenesisOutputRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", -+ "faultGameSplitDepth": 14, -+ "faultGameWithdrawalDelay": 600, ++ // only owner ++ function setCommissionUpdateDelay(uint256) external; ++ function setMaxGroupSize(uint256) external returns (bool); ++ function setMembershipHistoryLength(uint256) external returns (bool); ++ function setValidatorScoreParameters(uint256, uint256) external returns (bool); ++ function setGroupLockedGoldRequirements(uint256, uint256) external returns (bool); ++ function setValidatorLockedGoldRequirements(uint256, uint256) external returns (bool); ++ function setSlashingMultiplierResetPeriod(uint256) external; + -+ "preimageOracleMinProposalSize": 1800000, -+ "preimageOracleChallengePeriod": 300, ++ // view functions ++ function getMaxGroupSize() external view returns (uint256); ++ function getCommissionUpdateDelay() external view returns (uint256); ++ function getValidatorScoreParameters() external view returns (uint256, uint256); ++ function getMembershipHistory(address) ++ external ++ view ++ returns (uint256[] memory, address[] memory, uint256, uint256); ++ function calculateEpochScore(uint256) external view returns (uint256); ++ function calculateGroupEpochScore(uint256[] calldata) external view returns (uint256); ++ function getAccountLockedGoldRequirement(address) external view returns (uint256); ++ function meetsAccountLockedGoldRequirements(address) external view returns (bool); ++ function getValidatorBlsPublicKeyFromSigner(address) external view returns (bytes memory); ++ function getValidator(address account) ++ external ++ view ++ returns (bytes memory, bytes memory, address, uint256, address); ++ function getValidatorGroup(address) ++ external ++ view ++ returns (address[] memory, uint256, uint256, uint256, uint256[] memory, uint256, uint256); ++ function getGroupNumMembers(address) external view returns (uint256); ++ function getTopGroupValidators(address, uint256) external view returns (address[] memory); ++ function getGroupsNumMembers(address[] calldata accounts) external view returns (uint256[] memory); ++ function getNumRegisteredValidators() external view returns (uint256); ++ function groupMembershipInEpoch(address, uint256, uint256) external view returns (address); + -+ "fundDevAccounts": false, -+ "useFaultProofs": false, -+ "proofMaturityDelaySeconds": 604800, -+ "disputeGameFinalityDelaySeconds": 302400, -+ "respectedGameType": 0, ++ // only registered contract ++ function updateEcdsaPublicKey(address, address, bytes calldata) external returns (bool); ++ function updatePublicKeys( ++ address, ++ address, ++ bytes calldata, ++ bytes calldata, ++ bytes calldata ++ ) ++ external ++ returns (bool); ++ function getValidatorLockedGoldRequirements() external view returns (uint256, uint256); ++ function getGroupLockedGoldRequirements() external view returns (uint256, uint256); ++ function getRegisteredValidators() external view returns (address[] memory); ++ function getRegisteredValidatorSigners() external view returns (address[] memory); ++ function getRegisteredValidatorGroups() external view returns (address[] memory); ++ function isValidatorGroup(address) external view returns (bool); ++ function isValidator(address) external view returns (bool); ++ function getValidatorGroupSlashingMultiplier(address) external view returns (uint256); ++ function getMembershipInLastEpoch(address) external view returns (address); ++ function getMembershipInLastEpochFromSigner(address) external view returns (address); + -+ "useAltDA": true, -+ "daCommitmentType": "GenericCommitment", -+ "daChallengeWindow": 1, -+ "daResolveWindow": 1, ++ // only VM ++ function updateValidatorScoreFromSigner(address, uint256) external; ++ function distributeEpochPaymentsFromSigner(address, uint256) external returns (uint256); + -+ "useCustomGasToken": true, -+ "customGasTokenAddress": "0x0000000000000000000000000000000000000000" ++ // only slasher ++ function forceDeaffiliateIfValidator(address) external; ++ function halveSlashingMultiplier(address) external; +}
@@ -28318,9 +130543,9 @@
@@ -28335,7 +130560,7 @@
@@ -28345,108 +130570,138 @@
-
+90
+
+35
-0
-
diff --git OP/op-chain-ops/cmd/celo-migrate/testdata/deploy-config-holesky-alfajores.json CELO/op-chain-ops/cmd/celo-migrate/testdata/deploy-config-holesky-alfajores.json +
diff --git OP/packages/contracts-bedrock/src/celo/identity/interfaces/IAttestations.sol CELO/packages/contracts-bedrock/src/celo/identity/interfaces/IAttestations.sol new file mode 100644 -index 0000000000000000000000000000000000000000..0c8dee05d9c5b94f42bc97845fdf66da9b255a4c +index 0000000000000000000000000000000000000000..5c1a1d7a8f484e1cedc6336b39144ceea0941c97 --- /dev/null -+++ CELO/op-chain-ops/cmd/celo-migrate/testdata/deploy-config-holesky-alfajores.json -@@ -0,0 +1,90 @@ -+{ -+ "l1StartingBlockTag": "0xbbed3612407993e67f8ca7a423b181837ae164a531941e78f5ee48e766d39cad", -+ -+ "l1ChainID": 17000, -+ "l2ChainID": 44787, -+ "l2BlockTime": 2, -+ "l1BlockTime": 12, -+ -+ "maxSequencerDrift": 600, -+ "sequencerWindowSize": 3600, -+ "channelTimeout": 300, -+ -+ "p2pSequencerAddress": "0x644C82d76A43Fe9c76eda0EEd0f0DC17235c3005", -+ "batchInboxAddress": "0xff00000000000000000000000000000000044787", -+ "batchSenderAddress": "0x1660B1F70De0f32490b50f976e8983213dCF7FD5", -+ -+ "l2OutputOracleSubmissionInterval": 120, -+ "l2OutputOracleStartingBlockNumber": 0, -+ "l2OutputOracleStartingTimestamp": 1718312256, -+ -+ "l2OutputOracleProposer": "0x1BA11Ec6581FC8C3e35D6E345aEC977796Ffe89b", -+ "l2OutputOracleChallenger": "0xc07C5A1fBF6c7BC6b4f321E7dd031c0E1E98d32d", -+ -+ "finalizationPeriodSeconds": 12, -+ -+ "proxyAdminOwner": "0xc07C5A1fBF6c7BC6b4f321E7dd031c0E1E98d32d", -+ "baseFeeVaultRecipient": "0xc07C5A1fBF6c7BC6b4f321E7dd031c0E1E98d32d", -+ "l1FeeVaultRecipient": "0xc07C5A1fBF6c7BC6b4f321E7dd031c0E1E98d32d", -+ "sequencerFeeVaultRecipient": "0xc07C5A1fBF6c7BC6b4f321E7dd031c0E1E98d32d", -+ "finalSystemOwner": "0xc07C5A1fBF6c7BC6b4f321E7dd031c0E1E98d32d", -+ "superchainConfigGuardian": "0xc07C5A1fBF6c7BC6b4f321E7dd031c0E1E98d32d", -+ -+ "baseFeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000", -+ "l1FeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000", -+ "sequencerFeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000", -+ "baseFeeVaultWithdrawalNetwork": 0, -+ "l1FeeVaultWithdrawalNetwork": 0, -+ "sequencerFeeVaultWithdrawalNetwork": 0, -+ -+ "gasPriceOracleOverhead": 0, -+ "gasPriceOracleScalar": 1000000, -+ -+ "enableGovernance": false, -+ "governanceTokenSymbol": "OP", -+ "governanceTokenName": "Optimism", -+ "governanceTokenOwner": "0xc07C5A1fBF6c7BC6b4f321E7dd031c0E1E98d32d", -+ -+ "l2GenesisBlockGasLimit": "0x1c9c380", -+ "l2GenesisBlockBaseFeePerGas": "0x3b9aca00", -+ "l2GenesisRegolithTimeOffset": "0x0", -+ -+ "eip1559Denominator": 50, -+ "eip1559DenominatorCanyon": 250, -+ "eip1559Elasticity": 6, -+ -+ "l2GenesisGraniteTimeOffset": "0x0", -+ "l2GenesisEcotoneTimeOffset": "0x0", -+ "l2GenesisDeltaTimeOffset": "0x0", -+ "l2GenesisCanyonTimeOffset": "0x0", ++++ CELO/packages/contracts-bedrock/src/celo/identity/interfaces/IAttestations.sol +@@ -0,0 +1,35 @@ ++// SPDX-License-Identifier: LGPL-3.0-only ++pragma solidity ^0.8.15; + -+ "systemConfigStartBlock": 0, ++interface IAttestations { ++ function revoke(bytes32, uint256) external; ++ function withdraw(address) external; + -+ "requiredProtocolVersion": "0x0000000000000000000000000000000000000000000000000000000000000000", -+ "recommendedProtocolVersion": "0x0000000000000000000000000000000000000000000000000000000000000000", ++ // view functions ++ function getUnselectedRequest(bytes32, address) external view returns (uint32, uint32, address); ++ function getAttestationIssuers(bytes32, address) external view returns (address[] memory); ++ function getAttestationStats(bytes32, address) external view returns (uint32, uint32); ++ function batchGetAttestationStats(bytes32[] calldata) ++ external ++ view ++ returns (uint256[] memory, address[] memory, uint64[] memory, uint64[] memory); ++ function getAttestationState(bytes32, address, address) external view returns (uint8, uint32, address); ++ function getCompletableAttestations( ++ bytes32, ++ address ++ ) ++ external ++ view ++ returns (uint32[] memory, address[] memory, uint256[] memory, bytes memory); ++ function getAttestationRequestFee(address) external view returns (uint256); ++ function getMaxAttestations() external view returns (uint256); ++ function validateAttestationCode(bytes32, address, uint8, bytes32, bytes32) external view returns (address); ++ function lookupAccountsForIdentifier(bytes32) external view returns (address[] memory); ++ function requireNAttestationsRequested(bytes32, address, uint32) external view; + -+ "faultGameAbsolutePrestate": "0x03c7ae758795765c6664a5d39bf63841c71ff191e9189522bad8ebff5d4eca98", -+ "faultGameMaxDepth": 44, -+ "faultGameClockExtension": 0, -+ "faultGameMaxClockDuration": 600, -+ "faultGameGenesisBlock": 0, -+ "faultGameGenesisOutputRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", -+ "faultGameSplitDepth": 14, -+ "faultGameWithdrawalDelay": 604800, ++ // only owner ++ function setAttestationRequestFee(address, uint256) external; ++ function setAttestationExpiryBlocks(uint256) external; ++ function setSelectIssuersWaitBlocks(uint256) external; ++ function setMaxAttestations(uint256) external; ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+39
+
-0
+ +
+ +
+
+
diff --git OP/packages/contracts-bedrock/src/celo/identity/interfaces/IEscrow.sol CELO/packages/contracts-bedrock/src/celo/identity/interfaces/IEscrow.sol +new file mode 100644 +index 0000000000000000000000000000000000000000..87c145a4a1bb9bf3aa469bb8ec5ca6e92073525f +--- /dev/null ++++ CELO/packages/contracts-bedrock/src/celo/identity/interfaces/IEscrow.sol +@@ -0,0 +1,39 @@ ++// SPDX-License-Identifier: MIT ++pragma solidity ^0.8.15; + -+ "preimageOracleMinProposalSize": 1800000, -+ "preimageOracleChallengePeriod": 86400, ++interface IEscrow { ++ function transfer( ++ bytes32 identifier, ++ address token, ++ uint256 value, ++ uint256 expirySeconds, ++ address paymentId, ++ uint256 minAttestations ++ ) ++ external ++ returns (bool); ++ function transferWithTrustedIssuers( ++ bytes32 identifier, ++ address token, ++ uint256 value, ++ uint256 expirySeconds, ++ address paymentId, ++ uint256 minAttestations, ++ address[] calldata trustedIssuers ++ ) ++ external ++ returns (bool); ++ function withdraw(address paymentID, uint8 v, bytes32 r, bytes32 s) external returns (bool); ++ function revoke(address paymentID) external returns (bool); + -+ "fundDevAccounts": false, -+ "useFaultProofs": false, -+ "proofMaturityDelaySeconds": 604800, -+ "disputeGameFinalityDelaySeconds": 302400, -+ "respectedGameType": 0, ++ // view functions ++ function getReceivedPaymentIds(bytes32 identifier) external view returns (address[] memory); ++ function getSentPaymentIds(address sender) external view returns (address[] memory); ++ function getTrustedIssuersPerPayment(address paymentId) external view returns (address[] memory); ++ function getDefaultTrustedIssuers() external view returns (address[] memory); ++ function MAX_TRUSTED_ISSUERS_PER_PAYMENT() external view returns (uint256); + -+ "usePlasma": false, -+ "daCommitmentType": "KeccakCommitment", -+ "daChallengeWindow": 160, -+ "daResolveWindow": 160, -+ "daBondSize": 1000000, -+ "daResolverRefundPercentage": 0 ++ // onlyOwner functions ++ function addDefaultTrustedIssuer(address trustedIssuer) external; ++ function removeDefaultTrustedIssuer(address trustedIssuer, uint256 index) external; +}
@@ -28454,9 +130709,9 @@
@@ -28471,7 +130726,7 @@
@@ -28481,66 +130736,90 @@
-
+36
+
+62
-0
-
diff --git OP/op-chain-ops/cmd/celo-migrate/testdata/deployment-l1-dango.json CELO/op-chain-ops/cmd/celo-migrate/testdata/deployment-l1-dango.json +
diff --git OP/packages/contracts-bedrock/src/celo/identity/interfaces/IFederatedAttestations.sol CELO/packages/contracts-bedrock/src/celo/identity/interfaces/IFederatedAttestations.sol new file mode 100644 -index 0000000000000000000000000000000000000000..58c1f74772ed173da257ce7ab3fb5a03bad32d9a +index 0000000000000000000000000000000000000000..c0586eb9e44dc7a10fdd0e86de09a7753c6e4974 --- /dev/null -+++ CELO/op-chain-ops/cmd/celo-migrate/testdata/deployment-l1-dango.json -@@ -0,0 +1,37 @@ -+{ -+ "AddressManager": "0x5Ab3E4093B06a69954885caDAF29b280613c674f", -+ "AnchorStateRegistry": "0x5b530E1DD25513F0Da1CC39333f6fa91143884aB", -+ "AnchorStateRegistryProxy": "0xCCb982Cc00F9Cc970f71AF753Ff834e9AadADad6", -+ "CustomGasToken": "0xf7a83872810aBea270FAFF54206A522AB53f3df1", -+ "CustomGasTokenProxy": "0x3c300204B89F8A333350d9FfE72352D990DDA36f", -+ "DelayedWETH": "0x9eC20144141099E0c0581ABe0C507aCd2B07Da68", -+ "DelayedWETHProxy": "0xb0b158f73CF23c2edc220E586Bd043CB1b69c5Ad", -+ "DisputeGameFactory": "0x88ca8D6b24b691F617C9A02Ce8179F23C13e13Ae", -+ "DisputeGameFactoryProxy": "0x3889C8BA734148dec7A31472B4A370BC7fc3E50c", -+ "L1CrossDomainMessenger": "0xDb787d88Fa092d7144053138023137b01b2FB1af", -+ "L1CrossDomainMessengerProxy": "0x4401780183661b211a9ED386D56b400E430b0995", -+ "L1ERC721Bridge": "0x442Cc0A770Cd776930a14C0d3363a2931aBE273b", -+ "L1ERC721BridgeProxy": "0xC262D512A52D4F90D7Bc221979A584857Ab90dd9", -+ "L1StandardBridge": "0x3D4712d8cA71b8f5ae918213421e098761415898", -+ "L1StandardBridgeProxy": "0x59f2BDd9674c8C7c5750b12a004783da9a992e5A", -+ "L2OutputOracle": "0x1dd308d7e3aC77ea70f3c7069b29350665ab57F4", -+ "L2OutputOracleProxy": "0xD31bf46c090Ea08191fd11BFbf0758fAbeE468cC", -+ "Mips": "0x30f82aD995f412FBC3386022270AB071e616CaEA", -+ "OptimismMintableERC20Factory": "0x4626Da66AEE29bC145c7B04614437Aa6540D82F2", -+ "OptimismMintableERC20FactoryProxy": "0xabcd2bd6a5bc474287Fc460aD99F70d42711AA33", -+ "OptimismPortal": "0xD10c0833b38b47662200A026d60f0c891ea6C960", -+ "OptimismPortal2": "0xAAcC881F37e45CAb4C57A6757DE0334FC5b4DE7F", -+ "OptimismPortalProxy": "0xf550A0aEc6cD8fDFA904242d6e07F71E38BE5240", -+ "PermissionedDelayedWETHProxy": "0x85E318CE71dE55c19290Fa22149cC773526C8987", -+ "PreimageOracle": "0x2c010f9f6A63234d03baB647788633Fd5000410A", -+ "ProtocolVersions": "0x9233fCE30bfb57de432B1a8cf0Cad87A12011eFC", -+ "ProtocolVersionsProxy": "0x4CE6aDa5fef5BffD2f13257aAF5a40efd412C8E7", -+ "ProxyAdmin": "0x9f03734bE814De3652C757B3a5702BfE99BA0098", -+ "SafeProxyFactory": "0xa6B71E26C5e0845f74c812102Ca7114b6a896AB2", -+ "SafeSingleton": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", -+ "SuperchainConfig": "0x05B71600Fe59197339837509F702da31F9fa5cf3", -+ "SuperchainConfigProxy": "0xDDfcA11fD8553C6Fc1185aD5f492230c3A0091E3", -+ "SystemConfig": "0x5b10806e8068B517eaBd8DeD5B872034f31878F9", -+ "SystemConfigProxy": "0xFbe6510A1E209d9E2148d54F134f4E5634bE7241", -+ "SystemOwnerSafe": "0xD751beb42dBcde9BDe9E2866c0490DccA6A11Ba9" -+} -\ No newline at end of file
++++ CELO/packages/contracts-bedrock/src/celo/identity/interfaces/IFederatedAttestations.sol +@@ -0,0 +1,62 @@ ++// SPDX-License-Identifier: MIT ++pragma solidity ^0.8.15; ++ ++interface IFederatedAttestations { ++ function registerAttestationAsIssuer(bytes32 identifier, address account, uint64 issuedOn) external; ++ function registerAttestation( ++ bytes32 identifier, ++ address issuer, ++ address account, ++ address signer, ++ uint64 issuedOn, ++ uint8 v, ++ bytes32 r, ++ bytes32 s ++ ) ++ external; ++ function revokeAttestation(bytes32 identifier, address issuer, address account) external; ++ function batchRevokeAttestations( ++ address issuer, ++ bytes32[] calldata identifiers, ++ address[] calldata accounts ++ ) ++ external; ++ ++ // view functions ++ function lookupAttestations( ++ bytes32 identifier, ++ address[] calldata trustedIssuers ++ ) ++ external ++ view ++ returns (uint256[] memory, address[] memory, address[] memory, uint64[] memory, uint64[] memory); ++ function lookupIdentifiers( ++ address account, ++ address[] calldata trustedIssuers ++ ) ++ external ++ view ++ returns (uint256[] memory, bytes32[] memory); ++ function validateAttestationSig( ++ bytes32 identifier, ++ address issuer, ++ address account, ++ address signer, ++ uint64 issuedOn, ++ uint8 v, ++ bytes32 r, ++ bytes32 s ++ ) ++ external ++ view; ++ function getUniqueAttestationHash( ++ bytes32 identifier, ++ address issuer, ++ address account, ++ address signer, ++ uint64 issuedOn ++ ) ++ external ++ pure ++ returns (bytes32); ++}
@@ -28555,7 +130834,7 @@
@@ -28565,52 +130844,25 @@
-
+34
+
+7
-0
-
diff --git OP/op-chain-ops/cmd/celo-migrate/testdata/deployment-l1-holesky.json CELO/op-chain-ops/cmd/celo-migrate/testdata/deployment-l1-holesky.json +
diff --git OP/packages/contracts-bedrock/src/celo/identity/interfaces/IOdisPayments.sol CELO/packages/contracts-bedrock/src/celo/identity/interfaces/IOdisPayments.sol new file mode 100644 -index 0000000000000000000000000000000000000000..b37b79f4d4c8f1ee70c7aae7e7f351713226b8a3 +index 0000000000000000000000000000000000000000..ca188432c0dda414dfa563d857cccc600947de9e --- /dev/null -+++ CELO/op-chain-ops/cmd/celo-migrate/testdata/deployment-l1-holesky.json -@@ -0,0 +1,34 @@ -+{ -+ "AddressManager": "0x2d256f3b82f673Ee377C393fBF2Cf3DcA5D1D901", -+ "AnchorStateRegistry": "0x036fDE501893043825356Ce49dfd554809F07597", -+ "AnchorStateRegistryProxy": "0xe5077701c64782954d27384da76D95ABf320460f", -+ "DelayedWETH": "0x408Ad04Dd953958B080226025E17d6Ba12987EB7", -+ "DelayedWETHProxy": "0x27f7Ade64F031A39553Be8104bF8B0b410735845", -+ "DisputeGameFactory": "0xd7771F9687804Bba1D360B08AD9e4d8CB4523738", -+ "DisputeGameFactoryProxy": "0x193FdDF22D31c227f1Af1286cf2B051d701FF86E", -+ "L1CrossDomainMessenger": "0x1e3513a619AA4f2550CDD95709B92C1FE0397184", -+ "L1CrossDomainMessengerProxy": "0x35841aC1f5FdC5b812562adB17F6A0B9A178F643", -+ "L1ERC721Bridge": "0x695b01393f0539ec64AC316d4998E4130309efB0", -+ "L1ERC721BridgeProxy": "0x2b9C1e5b9a0D01256388cc4A0F8F290E839F2d82", -+ "L1StandardBridge": "0x2d1A818544b657Bc5d1E8c8B80F953bd0CA1C9B2", -+ "L1StandardBridgeProxy": "0xD10A531CB9b80BD507501F34D87Ad4083E9b7F98", -+ "L2OutputOracle": "0x04CD14625ff0Da62d6E0820a816b4dD3eCd0FF27", -+ "L2OutputOracleProxy": "0x5636f9D582DB69EAf1Eb9f05B0738225C91fBC1E", -+ "Mips": "0x60E1b8b535626Fc9fFCdf6147B45879634645771", -+ "OptimismMintableERC20Factory": "0x3fcd69a03857aA6e79AE9408fc7c887EE70FC145", -+ "OptimismMintableERC20FactoryProxy": "0x23c80F2503b93a58EC620D20b6b9B6AB8cCa2a12", -+ "OptimismPortal": "0xdF803FAC1d84a31Ff5aee841f11659f9a3787CE5", -+ "OptimismPortal2": "0x60bc423dDf0B24fa5104EcacAC5000674Ac3EBfB", -+ "OptimismPortalProxy": "0xa292B051eA58e2558243f4A9f74262B1796c9648", -+ "PreimageOracle": "0xEC19353B7364Fb85b9b0A57EaEEC6aCeBbFb6a53", -+ "ProtocolVersions": "0x077d61D4fb3378025950Bb60AD69179B38921107", -+ "ProtocolVersionsProxy": "0x791D5101840A547F1EE91148d34E061412A57ECD", -+ "ProxyAdmin": "0x4ddC758DA1697Ad58D86D03150872c042390dCa2", -+ "SafeProxyFactory": "0xa6B71E26C5e0845f74c812102Ca7114b6a896AB2", -+ "SafeSingleton": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552", -+ "SuperchainConfig": "0xA4f7dB67A6e098613B107be3F8441475Ec30FCC2", -+ "SuperchainConfigProxy": "0xB21214DA32a85A0d43372310D62095cf91d67765", -+ "SystemConfig": "0xeFA98Ba3ada6c6AC4bB84074820685E1F01C835d", -+ "SystemConfigProxy": "0x733043Aa78d25F6759d9e6Ce2B2897bE6d630E08", -+ "SystemOwnerSafe": "0xD2a6B91aB77691D6F8688eAFA7a5f188bc5baA3a" ++++ CELO/packages/contracts-bedrock/src/celo/identity/interfaces/IOdisPayments.sol +@@ -0,0 +1,7 @@ ++// SPDX-License-Identifier: MIT ++pragma solidity ^0.8.15; ++ ++interface IOdisPayments { ++ function payInCUSD(address account, uint256 value) external; ++ function totalPaidCUSD(address) external view returns (uint256); +}
@@ -28618,9 +130870,9 @@
@@ -28635,7 +130887,7 @@
@@ -28645,70 +130897,37 @@
-
+42
+
+9
-0
-
diff --git OP/op-chain-ops/cmd/celo-migrate/testdata/rollup-config-dango.json CELO/op-chain-ops/cmd/celo-migrate/testdata/rollup-config-dango.json +
diff --git OP/packages/contracts-bedrock/src/celo/identity/interfaces/IRandom.sol CELO/packages/contracts-bedrock/src/celo/identity/interfaces/IRandom.sol new file mode 100644 -index 0000000000000000000000000000000000000000..83de52fa1acebe25c1489c6465bbe6a8a84155b8 +index 0000000000000000000000000000000000000000..65cf3082d685cd4a5a9a2e38d8254e85de1bb2e5 --- /dev/null -+++ CELO/op-chain-ops/cmd/celo-migrate/testdata/rollup-config-dango.json -@@ -0,0 +1,42 @@ -+{ -+ "genesis": { -+ "l1": { -+ "hash": "0xe18e94c26beea64e318e25c32303c9a1ee2bfcee4492337bb5ac14181e99bd0c", -+ "number": 2358856 -+ }, -+ "l2": { -+ "hash": "0x0e1287f3eba321cb620a032d4d26978424e15b0533e1d19e870baeb1f0078e10", -+ "number": 25275061 -+ }, -+ "l2_time": 1726651200, -+ "system_config": { -+ "batcherAddr": "0x1660b1f70de0f32490b50f976e8983213dcf7fd5", -+ "overhead": "0x0000000000000000000000000000000000000000000000000000000000000000", -+ "scalar": "0x00000000000000000000000000000000000000000000000000000000000f4240", -+ "gasLimit": 30000000 -+ } -+ }, -+ "block_time": 2, -+ "max_sequencer_drift": 600, -+ "seq_window_size": 3600, -+ "channel_timeout": 300, -+ "l1_chain_id": 17000, -+ "l2_chain_id": 44787, -+ "regolith_time": 0, -+ "cel2_time": 0, -+ "canyon_time": 0, -+ "delta_time": 0, -+ "ecotone_time": 0, -+ "fjord_time": 0, -+ "batch_inbox_address": "0xff00000000000000000000000000000000044787", -+ "deposit_contract_address": "0xf550a0aec6cd8fdfa904242d6e07f71e38be5240", -+ "l1_system_config_address": "0xfbe6510a1e209d9e2148d54f134f4e5634be7241", -+ "protocol_versions_address": "0x0000000000000000000000000000000000000000", -+ "alt_da": { -+ "da_challenge_contract_address": "0x0000000000000000000000000000000000000000", -+ "da_commitment_type": "GenericCommitment", -+ "da_challenge_window": 1, -+ "da_resolve_window": 1 -+ } -+} -+
++++ CELO/packages/contracts-bedrock/src/celo/identity/interfaces/IRandom.sol +@@ -0,0 +1,9 @@ ++// SPDX-License-Identifier: LGPL-3.0-only ++pragma solidity ^0.8.15; ++ ++interface IRandom { ++ function revealAndCommit(bytes32, bytes32, address) external; ++ function randomnessBlockRetentionWindow() external view returns (uint256); ++ function random() external view returns (bytes32); ++ function getBlockRandomness(uint256) external view returns (bytes32); ++}
@@ -28723,7 +130942,7 @@
@@ -28733,64 +130952,76 @@
-
+36
+
+48
-0
-
diff --git OP/op-chain-ops/cmd/celo-migrate/testdata/rollup-config.json CELO/op-chain-ops/cmd/celo-migrate/testdata/rollup-config.json -new file mode 100644 -index 0000000000000000000000000000000000000000..8dfd1f25e28d86be0d6188ab982c2439b077a2f0 ---- /dev/null -+++ CELO/op-chain-ops/cmd/celo-migrate/testdata/rollup-config.json -@@ -0,0 +1,36 @@ -+{ -+ "genesis": { -+ "l1": { -+ "hash": "0xbbed3612407993e67f8ca7a423b181837ae164a531941e78f5ee48e766d39cad", -+ "number": 1729797 -+ }, -+ "l2": { -+ "hash": "0x2664d0a1f45dc9a010e553e815a25f33c6d949cbb0d38e179c6209fc0486aa41", -+ "number": 23912613 -+ }, -+ "l2_time": 1718312256, -+ "system_config": { -+ "batcherAddr": "0x1660b1f70de0f32490b50f976e8983213dcf7fd5", -+ "overhead": "0x0000000000000000000000000000000000000000000000000000000000000000", -+ "scalar": "0x00000000000000000000000000000000000000000000000000000000000f4240", -+ "gasLimit": 30000000 -+ } -+ }, -+ "block_time": 2, -+ "max_sequencer_drift": 600, -+ "seq_window_size": 3600, -+ "channel_timeout": 300, -+ "l1_chain_id": 17000, -+ "l2_chain_id": 44787, -+ "regolith_time": 0, -+ "cel2_time": 0, -+ "canyon_time": 0, -+ "delta_time": 0, -+ "ecotone_time": 0, -+ "batch_inbox_address": "0xff00000000000000000000000000000000044787", -+ "deposit_contract_address": "0xa292b051ea58e2558243f4a9f74262b1796c9648", -+ "l1_system_config_address": "0x733043aa78d25f6759d9e6ce2b2897be6d630e08", -+ "protocol_versions_address": "0x0000000000000000000000000000000000000000", -+ "da_challenge_contract_address": "0x0000000000000000000000000000000000000000" -+} -+
+
diff --git OP/packages/contracts-bedrock/src/celo/interfaces/IAccounts.sol CELO/packages/contracts-bedrock/src/celo/interfaces/IAccounts.sol +new file mode 100644 +index 0000000000000000000000000000000000000000..734dcddeb941d89c467af92a24ba0a488df4ab57 +--- /dev/null ++++ CELO/packages/contracts-bedrock/src/celo/interfaces/IAccounts.sol +@@ -0,0 +1,48 @@ ++// SPDX-License-Identifier: LGPL-3.0-only ++pragma solidity ^0.8.15; ++ ++interface IAccounts { ++ function isAccount(address) external view returns (bool); ++ function voteSignerToAccount(address) external view returns (address); ++ function validatorSignerToAccount(address) external view returns (address); ++ function attestationSignerToAccount(address) external view returns (address); ++ function signerToAccount(address) external view returns (address); ++ function getAttestationSigner(address) external view returns (address); ++ function getValidatorSigner(address) external view returns (address); ++ function getVoteSigner(address) external view returns (address); ++ function hasAuthorizedVoteSigner(address) external view returns (bool); ++ function hasAuthorizedValidatorSigner(address) external view returns (bool); ++ function hasAuthorizedAttestationSigner(address) external view returns (bool); ++ ++ function setAccountDataEncryptionKey(bytes calldata) external; ++ function setMetadataURL(string calldata) external; ++ function setName(string calldata) external; ++ function setWalletAddress(address, uint8, bytes32, bytes32) external; ++ function setAccount(string calldata, bytes calldata, address, uint8, bytes32, bytes32) external; ++ ++ function getDataEncryptionKey(address) external view returns (bytes memory); ++ function getWalletAddress(address) external view returns (address); ++ function getMetadataURL(address) external view returns (string memory); ++ function batchGetMetadataURL(address[] calldata) external view returns (uint256[] memory, bytes memory); ++ function getName(address) external view returns (string memory); ++ ++ function authorizeVoteSigner(address, uint8, bytes32, bytes32) external; ++ function authorizeValidatorSigner(address, uint8, bytes32, bytes32) external; ++ function authorizeValidatorSignerWithPublicKey(address, uint8, bytes32, bytes32, bytes calldata) external; ++ function authorizeValidatorSignerWithKeys( ++ address, ++ uint8, ++ bytes32, ++ bytes32, ++ bytes calldata, ++ bytes calldata, ++ bytes calldata ++ ) ++ external; ++ function authorizeAttestationSigner(address, uint8, bytes32, bytes32) external; ++ function createAccount() external returns (bool); ++ ++ function setPaymentDelegation(address, uint256) external; ++ function getPaymentDelegation(address) external view returns (address, uint256); ++ function isSigner(address, address, bytes32) external view returns (bool); ++}
@@ -28799,13 +131030,13 @@
- OP + (new)
@@ -28815,82 +131046,39 @@
-
+35
+
+11
-0
-
diff --git OP/op-service/predeploys/addresses.go CELO/op-service/predeploys/addresses.go -index a03fcf29188a5390aba3eb2437d31f14caf52522..f92469d247142d89504c337ed7788463de393d49 100644 ---- OP/op-service/predeploys/addresses.go -+++ CELO/op-service/predeploys/addresses.go -@@ -40,6 +40,16 @@ SenderCreator_v060 = "0x7fc98430eaedbb6070b35b39d798725049088348" - EntryPoint_v060 = "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789" - SenderCreator_v070 = "0xEFC2c1444eBCC4Db75e7613d20C6a62fF67A167C" - EntryPoint_v070 = "0x0000000071727De22E5E9d8BAf0edAc6f37da032" -+ -+ // Celo -+ CeloRegistry = "0x000000000000000000000000000000000000ce10" -+ GoldToken = "0x471ece3750da237f93b8e339c536989b8978a438" -+ FeeHandler = "0xcd437749e43a154c07f3553504c68fbfd56b8778" -+ MentoFeeHandlerSeller = "0x4efa274b7e33476c961065000d58ee09f7921a74" -+ UniswapFeeHandlerSeller = "0xd3aee28548dbb65df03981f0dc0713bfcbd10a97" -+ SortedOracles = "0xefb84935239dacdecf7c5ba76d8de40b077b7b33" -+ AddressSortedLinkedListWithMedian = "0xED477A99035d0c1e11369F1D7A4e587893cc002B" -+ FeeCurrency = "0x4200000000000000000000000000000000001022" - ) -  - var ( -@@ -80,6 +90,18 @@ EntryPoint_v070Addr = common.HexToAddress(EntryPoint_v070) -  - Predeploys = make(map[string]*Predeploy) - PredeploysByAddress = make(map[common.Address]*Predeploy) -+ -+ // Celo -+ CeloRegistryAddr = common.HexToAddress(CeloRegistry) -+ GoldTokenAddr = common.HexToAddress(GoldToken) -+ FeeHandlerAddr = common.HexToAddress(FeeHandler) -+ MentoFeeHandlerSellerAddr = common.HexToAddress(MentoFeeHandlerSeller) -+ UniswapFeeHandlerSellerAddr = common.HexToAddress(UniswapFeeHandlerSeller) -+ SortedOraclesAddr = common.HexToAddress(SortedOracles) -+ AddressSortedLinkedListWithMedianAddr = common.HexToAddress(AddressSortedLinkedListWithMedian) -+ FeeCurrencyAddr = common.HexToAddress(FeeCurrency) -+ -+ CeloPredeploys = make(map[string]*Predeploy) - ) -  - func init() { -@@ -161,6 +183,19 @@ } - Predeploys["EntryPoint_v070"] = &Predeploy{ - Address: EntryPoint_v070Addr, - ProxyDisabled: true, -+ } +
diff --git OP/packages/contracts-bedrock/src/celo/interfaces/ICeloRegistry.sol CELO/packages/contracts-bedrock/src/celo/interfaces/ICeloRegistry.sol +new file mode 100644 +index 0000000000000000000000000000000000000000..95e586da3954ffc48f18c7e781161990abab7936 +--- /dev/null ++++ CELO/packages/contracts-bedrock/src/celo/interfaces/ICeloRegistry.sol +@@ -0,0 +1,11 @@ ++// SPDX-License-Identifier: LGPL-3.0-only ++pragma solidity ^0.8.15; + -+ // Celo -+ CeloPredeploys["CeloRegistry"] = &Predeploy{Address: CeloRegistryAddr} -+ CeloPredeploys["GoldToken"] = &Predeploy{Address: GoldTokenAddr} -+ CeloPredeploys["FeeHandler"] = &Predeploy{Address: FeeHandlerAddr} -+ CeloPredeploys["MentoFeeHandlerSeller"] = &Predeploy{Address: MentoFeeHandlerSellerAddr} -+ CeloPredeploys["UniswapFeeHandlerSeller"] = &Predeploy{Address: UniswapFeeHandlerSellerAddr} -+ CeloPredeploys["SortedOracles"] = &Predeploy{Address: SortedOraclesAddr} -+ CeloPredeploys["AddressSortedLinkedListWithMedian"] = &Predeploy{Address: AddressSortedLinkedListWithMedianAddr} -+ CeloPredeploys["FeeCurrency"] = &Predeploy{Address: FeeCurrencyAddr} -+ for key, predeploy := range CeloPredeploys { -+ Predeploys[key] = predeploy - } -  - for _, predeploy := range Predeploys {
++interface ICeloRegistry { ++ function setAddressFor(string calldata, address) external; ++ function getAddressForOrDie(bytes32) external view returns (address); ++ function getAddressFor(bytes32) external view returns (address); ++ function getAddressForStringOrDie(string calldata identifier) external view returns (address); ++ function getAddressForString(string calldata identifier) external view returns (address); ++ function isOneOf(bytes32[] calldata, address) external view returns (bool); ++}
@@ -28899,13 +131087,13 @@
- OP + (new)
@@ -28915,41 +131103,42 @@
-
+3
-
-3
+
+14
+
-0
-
diff --git OP/op-service/txmgr/queue.go CELO/op-service/txmgr/queue.go -index cf83b00d5f8a0f7984e3f878545a4a2a4f92769f..ee7a03ffa92880cd20c0ef9e1e0d13eea0167be5 100644 ---- OP/op-service/txmgr/queue.go -+++ CELO/op-service/txmgr/queue.go -@@ -44,11 +44,11 @@ } - } -  - // Wait waits for all pending txs to complete (or fail). --func (q *Queue[T]) Wait() { -+func (q *Queue[T]) Wait() error { - if q.group == nil { -- return -+ return nil - } -- _ = q.group.Wait() -+ return q.group.Wait() - } -  - // Send will wait until the number of pending txs is below the max pending,
+
diff --git OP/packages/contracts-bedrock/src/celo/interfaces/ICeloToken.sol CELO/packages/contracts-bedrock/src/celo/interfaces/ICeloToken.sol +new file mode 100644 +index 0000000000000000000000000000000000000000..5bf2033f31726110e6504078561108cfee40a42d +--- /dev/null ++++ CELO/packages/contracts-bedrock/src/celo/interfaces/ICeloToken.sol +@@ -0,0 +1,14 @@ ++// SPDX-License-Identifier: LGPL-3.0-only ++pragma solidity ^0.8.15; ++ ++/** ++ * @title This interface describes the non- ERC20 shared interface for all Celo Tokens, and ++ * in the absence of interface inheritance is intended as a companion to IERC20.sol. ++ */ ++interface ICeloToken { ++ function transferWithComment(address, uint256, string calldata) external returns (bool); ++ function name() external view returns (string memory); ++ function symbol() external view returns (string memory); ++ function decimals() external view returns (uint8); ++ function burn(uint256 value) external returns (bool); ++}
@@ -28958,13 +131147,13 @@
- OP + (new)
@@ -28974,35 +131163,41 @@
-
+1
-
-1
+
+13
+
-0
-
diff --git OP/op-service/txmgr/queue_test.go CELO/op-service/txmgr/queue_test.go -index 678de8dbb28c3a7ee975edfbbe8a2c0825758686..549142c8592ac87ddc7c8d3f5e4634da9f162beb 100644 ---- OP/op-service/txmgr/queue_test.go -+++ CELO/op-service/txmgr/queue_test.go -@@ -222,7 +222,7 @@ queued := c.call(i, candidate, receiptChs[i], queue) - require.Equal(t, c.queued, queued, msg) - } - // wait for the queue to drain (all txs complete or failed) -- queue.Wait() -+ _ = queue.Wait() - duration := time.Since(start) - // expect the execution time within a certain window - now := time.Now()
+
diff --git OP/packages/contracts-bedrock/src/celo/interfaces/ICeloVersionedContract.sol CELO/packages/contracts-bedrock/src/celo/interfaces/ICeloVersionedContract.sol +new file mode 100644 +index 0000000000000000000000000000000000000000..37b1538c2a121b4dd73b5762db9ba4a97364581c +--- /dev/null ++++ CELO/packages/contracts-bedrock/src/celo/interfaces/ICeloVersionedContract.sol +@@ -0,0 +1,13 @@ ++// SPDX-License-Identifier: LGPL-3.0-only ++pragma solidity ^0.8.15; ++ ++interface ICeloVersionedContract { ++ /** ++ * @notice Returns the storage, major, minor, and patch version of the contract. ++ * @return Storage version of the contract. ++ * @return Major version of the contract. ++ * @return Minor version of the contract. ++ * @return Patch version of the contract. ++ */ ++ function getVersionNumber() external pure returns (uint256, uint256, uint256, uint256); ++}
@@ -29017,7 +131212,7 @@
@@ -29027,298 +131222,47 @@
-
+280
+
+29
-0
-
diff --git OP/packages/contracts-bedrock/lib/multicall/src/Multicall3.sol CELO/packages/contracts-bedrock/lib/multicall/src/Multicall3.sol +
diff --git OP/packages/contracts-bedrock/src/celo/interfaces/IFeeCurrencyDirectory.sol CELO/packages/contracts-bedrock/src/celo/interfaces/IFeeCurrencyDirectory.sol new file mode 100644 -index 0000000000000000000000000000000000000000..92195a5e91b974b51d163cdf29f56f02f2b149c9 +index 0000000000000000000000000000000000000000..5c6ab9051ccf28eebd9f8482ae22b9e9df8e939f --- /dev/null -+++ CELO/packages/contracts-bedrock/lib/multicall/src/Multicall3.sol -@@ -0,0 +1,280 @@ ++++ CELO/packages/contracts-bedrock/src/celo/interfaces/IFeeCurrencyDirectory.sol +@@ -0,0 +1,29 @@ +// SPDX-License-Identifier: MIT -+pragma solidity ^0.8.12; -+ -+/// @title Multicall3 -+/// @notice Aggregate results from multiple function calls -+/// @dev Multicall & Multicall2 backwards-compatible -+/// @dev Aggregate methods are marked `payable` to save 24 gas per call -+/// @author Michael Elliot <mike@makerdao.com> -+/// @author Joshua Levine <joshua@makerdao.com> -+/// @author Nick Johnson <arachnid@notdot.net> -+/// @author Andreas Bigger <andreas@nascent.xyz> -+/// @author Matt Solomon <matt@mattsolomon.dev> -+contract Multicall3 { -+ struct Call { -+ address target; -+ bytes callData; -+ } -+ -+ struct Call3 { -+ address target; -+ bool allowFailure; -+ bytes callData; -+ } -+ -+ struct Call3Value { -+ address target; -+ bool allowFailure; -+ uint256 value; -+ bytes callData; -+ } -+ -+ struct Result { -+ bool success; -+ bytes returnData; -+ } -+ -+ /// @notice Backwards-compatible call aggregation with Multicall -+ /// @param calls An array of Call structs -+ /// @return blockNumber The block number where the calls were executed -+ /// @return returnData An array of bytes containing the responses -+ function aggregate( -+ Call[] calldata calls -+ ) public payable returns (uint256 blockNumber, bytes[] memory returnData) { -+ blockNumber = block.number; -+ uint256 length = calls.length; -+ returnData = new bytes[](length); -+ Call calldata call; -+ for (uint256 i = 0; i < length; ) { -+ bool success; -+ call = calls[i]; -+ (success, returnData[i]) = call.target.call(call.callData); -+ require(success, 'Multicall3: call failed'); -+ unchecked { -+ ++i; -+ } -+ } -+ } -+ -+ /// @notice Backwards-compatible with Multicall2 -+ /// @notice Aggregate calls without requiring success -+ /// @param requireSuccess If true, require all calls to succeed -+ /// @param calls An array of Call structs -+ /// @return returnData An array of Result structs -+ function tryAggregate( -+ bool requireSuccess, -+ Call[] calldata calls -+ ) public payable returns (Result[] memory returnData) { -+ uint256 length = calls.length; -+ returnData = new Result[](length); -+ Call calldata call; -+ for (uint256 i = 0; i < length; ) { -+ Result memory result = returnData[i]; -+ call = calls[i]; -+ (result.success, result.returnData) = call.target.call(call.callData); -+ if (requireSuccess) require(result.success, 'Multicall3: call failed'); -+ unchecked { -+ ++i; -+ } -+ } -+ } -+ -+ /// @notice Backwards-compatible with Multicall2 -+ /// @notice Aggregate calls and allow failures using tryAggregate -+ /// @param calls An array of Call structs -+ /// @return blockNumber The block number where the calls were executed -+ /// @return blockHash The hash of the block where the calls were executed -+ /// @return returnData An array of Result structs -+ function tryBlockAndAggregate( -+ bool requireSuccess, -+ Call[] calldata calls -+ ) -+ public -+ payable -+ returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData) -+ { -+ blockNumber = block.number; -+ blockHash = blockhash(block.number); -+ returnData = tryAggregate(requireSuccess, calls); -+ } -+ -+ /// @notice Backwards-compatible with Multicall2 -+ /// @notice Aggregate calls and allow failures using tryAggregate -+ /// @param calls An array of Call structs -+ /// @return blockNumber The block number where the calls were executed -+ /// @return blockHash The hash of the block where the calls were executed -+ /// @return returnData An array of Result structs -+ function blockAndAggregate( -+ Call[] calldata calls -+ ) -+ public -+ payable -+ returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData) -+ { -+ (blockNumber, blockHash, returnData) = tryBlockAndAggregate(true, calls); -+ } -+ -+ /// @notice Aggregate calls, ensuring each returns success if required -+ /// @param calls An array of Call3 structs -+ /// @return returnData An array of Result structs -+ function aggregate3( -+ Call3[] calldata calls -+ ) public payable returns (Result[] memory returnData) { -+ uint256 length = calls.length; -+ returnData = new Result[](length); -+ Call3 calldata calli; -+ for (uint256 i = 0; i < length; ) { -+ Result memory result = returnData[i]; -+ calli = calls[i]; -+ (result.success, result.returnData) = calli.target.call(calli.callData); -+ assembly { -+ // Revert if the call fails and failure is not allowed -+ // `allowFailure := calldataload(add(calli, 0x20))` and `success := mload(result)` -+ if iszero(or(calldataload(add(calli, 0x20)), mload(result))) { -+ // set "Error(string)" signature: bytes32(bytes4(keccak256("Error(string)"))) -+ mstore( -+ 0x00, -+ 0x08c379a000000000000000000000000000000000000000000000000000000000 -+ ) -+ // set data offset -+ mstore( -+ 0x04, -+ 0x0000000000000000000000000000000000000000000000000000000000000020 -+ ) -+ // set length of revert string -+ mstore( -+ 0x24, -+ 0x0000000000000000000000000000000000000000000000000000000000000017 -+ ) -+ // set revert string: bytes32(abi.encodePacked("Multicall3: call failed")) -+ mstore( -+ 0x44, -+ 0x4d756c746963616c6c333a2063616c6c206661696c6564000000000000000000 -+ ) -+ revert(0x00, 0x64) -+ } -+ } -+ unchecked { -+ ++i; -+ } -+ } -+ } -+ -+ /// @notice Aggregate calls with a msg value -+ /// @notice Reverts if msg.value is less than the sum of the call values -+ /// @param calls An array of Call3Value structs -+ /// @return returnData An array of Result structs -+ function aggregate3Value( -+ Call3Value[] calldata calls -+ ) public payable returns (Result[] memory returnData) { -+ uint256 valAccumulator; -+ uint256 length = calls.length; -+ returnData = new Result[](length); -+ Call3Value calldata calli; -+ for (uint256 i = 0; i < length; ) { -+ Result memory result = returnData[i]; -+ calli = calls[i]; -+ uint256 val = calli.value; -+ // Humanity will be a Type V Kardashev Civilization before this overflows - andreas -+ // ~ 10^25 Wei in existence << ~ 10^76 size uint fits in a uint256 -+ unchecked { -+ valAccumulator += val; -+ } -+ (result.success, result.returnData) = calli.target.call{value: val}( -+ calli.callData -+ ); -+ assembly { -+ // Revert if the call fails and failure is not allowed -+ // `allowFailure := calldataload(add(calli, 0x20))` and `success := mload(result)` -+ if iszero(or(calldataload(add(calli, 0x20)), mload(result))) { -+ // set "Error(string)" signature: bytes32(bytes4(keccak256("Error(string)"))) -+ mstore( -+ 0x00, -+ 0x08c379a000000000000000000000000000000000000000000000000000000000 -+ ) -+ // set data offset -+ mstore( -+ 0x04, -+ 0x0000000000000000000000000000000000000000000000000000000000000020 -+ ) -+ // set length of revert string -+ mstore( -+ 0x24, -+ 0x0000000000000000000000000000000000000000000000000000000000000017 -+ ) -+ // set revert string: bytes32(abi.encodePacked("Multicall3: call failed")) -+ mstore( -+ 0x44, -+ 0x4d756c746963616c6c333a2063616c6c206661696c6564000000000000000000 -+ ) -+ revert(0x00, 0x84) -+ } -+ } -+ unchecked { -+ ++i; -+ } -+ } -+ // Finally, make sure the msg.value = SUM(call[0...i].value) -+ require(msg.value == valAccumulator, 'Multicall3: value mismatch'); -+ } -+ -+ /// @notice Returns the block hash for the given block number -+ /// @param blockNumber The block number -+ function getBlockHash( -+ uint256 blockNumber -+ ) public view returns (bytes32 blockHash) { -+ blockHash = blockhash(blockNumber); -+ } -+ -+ /// @notice Returns the block number -+ function getBlockNumber() public view returns (uint256 blockNumber) { -+ blockNumber = block.number; -+ } -+ -+ /// @notice Returns the block coinbase -+ function getCurrentBlockCoinbase() public view returns (address coinbase) { -+ coinbase = block.coinbase; -+ } -+ -+ /// @notice Returns the block difficulty -+ function getCurrentBlockDifficulty() -+ public -+ view -+ returns (uint256 difficulty) -+ { -+ difficulty = block.difficulty; -+ } -+ -+ /// @notice Returns the block gas limit -+ function getCurrentBlockGasLimit() public view returns (uint256 gaslimit) { -+ gaslimit = block.gaslimit; -+ } -+ -+ /// @notice Returns the block timestamp -+ function getCurrentBlockTimestamp() public view returns (uint256 timestamp) { -+ timestamp = block.timestamp; -+ } -+ -+ /// @notice Returns the (ETH) balance of a given address -+ function getEthBalance(address addr) public view returns (uint256 balance) { -+ balance = addr.balance; -+ } ++pragma solidity ^0.8.0; + -+ /// @notice Returns the block hash of the last block -+ function getLastBlockHash() public view returns (bytes32 blockHash) { -+ unchecked { -+ blockHash = blockhash(block.number - 1); ++interface IFeeCurrencyDirectory { ++ struct CurrencyConfig { ++ address oracle; ++ uint256 intrinsicGas; + } -+ } + -+ /// @notice Gets the base fee of the given block -+ /// @notice Can revert if the BASEFEE opcode is not implemented by the given chain -+ function getBasefee() public view returns (uint256 basefee) { -+ basefee = block.basefee; -+ } ++ /** ++ * @notice Returns the list of all currency addresses. ++ * @return An array of addresses. ++ */ ++ function getCurrencies() external view returns (address[] memory); ++ /** ++ * @notice Returns the configuration for a currency. ++ * @param token The address of the token. ++ * @return Currency configuration of the token. ++ */ ++ function getCurrencyConfig(address token) external view returns (CurrencyConfig memory); + -+ /// @notice Returns the chain id -+ function getChainId() public view returns (uint256 chainid) { -+ chainid = block.chainid; -+ } ++ /** ++ * @notice Retrieves exchange rate between token and CELO. ++ * @param token The token address whose price is to be fetched. ++ * @return numerator The exchange rate numerator. ++ * @return denominator The exchange rate denominator. ++ */ ++ function getExchangeRate(address token) external view returns (uint256 numerator, uint256 denominator); +}
@@ -29326,9 +131270,9 @@
@@ -29343,7 +131287,7 @@
@@ -29353,306 +131297,113 @@
-
+288
+
+6
-0
-
diff --git OP/packages/contracts-bedrock/src/celo/common/FixidityLib.sol CELO/packages/contracts-bedrock/src/celo/common/FixidityLib.sol +
diff --git OP/packages/contracts-bedrock/src/celo/interfaces/IFreezer.sol CELO/packages/contracts-bedrock/src/celo/interfaces/IFreezer.sol new file mode 100644 -index 0000000000000000000000000000000000000000..613da18562198968356b17cffa9890cb364b2063 +index 0000000000000000000000000000000000000000..a629b3325a5ba883298aa61d85f260573fe042a8 --- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/common/FixidityLib.sol -@@ -0,0 +1,288 @@ ++++ CELO/packages/contracts-bedrock/src/celo/interfaces/IFreezer.sol +@@ -0,0 +1,6 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity ^0.8.15; + -+/** -+ * @title FixidityLib -+ * @author Gadi Guy, Alberto Cuesta Canada -+ * @notice This library provides fixed point arithmetic with protection against -+ * overflow. -+ * All operations are done with uint256 and the operands must have been created -+ * with any of the newFrom* functions, which shift the comma digits() to the -+ * right and check for limits, or with wrap() which expects a number already -+ * in the internal representation of a fraction. -+ * When using this library be sure to use maxNewFixed() as the upper limit for -+ * creation of fixed point numbers. -+ * @dev All contained functions are pure and thus marked internal to be inlined -+ * on consuming contracts at compile time for gas efficiency. -+ */ -+library FixidityLib { -+ struct Fraction { -+ uint256 value; -+ } -+ -+ /** -+ * @notice Number of positions that the comma is shifted to the right. -+ */ -+ function digits() internal pure returns (uint8) { -+ return 24; -+ } -+ -+ uint256 private constant FIXED1_UINT = 1000000000000000000000000; -+ -+ /** -+ * @notice This is 1 in the fixed point units used in this library. -+ * @dev Test fixed1() equals 10^digits() -+ * Hardcoded to 24 digits. -+ */ -+ function fixed1() internal pure returns (Fraction memory) { -+ return Fraction(FIXED1_UINT); -+ } -+ -+ /** -+ * @notice Wrap a uint256 that represents a 24-decimal fraction in a Fraction -+ * struct. -+ * @param x Number that already represents a 24-decimal fraction. -+ * @return A Fraction struct with contents x. -+ */ -+ function wrap(uint256 x) internal pure returns (Fraction memory) { -+ return Fraction(x); -+ } -+ -+ /** -+ * @notice Unwraps the uint256 inside of a Fraction struct. -+ */ -+ function unwrap(Fraction memory x) internal pure returns (uint256) { -+ return x.value; -+ } -+ -+ /** -+ * @notice The amount of decimals lost on each multiplication operand. -+ * @dev Test mulPrecision() equals sqrt(fixed1) -+ */ -+ function mulPrecision() internal pure returns (uint256) { -+ return 1000000000000; -+ } -+ -+ /** -+ * @notice Maximum value that can be converted to fixed point. Optimize for deployment. -+ * @dev -+ * Test maxNewFixed() equals maxUint256() / fixed1() -+ */ -+ function maxNewFixed() internal pure returns (uint256) { -+ return 115792089237316195423570985008687907853269984665640564; -+ } -+ -+ /** -+ * @notice Converts a uint256 to fixed point Fraction -+ * @dev Test newFixed(0) returns 0 -+ * Test newFixed(1) returns fixed1() -+ * Test newFixed(maxNewFixed()) returns maxNewFixed() * fixed1() -+ * Test newFixed(maxNewFixed()+1) fails -+ */ -+ function newFixed(uint256 x) internal pure returns (Fraction memory) { -+ require(x <= maxNewFixed(), "can't create fixidity number larger than maxNewFixed()"); -+ return Fraction(x * FIXED1_UINT); -+ } -+ -+ /** -+ * @notice Converts a uint256 in the fixed point representation of this -+ * library to a non decimal. All decimal digits will be truncated. -+ */ -+ function fromFixed(Fraction memory x) internal pure returns (uint256) { -+ return x.value / FIXED1_UINT; -+ } -+ -+ /** -+ * @notice Converts two uint256 representing a fraction to fixed point units, -+ * equivalent to multiplying dividend and divisor by 10^digits(). -+ * @param numerator numerator must be <= maxNewFixed() -+ * @param denominator denominator must be <= maxNewFixed() and denominator can't be 0 -+ * @dev -+ * Test newFixedFraction(1,0) fails -+ * Test newFixedFraction(0,1) returns 0 -+ * Test newFixedFraction(1,1) returns fixed1() -+ * Test newFixedFraction(1,fixed1()) returns 1 -+ */ -+ function newFixedFraction(uint256 numerator, uint256 denominator) internal pure returns (Fraction memory) { -+ Fraction memory convertedNumerator = newFixed(numerator); -+ Fraction memory convertedDenominator = newFixed(denominator); -+ return divide(convertedNumerator, convertedDenominator); -+ } -+ -+ /** -+ * @notice Returns the integer part of a fixed point number. -+ * @dev -+ * Test integer(0) returns 0 -+ * Test integer(fixed1()) returns fixed1() -+ * Test integer(newFixed(maxNewFixed())) returns maxNewFixed()*fixed1() -+ */ -+ function integer(Fraction memory x) internal pure returns (Fraction memory) { -+ return Fraction((x.value / FIXED1_UINT) * FIXED1_UINT); // Can't overflow -+ } -+ -+ /** -+ * @notice Returns the fractional part of a fixed point number. -+ * In the case of a negative number the fractional is also negative. -+ * @dev -+ * Test fractional(0) returns 0 -+ * Test fractional(fixed1()) returns 0 -+ * Test fractional(fixed1()-1) returns 10^24-1 -+ */ -+ function fractional(Fraction memory x) internal pure returns (Fraction memory) { -+ return Fraction(x.value - (x.value / FIXED1_UINT) * FIXED1_UINT); // Can't overflow -+ } -+ -+ /** -+ * @notice x+y. -+ * @dev The maximum value that can be safely used as an addition operator is defined as -+ * maxFixedAdd = maxUint256()-1 / 2, or -+ * 57896044618658097711785492504343953926634992332820282019728792003956564819967. -+ * Test add(maxFixedAdd,maxFixedAdd) equals maxFixedAdd + maxFixedAdd -+ * Test add(maxFixedAdd+1,maxFixedAdd+1) throws -+ */ -+ function add(Fraction memory x, Fraction memory y) internal pure returns (Fraction memory) { -+ uint256 z = x.value + y.value; -+ require(z >= x.value, "add overflow detected"); -+ return Fraction(z); -+ } -+ -+ /** -+ * @notice x-y. -+ * @dev -+ * Test subtract(6, 10) fails -+ */ -+ function subtract(Fraction memory x, Fraction memory y) internal pure returns (Fraction memory) { -+ require(x.value >= y.value, "substraction underflow detected"); -+ return Fraction(x.value - y.value); -+ } -+ -+ /** -+ * @notice x*y. If any of the operators is higher than the max multiplier value it -+ * might overflow. -+ * @dev The maximum value that can be safely used as a multiplication operator -+ * (maxFixedMul) is calculated as sqrt(maxUint256()*fixed1()), -+ * or 340282366920938463463374607431768211455999999999999 -+ * Test multiply(0,0) returns 0 -+ * Test multiply(maxFixedMul,0) returns 0 -+ * Test multiply(0,maxFixedMul) returns 0 -+ * Test multiply(fixed1()/mulPrecision(),fixed1()*mulPrecision()) returns fixed1() -+ * Test multiply(maxFixedMul,maxFixedMul) is around maxUint256() -+ * Test multiply(maxFixedMul+1,maxFixedMul+1) fails -+ */ -+ function multiply(Fraction memory x, Fraction memory y) internal pure returns (Fraction memory) { -+ if (x.value == 0 || y.value == 0) return Fraction(0); -+ if (y.value == FIXED1_UINT) return x; -+ if (x.value == FIXED1_UINT) return y; -+ -+ // Separate into integer and fractional parts -+ // x = x1 + x2, y = y1 + y2 -+ uint256 x1 = integer(x).value / FIXED1_UINT; -+ uint256 x2 = fractional(x).value; -+ uint256 y1 = integer(y).value / FIXED1_UINT; -+ uint256 y2 = fractional(y).value; -+ -+ // (x1 + x2) * (y1 + y2) = (x1 * y1) + (x1 * y2) + (x2 * y1) + (x2 * y2) -+ uint256 x1y1 = x1 * y1; -+ if (x1 != 0) require(x1y1 / x1 == y1, "overflow x1y1 detected"); -+ -+ // x1y1 needs to be multiplied back by fixed1 -+ // solium-disable-next-line mixedcase -+ uint256 fixed_x1y1 = x1y1 * FIXED1_UINT; -+ if (x1y1 != 0) require(fixed_x1y1 / x1y1 == FIXED1_UINT, "overflow x1y1 * fixed1 detected"); -+ x1y1 = fixed_x1y1; -+ -+ uint256 x2y1 = x2 * y1; -+ if (x2 != 0) require(x2y1 / x2 == y1, "overflow x2y1 detected"); -+ -+ uint256 x1y2 = x1 * y2; -+ if (x1 != 0) require(x1y2 / x1 == y2, "overflow x1y2 detected"); -+ -+ x2 = x2 / mulPrecision(); -+ y2 = y2 / mulPrecision(); -+ uint256 x2y2 = x2 * y2; -+ if (x2 != 0) require(x2y2 / x2 == y2, "overflow x2y2 detected"); -+ -+ // result = fixed1() * x1 * y1 + x1 * y2 + x2 * y1 + x2 * y2 / fixed1(); -+ Fraction memory result = Fraction(x1y1); -+ result = add(result, Fraction(x2y1)); // Add checks for overflow -+ result = add(result, Fraction(x1y2)); // Add checks for overflow -+ result = add(result, Fraction(x2y2)); // Add checks for overflow -+ return result; -+ } -+ -+ /** -+ * @notice 1/x -+ * @dev -+ * Test reciprocal(0) fails -+ * Test reciprocal(fixed1()) returns fixed1() -+ * Test reciprocal(fixed1()*fixed1()) returns 1 // Testing how the fractional is truncated -+ * Test reciprocal(1+fixed1()*fixed1()) returns 0 // Testing how the fractional is truncated -+ * Test reciprocal(newFixedFraction(1, 1e24)) returns newFixed(1e24) -+ */ -+ function reciprocal(Fraction memory x) internal pure returns (Fraction memory) { -+ require(x.value != 0, "can't call reciprocal(0)"); -+ return Fraction((FIXED1_UINT * FIXED1_UINT) / x.value); // Can't overflow -+ } -+ -+ /** -+ * @notice x/y. If the dividend is higher than the max dividend value, it -+ * might overflow. You can use multiply(x,reciprocal(y)) instead. -+ * @dev The maximum value that can be safely used as a dividend (maxNewFixed) is defined as -+ * divide(maxNewFixed,newFixedFraction(1,fixed1())) is around maxUint256(). -+ * This yields the value 115792089237316195423570985008687907853269984665640564. -+ * Test maxNewFixed equals maxUint256()/fixed1() -+ * Test divide(maxNewFixed,1) equals maxNewFixed*(fixed1) -+ * Test divide(maxNewFixed+1,multiply(mulPrecision(),mulPrecision())) throws -+ * Test divide(fixed1(),0) fails -+ * Test divide(maxNewFixed,1) = maxNewFixed*(10^digits()) -+ * Test divide(maxNewFixed+1,1) throws -+ */ -+ function divide(Fraction memory x, Fraction memory y) internal pure returns (Fraction memory) { -+ require(y.value != 0, "can't divide by 0"); -+ uint256 X = x.value * FIXED1_UINT; -+ require(X / FIXED1_UINT == x.value, "overflow at divide"); -+ return Fraction(X / y.value); -+ } -+ -+ /** -+ * @notice x > y -+ */ -+ function gt(Fraction memory x, Fraction memory y) internal pure returns (bool) { -+ return x.value > y.value; -+ } -+ -+ /** -+ * @notice x >= y -+ */ -+ function gte(Fraction memory x, Fraction memory y) internal pure returns (bool) { -+ return x.value >= y.value; -+ } -+ -+ /** -+ * @notice x < y -+ */ -+ function lt(Fraction memory x, Fraction memory y) internal pure returns (bool) { -+ return x.value < y.value; -+ } ++interface IFreezer { ++ function isFrozen(address) external view returns (bool); ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+43
+
-0
+ +
+ +
+
+
diff --git OP/packages/contracts-bedrock/src/celo/interfaces/IMetaTransactionWallet.sol CELO/packages/contracts-bedrock/src/celo/interfaces/IMetaTransactionWallet.sol +new file mode 100644 +index 0000000000000000000000000000000000000000..5c7f392814b615b6b35ec6de7e4a044708fec8df +--- /dev/null ++++ CELO/packages/contracts-bedrock/src/celo/interfaces/IMetaTransactionWallet.sol +@@ -0,0 +1,43 @@ ++// SPDX-License-Identifier: LGPL-3.0-only ++pragma solidity ^0.8.15; + -+ /** -+ * @notice x <= y -+ */ -+ function lte(Fraction memory x, Fraction memory y) internal pure returns (bool) { -+ return x.value <= y.value; -+ } ++interface IMetaTransactionWallet { ++ function setEip712DomainSeparator() external; ++ function executeMetaTransaction( ++ address, ++ uint256, ++ bytes calldata, ++ uint8, ++ bytes32, ++ bytes32 ++ ) ++ external ++ returns (bytes memory); ++ function executeTransaction(address, uint256, bytes calldata) external returns (bytes memory); ++ function executeTransactions( ++ address[] calldata, ++ uint256[] calldata, ++ bytes calldata, ++ uint256[] calldata ++ ) ++ external ++ returns (bytes memory, uint256[] memory); + -+ /** -+ * @notice x == y -+ */ -+ function equals(Fraction memory x, Fraction memory y) internal pure returns (bool) { -+ return x.value == y.value; -+ } ++ // view functions ++ function getMetaTransactionDigest(address, uint256, bytes calldata, uint256) external view returns (bytes32); ++ function getMetaTransactionSigner( ++ address, ++ uint256, ++ bytes calldata, ++ uint256, ++ uint8, ++ bytes32, ++ bytes32 ++ ) ++ external ++ view ++ returns (address); + -+ /** -+ * @notice x <= 1 -+ */ -+ function isProperFraction(Fraction memory x) internal pure returns (bool) { -+ return lte(x, fixed1()); -+ } ++ //only owner ++ function setSigner(address) external; +}
@@ -29660,9 +131411,9 @@
@@ -29677,7 +131428,7 @@
@@ -29687,31 +131438,24 @@
-
+13
+
+6
-0
-
diff --git OP/packages/contracts-bedrock/src/celo/common/Freezable.sol CELO/packages/contracts-bedrock/src/celo/common/Freezable.sol +
diff --git OP/packages/contracts-bedrock/src/celo/interfaces/IMetaTransactionWalletDeployer.sol CELO/packages/contracts-bedrock/src/celo/interfaces/IMetaTransactionWalletDeployer.sol new file mode 100644 -index 0000000000000000000000000000000000000000..7541ea6fa5717fbe7905c58637c276771a63f9cb +index 0000000000000000000000000000000000000000..5828bee3c7467f9386974465a6a3fee00c3ef65f --- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/common/Freezable.sol -@@ -0,0 +1,13 @@ -+// SPDX-License-Identifier: MIT ++++ CELO/packages/contracts-bedrock/src/celo/interfaces/IMetaTransactionWalletDeployer.sol +@@ -0,0 +1,6 @@ ++// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity ^0.8.15; + -+import "../UsingRegistry.sol"; -+ -+contract Freezable is UsingRegistry { -+ // onlyWhenNotFrozen functions can only be called when `frozen` is false, otherwise they will -+ // revert. -+ modifier onlyWhenNotFrozen() { -+ require(!getFreezer().isFrozen(address(this)), "can't call when contract is frozen"); -+ _; -+ } ++interface IMetaTransactionWalletDeployer { ++ function deploy(address, address, bytes calldata) external; +}
@@ -29719,9 +131463,9 @@
@@ -29736,7 +131480,7 @@
@@ -29746,36 +131490,170 @@
-
+18
+
+7
-0
-
diff --git OP/packages/contracts-bedrock/src/celo/common/Initializable.sol CELO/packages/contracts-bedrock/src/celo/common/Initializable.sol +
diff --git OP/packages/contracts-bedrock/src/celo/interfaces/IOracle.sol CELO/packages/contracts-bedrock/src/celo/interfaces/IOracle.sol new file mode 100644 -index 0000000000000000000000000000000000000000..92baac5494d3b0324d3d506d0607f38199028b30 +index 0000000000000000000000000000000000000000..b3ae66a92756c915ede5a6c5b1f57387b2edc254 --- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/common/Initializable.sol -@@ -0,0 +1,18 @@ ++++ CELO/packages/contracts-bedrock/src/celo/interfaces/IOracle.sol +@@ -0,0 +1,7 @@ +// SPDX-License-Identifier: MIT -+pragma solidity ^0.8.15; ++pragma solidity >=0.5.13 <0.9.0; ++ ++/// Possibly not final version ++interface IOracle { ++ function getExchangeRate(address token) external view returns (uint256 numerator, uint256 denominator); ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+99
+
-0
+ +
+ +
+
+
diff --git OP/packages/contracts-bedrock/src/celo/interfaces/IStableToken.sol CELO/packages/contracts-bedrock/src/celo/interfaces/IStableToken.sol +new file mode 100644 +index 0000000000000000000000000000000000000000..b13febff81fc8c95da5bc8567fdbcc64938c9d19 +--- /dev/null ++++ CELO/packages/contracts-bedrock/src/celo/interfaces/IStableToken.sol +@@ -0,0 +1,99 @@ ++// SPDX-License-Identifier: GPL-3.0-or-later ++pragma solidity >=0.5.17 <9.0.0; ++ ++interface IStableTokenV2 { ++ function totalSupply() external view returns (uint256); ++ ++ function balanceOf(address account) external view returns (uint256); ++ ++ function transfer(address recipient, uint256 amount) external returns (bool); ++ ++ function allowance(address owner, address spender) external view returns (uint256); ++ ++ function approve(address spender, uint256 amount) external returns (bool); ++ ++ function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); ++ ++ function mint(address, uint256) external returns (bool); ++ ++ function burn(uint256) external returns (bool); ++ ++ function permit( ++ address owner, ++ address spender, ++ uint256 value, ++ uint256 deadline, ++ uint8 v, ++ bytes32 r, ++ bytes32 s ++ ) ++ external; ++ ++ /** ++ * @notice Transfer token for a specified address ++ * @param to The address to transfer to. ++ * @param value The amount to be transferred. ++ * @param comment The transfer comment. ++ * @return True if the transaction succeeds. ++ */ ++ function transferWithComment(address to, uint256 value, string calldata comment) external returns (bool); ++ ++ /** ++ * @notice Initializes a StableTokenV2. ++ * It keeps the same signature as the original initialize() function ++ * in legacy/StableToken.sol ++ * @param _name The name of the stable token (English) ++ * @param _symbol A short symbol identifying the token (e.g. "cUSD") ++ * @param initialBalanceAddresses Array of addresses with an initial balance. ++ * @param initialBalanceValues Array of balance values corresponding to initialBalanceAddresses. ++ * deprecated-param exchangeIdentifier String identifier of exchange in registry (for specific fiat pairs) ++ */ ++ function initialize( ++ string calldata _name, ++ string calldata _symbol, ++ address[] calldata initialBalanceAddresses, ++ uint256[] calldata initialBalanceValues ++ ) ++ external; + -+contract Initializable { -+ bool public initialized; ++ /** ++ * @notice Initializes a StableTokenV2 contract ++ * when upgrading from legacy/StableToken.sol. ++ * It sets the addresses that were previously read from the Registry. ++ * It runs the ERC20PermitUpgradeable initializer. ++ * @dev This function is only callable once. ++ * @param _broker The address of the Broker contract. ++ * @param _validators The address of the Validators contract. ++ * @param _exchange The address of the Exchange contract. ++ */ ++ function initializeV2(address _broker, address _validators, address _exchange) external; + -+ constructor(bool testingDeployment) { -+ if (!testingDeployment) { -+ initialized = true; -+ } -+ } ++ /** ++ * @notice Gets the address of the Broker contract. ++ */ ++ function broker() external returns (address); + -+ modifier initializer() { -+ require(!initialized, "contract already initialized"); -+ initialized = true; -+ _; -+ } ++ /** ++ * @notice Gets the address of the Validators contract. ++ */ ++ function validators() external returns (address); ++ ++ /** ++ * @notice Gets the address of the Exchange contract. ++ */ ++ function exchange() external returns (address); ++ ++ function debitGasFees(address from, uint256 value) external; ++ ++ function creditGasFees( ++ address from, ++ address feeRecipient, ++ address gatewayFeeRecipient, ++ address communityFund, ++ uint256 refund, ++ uint256 tipTxFee, ++ uint256 gatewayFee, ++ uint256 baseTxFee ++ ) ++ external; +}
@@ -29783,9 +131661,9 @@
@@ -29800,7 +131678,7 @@
@@ -29810,32 +131688,45 @@
-
+14
+
+27
-0
-
diff --git OP/packages/contracts-bedrock/src/celo/common/interfaces/ICeloToken.sol CELO/packages/contracts-bedrock/src/celo/common/interfaces/ICeloToken.sol +
diff --git OP/packages/contracts-bedrock/src/celo/interfaces/IStableTokenMento.sol CELO/packages/contracts-bedrock/src/celo/interfaces/IStableTokenMento.sol new file mode 100644 -index 0000000000000000000000000000000000000000..5bf2033f31726110e6504078561108cfee40a42d +index 0000000000000000000000000000000000000000..b309071d9f0ad88f27ece5e2648d4fa51465b741 --- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/common/interfaces/ICeloToken.sol -@@ -0,0 +1,14 @@ ++++ CELO/packages/contracts-bedrock/src/celo/interfaces/IStableTokenMento.sol +@@ -0,0 +1,27 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity ^0.8.15; + +/** -+ * @title This interface describes the non- ERC20 shared interface for all Celo Tokens, and -+ * in the absence of interface inheritance is intended as a companion to IERC20.sol. ++ * @title This interface describes the functions specific to Celo Stable Tokens, and in the ++ * absence of interface inheritance is intended as a companion to IERC20.sol and ICeloToken.sol. + */ -+interface ICeloToken { -+ function transferWithComment(address, uint256, string calldata) external returns (bool); -+ function name() external view returns (string memory); -+ function symbol() external view returns (string memory); -+ function decimals() external view returns (uint8); -+ function burn(uint256 value) external returns (bool); ++interface IStableTokenMento { ++ function mint(address, uint256) external returns (bool); ++ ++ function burn(uint256) external returns (bool); ++ ++ function setInflationParameters(uint256, uint256) external; ++ ++ function valueToUnits(uint256) external view returns (uint256); ++ ++ function unitsToValue(uint256) external view returns (uint256); ++ ++ function getInflationParameters() external view returns (uint256, uint256, uint256, uint256); ++ ++ // NOTE: duplicated with IERC20.sol, remove once interface inheritance is supported. ++ function balanceOf(address) external view returns (uint256); ++ ++ function getExchangeRegistryId() external view returns (bytes32); ++ ++ function approve(address spender, uint256 value) external returns (bool); +}
@@ -29843,9 +131734,9 @@
@@ -29860,7 +131751,7 @@
@@ -29870,31 +131761,36 @@
-
+13
+
+18
-0
-
diff --git OP/packages/contracts-bedrock/src/celo/common/interfaces/ICeloVersionedContract.sol CELO/packages/contracts-bedrock/src/celo/common/interfaces/ICeloVersionedContract.sol +
diff --git OP/packages/contracts-bedrock/src/celo/mento/interfaces/IExchange.sol CELO/packages/contracts-bedrock/src/celo/mento/interfaces/IExchange.sol new file mode 100644 -index 0000000000000000000000000000000000000000..37b1538c2a121b4dd73b5762db9ba4a97364581c +index 0000000000000000000000000000000000000000..4e15e8a8750d45e28c6fc9eb7e483bf39591fa0b --- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/common/interfaces/ICeloVersionedContract.sol -@@ -0,0 +1,13 @@ ++++ CELO/packages/contracts-bedrock/src/celo/mento/interfaces/IExchange.sol +@@ -0,0 +1,18 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity ^0.8.15; + -+interface ICeloVersionedContract { -+ /** -+ * @notice Returns the storage, major, minor, and patch version of the contract. -+ * @return Storage version of the contract. -+ * @return Major version of the contract. -+ * @return Minor version of the contract. -+ * @return Patch version of the contract. -+ */ -+ function getVersionNumber() external pure returns (uint256, uint256, uint256, uint256); ++interface IExchange { ++ function buy(uint256, uint256, bool) external returns (uint256); ++ ++ function sell(uint256, uint256, bool) external returns (uint256); ++ ++ function exchange(uint256, uint256, bool) external returns (uint256); ++ ++ function setUpdateFrequency(uint256) external; ++ ++ function getBuyTokenAmount(uint256, bool) external view returns (uint256); ++ ++ function getSellTokenAmount(uint256, bool) external view returns (uint256); ++ ++ function getBuyAndSellBuckets(bool) external view returns (uint256, uint256); +}
@@ -29902,9 +131798,9 @@
@@ -29919,7 +131815,7 @@
@@ -29929,57 +131825,50 @@
-
+39
+
+32
-0
-
diff --git OP/packages/contracts-bedrock/src/celo/common/interfaces/IFeeHandler.sol CELO/packages/contracts-bedrock/src/celo/common/interfaces/IFeeHandler.sol +
diff --git OP/packages/contracts-bedrock/src/celo/mento/interfaces/IReserve.sol CELO/packages/contracts-bedrock/src/celo/mento/interfaces/IReserve.sol new file mode 100644 -index 0000000000000000000000000000000000000000..b707a446a685ac27778cd547f44932a4d92c127b +index 0000000000000000000000000000000000000000..14f77c10549a1247f645191e241cd61a23145af5 --- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/common/interfaces/IFeeHandler.sol -@@ -0,0 +1,39 @@ ++++ CELO/packages/contracts-bedrock/src/celo/mento/interfaces/IReserve.sol +@@ -0,0 +1,32 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity ^0.8.15; + -+import "../FixidityLib.sol"; ++interface IReserve { ++ function setTobinTaxStalenessThreshold(uint256) external; + -+interface IFeeHandler { -+ // sets the portion of the fee that should be burned. -+ function setBurnFraction(uint256 fraction) external; ++ function addToken(address) external returns (bool); + -+ function addToken(address tokenAddress, address handlerAddress) external; -+ function removeToken(address tokenAddress) external; ++ function removeToken(address, uint256) external returns (bool); + -+ function setHandler(address tokenAddress, address handlerAddress) external; ++ function transferGold(address payable, uint256) external returns (bool); + -+ // marks token to be handled in "handleAll()) -+ function activateToken(address tokenAddress) external; -+ function deactivateToken(address tokenAddress) external; ++ function transferExchangeGold(address payable, uint256) external returns (bool); + -+ function sell(address tokenAddress) external; ++ function getReserveGoldBalance() external view returns (uint256); + -+ // calls exchange(tokenAddress), and distribute(tokenAddress) -+ function handle(address tokenAddress) external; ++ function getUnfrozenReserveGoldBalance() external view returns (uint256); + -+ // main entrypoint for a burn, iterates over token and calles handle -+ function handleAll() external; ++ function getOrComputeTobinTax() external returns (uint256, uint256); + -+ // Sends the balance of token at tokenAddress to feesBeneficiary, -+ // according to the entry tokensToDistribute[tokenAddress] -+ function distribute(address tokenAddress) external; ++ function getTokens() external view returns (address[] memory); + -+ // burns the balance of Celo in the contract minus the entry of tokensToDistribute[CeloAddress] -+ function burnCelo() external; ++ function getReserveRatio() external view returns (uint256); + -+ // calls distribute for all the nonCeloTokens -+ function distributeAll() external; ++ function addExchangeSpender(address) external; + -+ // in case some funds need to be returned or moved to another contract -+ function transfer(address token, address recipient, uint256 value) external returns (bool); ++ function removeExchangeSpender(address, uint256) external; ++ ++ function addSpender(address) external; ++ ++ function removeSpender(address) external; +}
@@ -29987,9 +131876,9 @@
@@ -30004,7 +131893,7 @@
@@ -30014,35 +131903,41 @@
-
+17
+
+23
-0
-
diff --git OP/packages/contracts-bedrock/src/celo/common/interfaces/IFeeHandlerSeller.sol CELO/packages/contracts-bedrock/src/celo/common/interfaces/IFeeHandlerSeller.sol +
diff --git OP/packages/contracts-bedrock/src/celo/mento/interfaces/IStableToken.sol CELO/packages/contracts-bedrock/src/celo/mento/interfaces/IStableToken.sol new file mode 100644 -index 0000000000000000000000000000000000000000..c3a9df0ee324a675f00c5b49f9f615a42427e815 +index 0000000000000000000000000000000000000000..c0b681dfb8aee25aa686d5484adea6f3f6f79179 --- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/common/interfaces/IFeeHandlerSeller.sol -@@ -0,0 +1,17 @@ ++++ CELO/packages/contracts-bedrock/src/celo/mento/interfaces/IStableToken.sol +@@ -0,0 +1,23 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity ^0.8.15; + -+import "../FixidityLib.sol"; ++/** ++ * @title This interface describes the functions specific to Celo Stable Tokens, and in the ++ * absence of interface inheritance is intended as a companion to IERC20.sol and ICeloToken.sol. ++ */ ++interface IStableToken { ++ function mint(address, uint256) external returns (bool); + -+interface IFeeHandlerSeller { -+ function sell( -+ address sellTokenAddress, -+ address buyTokenAddress, -+ uint256 amount, -+ uint256 minAmount -+ ) -+ external -+ returns (uint256); -+ // in case some funds need to be returned or moved to another contract -+ function transfer(address token, uint256 amount, address to) external returns (bool); ++ function burn(uint256) external returns (bool); ++ ++ function setInflationParameters(uint256, uint256) external; ++ ++ function valueToUnits(uint256) external view returns (uint256); ++ ++ function unitsToValue(uint256) external view returns (uint256); ++ ++ function getInflationParameters() external view returns (uint256, uint256, uint256, uint256); ++ ++ // NOTE: duplicated with IERC20.sol, remove once interface inheritance is supported. ++ function balanceOf(address) external view returns (uint256); +}
@@ -30050,9 +131945,9 @@
@@ -30067,7 +131962,7 @@
@@ -30077,283 +131972,482 @@
-
+267
+
+466
-0
-
diff --git OP/packages/contracts-bedrock/src/celo/common/linkedlists/AddressSortedLinkedList.sol CELO/packages/contracts-bedrock/src/celo/common/linkedlists/AddressSortedLinkedList.sol +
diff --git OP/packages/contracts-bedrock/src/celo/stability/SortedOracles.sol CELO/packages/contracts-bedrock/src/celo/stability/SortedOracles.sol new file mode 100644 -index 0000000000000000000000000000000000000000..38ae7359e0e069a46e616d774be857852d3a98a0 +index 0000000000000000000000000000000000000000..d2209dac5d2c8de4df0d0a1eb0ae0ec3f0e4422b --- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/common/linkedlists/AddressSortedLinkedList.sol -@@ -0,0 +1,267 @@ -+// SPDX-License-Identifier: MIT ++++ CELO/packages/contracts-bedrock/src/celo/stability/SortedOracles.sol +@@ -0,0 +1,466 @@ ++// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity ^0.8.15; + -+import "@openzeppelin/contracts/utils/math/Math.sol"; ++import "../../../lib/openzeppelin-contracts/contracts/access/Ownable.sol"; ++import "../../../lib/openzeppelin-contracts/contracts/utils/math/SafeMath.sol"; + -+import "./SortedLinkedList.sol"; ++import "./interfaces/ISortedOracles.sol"; ++import "../common/interfaces/ICeloVersionedContract.sol"; ++import "./interfaces/IBreakerBox.sol"; ++ ++import "../common/FixidityLib.sol"; ++import "../common/Initializable.sol"; ++import "../common/linkedlists/AddressSortedLinkedListWithMedian.sol"; ++import "../common/linkedlists/SortedLinkedListWithMedian.sol"; ++import "./interfaces/IOracle.sol"; + +/** -+ * @title Maintains a sorted list of unsigned ints keyed by address. ++ * @title SortedOracles ++ * ++ * @notice This contract stores a collection of exchange rates with CELO ++ * expressed in units of other assets. The most recent exchange rates ++ * are gathered off-chain by oracles, who then use the `report` function to ++ * submit the rates to this contract. Before submitting a rate report, an ++ * oracle's address must be added to the `isOracle` mapping for a specific ++ * rateFeedId, with the flag set to true. While submitting a report requires ++ * an address to be added to the mapping, no additional permissions are needed ++ * to read the reports, the calculated median rate, or the list of oracles. ++ * ++ * @dev A unique rateFeedId identifies each exchange rate. In the initial implementation ++ * of this contract, the rateFeedId was set as the address of the stable ++ * asset contract that used the rate. However, this implementation has since ++ * been updated, and the rateFeedId block.timestamp also refers to an address derived from the ++ * concatenation other asset symbols. This change enables the contract to store multiple exchange rates for a ++ * single token. As a result of this change, there may be instances ++ * where the term "token" is used in the contract code. These useages of the term ++ * "token" are actually referring to the rateFeedId. ++ * + */ -+library AddressSortedLinkedList { -+ using SortedLinkedList for SortedLinkedList.List; ++contract SortedOracles is ISortedOracles, IOracle, ICeloVersionedContract, Ownable, Initializable { ++ using SafeMath for uint256; ++ using AddressSortedLinkedListWithMedian for SortedLinkedListWithMedian.List; ++ using FixidityLib for FixidityLib.Fraction; ++ ++ struct EquivalentToken { ++ address token; ++ } ++ ++ uint256 private constant FIXED1_UINT = 1e24; ++ ++ // Maps a rateFeedID to a sorted list of report values. ++ mapping(address => SortedLinkedListWithMedian.List) private rates; ++ // Maps a rateFeedID to a sorted list of report timestamps. ++ mapping(address => SortedLinkedListWithMedian.List) private timestamps; ++ mapping(address => mapping(address => bool)) public isOracle; ++ mapping(address => address[]) public oracles; ++ ++ // `reportExpirySeconds` is the fallback value used to determine reporting ++ // frequency. Initially it was the _only_ value but we later introduced ++ // the per token mapping in `tokenReportExpirySeconds`. If a token ++ // doesn't have a value in the mapping (i.e. it's 0), the fallback is used. ++ // See: #getTokenReportExpirySeconds ++ uint256 public reportExpirySeconds; ++ // Maps a rateFeedId to its report expiry time in seconds. ++ mapping(address => uint256) public tokenReportExpirySeconds; ++ ++ IBreakerBox public breakerBox; ++ // Maps a token address to its equivalent token address. ++ // Original token will return the median value same as the value of equivalent token. ++ mapping(address => EquivalentToken) public equivalentTokens; ++ ++ event OracleAdded(address indexed token, address indexed oracleAddress); ++ event OracleRemoved(address indexed token, address indexed oracleAddress); ++ event OracleReported(address indexed token, address indexed oracle, uint256 timestamp, uint256 value); ++ event OracleReportRemoved(address indexed token, address indexed oracle); ++ event MedianUpdated(address indexed token, uint256 value); ++ event ReportExpirySet(uint256 reportExpiry); ++ event TokenReportExpirySet(address token, uint256 reportExpiry); ++ event BreakerBoxUpdated(address indexed newBreakerBox); ++ event EquivalentTokenSet(address indexed token, address indexed equivalentToken); ++ ++ modifier onlyOracle(address token) { ++ require(isOracle[token][msg.sender], "sender was not an oracle for token addr"); ++ _; ++ } + + /** -+ * @notice Inserts an element into a doubly linked list. -+ * @param list A storage pointer to the underlying list. -+ * @param key The key of the element to insert. -+ * @param value The element value. -+ * @param lesserKey The key of the element less than the element to insert. -+ * @param greaterKey The key of the element greater than the element to insert. ++ * @notice Sets initialized == true on implementation contracts ++ * @param test Set to true to skip implementation initialization + */ -+ function insert( -+ SortedLinkedList.List storage list, -+ address key, -+ uint256 value, -+ address lesserKey, -+ address greaterKey -+ ) -+ public ++ constructor(bool test) Initializable(test) { } ++ ++ /** ++ * @notice Used in place of the constructor to allow the contract to be upgradable via proxy. ++ * @param _reportExpirySeconds The number of seconds before a report is considered expired. ++ */ ++ function initialize(uint256 _reportExpirySeconds) external initializer { ++ _transferOwnership(msg.sender); ++ setReportExpiry(_reportExpirySeconds); ++ } ++ ++ /** ++ * @notice Sets the report expiry parameter for a rateFeedId. ++ * @param _token The token for which the report expiry is being set. ++ * @param _reportExpirySeconds The number of seconds before a report is considered expired. ++ */ ++ function setTokenReportExpiry(address _token, uint256 _reportExpirySeconds) external onlyOwner { ++ require(_reportExpirySeconds > 0, "report expiry seconds must be > 0"); ++ require(_reportExpirySeconds != tokenReportExpirySeconds[_token], "token reportExpirySeconds hasn't changed"); ++ tokenReportExpirySeconds[_token] = _reportExpirySeconds; ++ emit TokenReportExpirySet(_token, _reportExpirySeconds); ++ } ++ ++ /** ++ * @notice Adds a new Oracle for a specified rate feed. ++ * @param token The token for which the specified oracle is to be added. ++ * @param oracleAddress The address of the oracle. ++ */ ++ function addOracle(address token, address oracleAddress) external onlyOwner { ++ // solhint-disable-next-line reason-string ++ require( ++ token != address(0) && oracleAddress != address(0) && !isOracle[token][oracleAddress], ++ "token addr was null or oracle addr was null or oracle addr is already an oracle for token addr" ++ ); ++ isOracle[token][oracleAddress] = true; ++ oracles[token].push(oracleAddress); ++ emit OracleAdded(token, oracleAddress); ++ } ++ ++ /** ++ * @notice Removes an Oracle from a specified rate feed. ++ * @param token The token from which the specified oracle is to be removed. ++ * @param oracleAddress The address of the oracle. ++ * @param index The index of `oracleAddress` in the list of oracles. ++ */ ++ function removeOracle(address token, address oracleAddress, uint256 index) external onlyOwner { ++ // solhint-disable-next-line reason-string ++ require( ++ token != address(0) && oracleAddress != address(0) && oracles[token].length > index ++ && oracles[token][index] == oracleAddress, ++ "token addr null or oracle addr null or index of token oracle not mapped to oracle addr" ++ ); ++ isOracle[token][oracleAddress] = false; ++ oracles[token][index] = oracles[token][oracles[token].length.sub(1)]; ++ oracles[token].pop(); ++ if (reportExists(token, oracleAddress)) { ++ removeReport(token, oracleAddress); ++ } ++ emit OracleRemoved(token, oracleAddress); ++ } ++ ++ /** ++ * @notice Removes a report that is expired. ++ * @param token The token for which the expired report is to be removed. ++ * @param n The number of expired reports to remove, at most (deterministic upper gas bound). ++ */ ++ function removeExpiredReports(address token, uint256 n) external { ++ require( ++ token != address(0) && n < timestamps[token].getNumElements(), ++ "token addr null or trying to remove too many reports" ++ ); ++ for (uint256 i = 0; i < n; i = i.add(1)) { ++ (bool isExpired, address oldestAddress) = isOldestReportExpired(token); ++ if (isExpired) { ++ removeReport(token, oldestAddress); ++ } else { ++ break; ++ } ++ } ++ } ++ ++ /** ++ * @notice Sets the equivalent token for a token. ++ * @param token The address of the token. ++ * @param equivalentToken The address of the equivalent token. ++ */ ++ function setEquivalentToken(address token, address equivalentToken) external onlyOwner { ++ require(token != address(0), "token address cannot be 0"); ++ require(equivalentToken != address(0), "equivalentToken address cannot be 0"); ++ equivalentTokens[token] = EquivalentToken(equivalentToken); ++ emit EquivalentTokenSet(token, equivalentToken); ++ } ++ ++ /** ++ * @notice Sets the equivalent token for a token. ++ * @param token The address of the token. ++ */ ++ function deleteEquivalentToken(address token) external onlyOwner { ++ require(token != address(0), "token address cannot be 0"); ++ delete equivalentTokens[token]; ++ emit EquivalentTokenSet(token, address(0)); ++ } ++ ++ /** ++ * @notice Updates an oracle value and the median. ++ * @param token The token for which the rate is being reported. ++ * @param value The number of stable asset that equate to one unit of collateral asset, for the ++ * specified rateFeedId, expressed as a fixidity value. ++ * @param lesserKey The element which should be just left of the new oracle value. ++ * @param greaterKey The element which should be just right of the new oracle value. ++ * @dev Note that only one of `lesserKey` or `greaterKey` needs to be correct to reduce friction. ++ */ ++ function report(address token, uint256 value, address lesserKey, address greaterKey) external onlyOracle(token) { ++ uint256 originalMedian = rates[token].getMedianValue(); ++ if (rates[token].contains(msg.sender)) { ++ rates[token].update(msg.sender, value, lesserKey, greaterKey); ++ ++ // Rather than update the timestamp, we remove it and re-add it at the ++ // head of the list later. The reason for this is that we need to handle ++ // a few different cases: ++ // 1. This oracle is the only one to report so far. lesserKey = address(0) ++ // 2. Other oracles have reported since this one's last report. lesserKey = getHead() ++ // 3. Other oracles have reported, but the most recent is this one. ++ // lesserKey = key immediately after getHead() ++ // ++ // However, if we just remove this timestamp, timestamps[token].getHead() ++ // does the right thing in all cases. ++ timestamps[token].remove(msg.sender); ++ } else { ++ rates[token].insert(msg.sender, value, lesserKey, greaterKey); ++ } ++ timestamps[token].insert( ++ msg.sender, ++ // solhint-disable-next-line not-rely-on-time ++ block.timestamp, ++ timestamps[token].getHead(), ++ address(0) ++ ); ++ emit OracleReported(token, msg.sender, block.timestamp, value); ++ uint256 newMedian = rates[token].getMedianValue(); ++ if (newMedian != originalMedian) { ++ emit MedianUpdated(token, newMedian); ++ } ++ ++ if (address(breakerBox) != address(0)) { ++ breakerBox.checkAndSetBreakers(token); ++ } ++ } ++ ++ /** ++ * @notice Gets the equivalent token for a token. ++ * @param token The address of the token. ++ * @return The address of the equivalent token. ++ */ ++ function getEquivalentToken(address token) external view returns (address) { ++ return (equivalentTokens[token].token); ++ } ++ ++ /** ++ * @notice Returns the median timestamp. ++ * @dev Does not take the equivalentTokens mapping into account. ++ * For that, the underlying token should be queried. ++ * @param token The token for which the median timestamp is being retrieved. ++ * @return uint256 The median report timestamp for the specified rateFeedId. ++ */ ++ function medianTimestamp(address token) external view returns (uint256) { ++ return timestamps[token].getMedianValue(); ++ } ++ ++ /** ++ * @notice Gets all elements from the doubly linked list. ++ * @dev Does not take the equivalentTokens mapping into account. ++ * For that, the underlying token should be queried. ++ * @param token The token for which the timestamps are being retrieved. ++ * @return keys Keys of nn unpacked list of elements from largest to smallest. ++ * @return values Values of an unpacked list of elements from largest to smallest. ++ * @return relations Relations of an unpacked list of elements from largest to smallest. ++ */ ++ function getTimestamps(address token) ++ external ++ view ++ returns (address[] memory, uint256[] memory, SortedLinkedListWithMedian.MedianRelation[] memory) + { -+ list.insert(toBytes(key), value, toBytes(lesserKey), toBytes(greaterKey)); ++ return timestamps[token].getElements(); + } + + /** -+ * @notice Removes an element from the doubly linked list. -+ * @param list A storage pointer to the underlying list. -+ * @param key The key of the element to remove. ++ * @notice Returns the list of oracles for a speficied rateFeedId. ++ * @dev Does not take the equivalentTokens mapping into account. ++ * For that, the underlying token should be queried. ++ * @param token The token for which the oracles are being retrieved. ++ * @return address[] A list of oracles for the given rateFeedId. + */ -+ function remove(SortedLinkedList.List storage list, address key) public { -+ list.remove(toBytes(key)); ++ function getOracles(address token) external view returns (address[] memory) { ++ return oracles[token]; + } + + /** -+ * @notice Updates an element in the list. -+ * @param list A storage pointer to the underlying list. -+ * @param key The element key. -+ * @param value The element value. -+ * @param lesserKey The key of the element will be just left of `key` after the update. -+ * @param greaterKey The key of the element will be just right of `key` after the update. -+ * @dev Note that only one of "lesserKey" or "greaterKey" needs to be correct to reduce friction. ++ * @notice Gets all elements from the doubly linked list. ++ * @dev Does not take the equivalentTokens mapping into account. ++ * For that, the underlying token should be queried. ++ * @param token The token for which the rates are being retrieved. ++ * @return keys Keys of an unpacked list of elements from largest to smallest. ++ * @return values Values of an unpacked list of elements from largest to smallest. ++ * @return relations Relations of an unpacked list of elements from largest to smallest. + */ -+ function update( -+ SortedLinkedList.List storage list, -+ address key, -+ uint256 value, -+ address lesserKey, -+ address greaterKey -+ ) -+ public ++ function getRates(address token) ++ external ++ view ++ returns (address[] memory, uint256[] memory, SortedLinkedListWithMedian.MedianRelation[] memory) + { -+ list.update(toBytes(key), value, toBytes(lesserKey), toBytes(greaterKey)); ++ return rates[token].getElements(); + } + + /** -+ * @notice Returns whether or not a particular key is present in the sorted list. -+ * @param list A storage pointer to the underlying list. -+ * @param key The element key. -+ * @return Whether or not the key is in the sorted list. ++ * @notice Returns the exchange rate for a specified token. ++ * @param token The token for which the exchange rate is being retrieved. ++ * @return numerator uint256 The exchange rate for the specified token. ++ * @return denominator uint256 The denominator for the exchange rate. + */ -+ function contains(SortedLinkedList.List storage list, address key) public view returns (bool) { -+ return list.contains(toBytes(key)); ++ function getExchangeRate(address token) external view returns (uint256 numerator, uint256 denominator) { ++ (numerator, denominator) = medianRate(token); + } + + /** -+ * @notice Returns the value for a particular key in the sorted list. -+ * @param list A storage pointer to the underlying list. -+ * @param key The element key. -+ * @return The element value. ++ * @notice Returns the storage, major, minor, and patch version of the contract. ++ * @return Storage version of the contract. ++ * @return Major version of the contract. ++ * @return Minor version of the contract. ++ * @return Patch version of the contract. + */ -+ function getValue(SortedLinkedList.List storage list, address key) public view returns (uint256) { -+ return list.getValue(toBytes(key)); ++ function getVersionNumber() external pure returns (uint256, uint256, uint256, uint256) { ++ return (1, 1, 4, 0); + } + + /** -+ * @notice Gets all elements from the doubly linked list. -+ * @return Array of all keys in the list. -+ * @return Values corresponding to keys, which will be ordered largest to smallest. ++ * @notice Sets the report expiry parameter. ++ * @param _reportExpirySeconds The number of seconds before a report is considered expired. + */ -+ function getElements(SortedLinkedList.List storage list) public view returns (address[] memory, uint256[] memory) { -+ bytes32[] memory byteKeys = list.getKeys(); -+ address[] memory keys = new address[](byteKeys.length); -+ uint256[] memory values = new uint256[](byteKeys.length); -+ for (uint256 i = 0; i < byteKeys.length; i = i + 1) { -+ keys[i] = toAddress(byteKeys[i]); -+ values[i] = list.values[byteKeys[i]]; -+ } -+ return (keys, values); ++ function setReportExpiry(uint256 _reportExpirySeconds) public onlyOwner { ++ require(_reportExpirySeconds > 0, "report expiry seconds must be > 0"); ++ require(_reportExpirySeconds != reportExpirySeconds, "reportExpirySeconds hasn't changed"); ++ reportExpirySeconds = _reportExpirySeconds; ++ emit ReportExpirySet(_reportExpirySeconds); + } + + /** -+ * @notice Returns the minimum of `max` and the number of elements in the list > threshold. -+ * @param list A storage pointer to the underlying list. -+ * @param threshold The number that the element must exceed to be included. -+ * @param max The maximum number returned by this function. -+ * @return The minimum of `max` and the number of elements in the list > threshold. ++ * @notice Sets the address of the BreakerBox. ++ * @param newBreakerBox The new BreakerBox address. + */ -+ function numElementsGreaterThan( -+ SortedLinkedList.List storage list, -+ uint256 threshold, -+ uint256 max -+ ) -+ public -+ view -+ returns (uint256) -+ { -+ uint256 revisedMax = Math.min(max, list.list.numElements); -+ bytes32 key = list.list.head; -+ for (uint256 i = 0; i < revisedMax; i = i + 1) { -+ if (list.getValue(key) < threshold) { -+ return i; -+ } -+ key = list.list.elements[key].previousKey; -+ } -+ return revisedMax; ++ function setBreakerBox(IBreakerBox newBreakerBox) public onlyOwner { ++ require(address(newBreakerBox) != address(0), "BreakerBox address must be set"); ++ breakerBox = newBreakerBox; ++ emit BreakerBoxUpdated(address(newBreakerBox)); + } + + /** -+ * @notice Returns the N greatest elements of the list. -+ * @param list A storage pointer to the underlying list. -+ * @param n The number of elements to return. -+ * @return The keys of the greatest elements. ++ * @notice Returns the median of the currently stored rates for a specified rateFeedId. ++ * @dev Please note that this function respects the equivalentToken mapping, and so may ++ * return the median identified as an equivalent to the supplied rateFeedId. ++ * @param token The token for which the median value is being retrieved. ++ * @return uint256 The median exchange rate for rateFeedId (fixidity). ++ * @return uint256 denominator + */ -+ function headN(SortedLinkedList.List storage list, uint256 n) public view returns (address[] memory) { -+ bytes32[] memory byteKeys = list.headN(n); -+ address[] memory keys = new address[](n); -+ for (uint256 i = 0; i < n; i = i + 1) { -+ keys[i] = toAddress(byteKeys[i]); ++ function medianRate(address token) public view returns (uint256, uint256) { ++ EquivalentToken storage equivalentToken = equivalentTokens[token]; ++ if (equivalentToken.token != address(0)) { ++ (uint256 equivalentMedianRate, uint256 denominator) = ++ medianRateWithoutEquivalentMapping(equivalentToken.token); ++ return (equivalentMedianRate, denominator); + } -+ return keys; ++ ++ return medianRateWithoutEquivalentMapping(token); + } + + /** -+ * @notice Gets all element keys from the doubly linked list. -+ * @param list A storage pointer to the underlying list. -+ * @return All element keys from head to tail. ++ * @notice Returns the number of rates that are currently stored for a specifed rateFeedId. ++ * @dev Does not take the equivalentTokens mapping into account. ++ * For that, the underlying token should be queried. ++ * @param token The token for which the number of rates is being retrieved. ++ * @return uint256 The number of reported oracle rates stored for the given rateFeedId. + */ -+ function getKeys(SortedLinkedList.List storage list) public view returns (address[] memory) { -+ return headN(list, list.list.numElements); ++ function numRates(address token) public view returns (uint256) { ++ return rates[token].getNumElements(); + } + + /** -+ * @notice Returns the number of elements in the list. -+ * @param list A storage pointer to the underlying list. -+ * @return The number of elements in the list. ++ * @notice Check if last report is expired. ++ * @param token The token for which the expired report is to be checked. ++ * @return bool A bool indicating if the last report is expired. ++ * @return address Oracle address of the last report. + */ -+ function getNumElements(SortedLinkedList.List storage list) public view returns (uint256) { -+ return list.list.numElements; ++ function isOldestReportExpired(address token) public view returns (bool, address) { ++ // solhint-disable-next-line reason-string ++ require(token != address(0)); ++ address oldest = timestamps[token].getTail(); ++ uint256 timestamp = timestamps[token].getValue(oldest); ++ // solhint-disable-next-line not-rely-on-time ++ if (block.timestamp.sub(timestamp) >= getTokenReportExpirySeconds(token)) { ++ return (true, oldest); ++ } ++ return (false, oldest); + } + + /** -+ * @notice Returns the key of the first element in the list. -+ * @param list A storage pointer to the underlying list. -+ * @return The key of the first element in the list. ++ * @notice Returns the median of the currently stored rates for a specified rateFeedId. ++ * @dev Does not take the equivalentTokens mapping into account. ++ * @param token The token for which the median value is being retrieved. ++ * @return uint256 The median exchange rate for rateFeedId (fixidity). ++ * @return uint256 denominator + */ -+ function getHead(SortedLinkedList.List storage list) public view returns (address) { -+ return toAddress(list.list.head); ++ function medianRateWithoutEquivalentMapping(address token) public view returns (uint256, uint256) { ++ return (rates[token].getMedianValue(), numRates(token) == 0 ? 0 : FIXED1_UINT); + } + + /** -+ * @notice Returns the key of the last element in the list. -+ * @param list A storage pointer to the underlying list. -+ * @return The key of the last element in the list. ++ * @notice Returns the number of timestamps. ++ * @dev Does not take the equivalentTokens mapping into account. ++ * For that, the underlying token should be queried. ++ * @param token The token for which the number of timestamps is being retrieved. ++ * @return uint256 The number of oracle report timestamps for the specified rateFeedId. + */ -+ function getTail(SortedLinkedList.List storage list) public view returns (address) { -+ return toAddress(list.list.tail); ++ function numTimestamps(address token) public view returns (uint256) { ++ return timestamps[token].getNumElements(); + } + + /** -+ * @notice Gets lesser and greater for address that has increased it's value. -+ * @param list A storage pointer to the underlying list. -+ * @param group The original address. -+ * @param newValue New value that has to be bigger or equal than the previous one. -+ * @param loopLimit The max limit of loops that will be executed. ++ * @notice Returns the expiry for specified rateFeedId if it exists, if not the default is returned. ++ * @dev Does not take the equivalentTokens mapping into account. ++ * For that, the underlying token should be queried. ++ * @param token The token for which the report expiry is being retrieved. ++ * @return The report expiry in seconds. + */ -+ function getLesserAndGreaterOfAddressThatIncreasedValue( -+ SortedLinkedList.List storage list, -+ address group, -+ uint256 newValue, -+ uint256 loopLimit -+ ) -+ public -+ view -+ returns (address previous, address next) -+ { -+ (, previous, next) = get(list, group); -+ -+ while (next != address(0) && loopLimit != 0 && newValue > getValue(list, next)) { -+ previous = next; -+ (,, next) = get(list, previous); -+ loopLimit--; ++ function getTokenReportExpirySeconds(address token) public view returns (uint256) { ++ if (tokenReportExpirySeconds[token] == 0) { ++ return reportExpirySeconds; + } + -+ if (loopLimit == 0) { -+ return (address(0), address(0)); -+ } ++ return tokenReportExpirySeconds[token]; + } + + /** -+ * @notice Gets lesser and greater for address that has decreased it's value. -+ * @param list A storage pointer to the underlying list. -+ * @param group The original address. -+ * @param newValue New value that has to be smaller or equal than the previous one. -+ * @param loopLimit The max limit of loops that will be executed. ++ * @notice Checks if a report exists for a specified rateFeedId from a given oracle. ++ * @dev Does not take the equivalentTokens mapping into account. ++ * For that, the underlying token should be queried. ++ * @param token The token for which the report should be checked. ++ * @param oracle The oracle whose report should be checked. ++ * @return bool True if a report exists, false otherwise. + */ -+ function getLesserAndGreaterOfAddressThatDecreasedValue( -+ SortedLinkedList.List storage list, -+ address group, -+ uint256 newValue, -+ uint256 loopLimit -+ ) -+ public -+ view -+ returns (address previous, address next) -+ { -+ (, previous, next) = get(list, group); -+ while (previous != address(0) && loopLimit != 0 && newValue < getValue(list, previous)) { -+ next = previous; -+ (, previous,) = get(list, next); -+ loopLimit--; -+ } -+ if (loopLimit == 0) { -+ return (address(0), address(0)); -+ } -+ } -+ -+ function toBytes(address a) public pure returns (bytes32) { -+ return bytes32(uint256(uint160(a)) << 96); -+ } -+ -+ function toAddress(bytes32 b) public pure returns (address) { -+ return address(uint160(uint256(b) >> 96)); ++ function reportExists(address token, address oracle) internal view returns (bool) { ++ return rates[token].contains(oracle) && timestamps[token].contains(oracle); + } + + /** -+ * @notice Returns Element based on key. -+ * @param list A storage pointer to the underlying list. -+ * @param key The element key. -+ * @return exists Whether or not the key exists. -+ * @return previousKey Previous key. -+ * @return nextKey Next key. ++ * @notice Removes an oracle value and updates the median. ++ * @dev Does not take the equivalentTokens mapping into account. ++ * For that, the underlying token should be queried. ++ * @param token The token for which the oracle report should be removed. ++ * @param oracle The oracle whose value should be removed. ++ * @dev This can be used to delete elements for oracles that have been removed. ++ * However, a > 1 elements reports list should always be maintained + */ -+ function get( -+ SortedLinkedList.List storage list, -+ address key -+ ) -+ internal -+ view -+ returns (bool exists, address previousKey, address nextKey) -+ { -+ LinkedList.Element memory element = list.get(toBytes(key)); -+ exists = element.exists; -+ if (element.exists) { -+ previousKey = toAddress(element.previousKey); -+ nextKey = toAddress(element.nextKey); ++ function removeReport(address token, address oracle) private { ++ if (numTimestamps(token) == 1 && reportExists(token, oracle)) return; ++ uint256 originalMedian = rates[token].getMedianValue(); ++ rates[token].remove(oracle); ++ timestamps[token].remove(oracle); ++ emit OracleReportRemoved(token, oracle); ++ uint256 newMedian = rates[token].getMedianValue(); ++ if (newMedian != originalMedian) { ++ emit MedianUpdated(token, newMedian); ++ if (address(breakerBox) != address(0)) { ++ breakerBox.checkAndSetBreakers(token); ++ } + } + } +}
@@ -30363,9 +132457,9 @@
@@ -30390,178 +132484,158 @@
-
+160
+
+140
-0
-
diff --git OP/packages/contracts-bedrock/src/celo/common/linkedlists/AddressSortedLinkedListWithMedian.sol CELO/packages/contracts-bedrock/src/celo/common/linkedlists/AddressSortedLinkedListWithMedian.sol +
diff --git OP/packages/contracts-bedrock/src/celo/stability/interfaces/IBreakerBox.sol CELO/packages/contracts-bedrock/src/celo/stability/interfaces/IBreakerBox.sol new file mode 100644 -index 0000000000000000000000000000000000000000..2ddf56612244e868dd6f3ba0aede4103c7569441 +index 0000000000000000000000000000000000000000..26430da7a3bea5db65b04502a7057a0606b44d7d --- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/common/linkedlists/AddressSortedLinkedListWithMedian.sol -@@ -0,0 +1,160 @@ ++++ CELO/packages/contracts-bedrock/src/celo/stability/interfaces/IBreakerBox.sol +@@ -0,0 +1,140 @@ +// SPDX-License-Identifier: MIT -+pragma solidity ^0.8.15; -+ -+import "./SortedLinkedListWithMedian.sol"; ++pragma solidity >=0.5.13 <0.9.0; + +/** -+ * @title Maintains a sorted list of unsigned ints keyed by address. ++ * @title Breaker Box Interface ++ * @notice Defines the basic interface for the Breaker Box + */ -+library AddressSortedLinkedListWithMedian { -+ using SortedLinkedListWithMedian for SortedLinkedListWithMedian.List; -+ -+ function toBytes(address a) public pure returns (bytes32) { -+ return bytes32(uint256(uint160(a)) << 96); ++interface IBreakerBox { ++ /** ++ * @dev Used to keep track of the status of a breaker for a specific rate feed. ++ * ++ * - TradingMode: Represents the trading mode the breaker is in for a rate feed. ++ * This uses a bitmask approach, meaning each bit represents a ++ * different trading mode. The final trading mode of the rate feed ++ * is obtained by applying a logical OR operation to the TradingMode ++ * of all breakers associated with that rate feed. This allows multiple ++ * breakers to contribute to the final trading mode simultaneously. ++ * Possible values: ++ * 0: bidirectional trading. ++ * 1: inflow only. ++ * 2: outflow only. ++ * 3: trading halted. ++ * ++ * - LastUpdatedTime: Records the last time the breaker status was updated. This is ++ * used to manage cooldown periods before the breaker can be reset. ++ * ++ * - Enabled: Indicates whether the breaker is enabled for the associated rate feed. ++ */ ++ struct BreakerStatus { ++ uint8 tradingMode; ++ uint64 lastUpdatedTime; ++ bool enabled; + } + -+ function toAddress(bytes32 b) public pure returns (address) { -+ return address(uint160(uint256(b) >> 96)); -+ } ++ /** ++ * @notice Emitted when a new breaker is added to the breaker box. ++ * @param breaker The address of the breaker. ++ */ ++ event BreakerAdded(address indexed breaker); + + /** -+ * @notice Inserts an element into a doubly linked list. -+ * @param list A storage pointer to the underlying list. -+ * @param key The key of the element to insert. -+ * @param value The element value. -+ * @param lesserKey The key of the element less than the element to insert. -+ * @param greaterKey The key of the element greater than the element to insert. ++ * @notice Emitted when a breaker is removed from the breaker box. ++ * @param breaker The address of the breaker. + */ -+ function insert( -+ SortedLinkedListWithMedian.List storage list, -+ address key, -+ uint256 value, -+ address lesserKey, -+ address greaterKey -+ ) -+ public -+ { -+ list.insert(toBytes(key), value, toBytes(lesserKey), toBytes(greaterKey)); -+ } ++ event BreakerRemoved(address indexed breaker); + + /** -+ * @notice Removes an element from the doubly linked list. -+ * @param list A storage pointer to the underlying list. -+ * @param key The key of the element to remove. ++ * @notice Emitted when a breaker is tripped by a rate feed. ++ * @param breaker The address of the breaker. ++ * @param rateFeedID The address of the rate feed. + */ -+ function remove(SortedLinkedListWithMedian.List storage list, address key) public { -+ list.remove(toBytes(key)); -+ } ++ event BreakerTripped(address indexed breaker, address indexed rateFeedID); + + /** -+ * @notice Updates an element in the list. -+ * @param list A storage pointer to the underlying list. -+ * @param key The element key. -+ * @param value The element value. -+ * @param lesserKey The key of the element will be just left of `key` after the update. -+ * @param greaterKey The key of the element will be just right of `key` after the update. -+ * @dev Note that only one of "lesserKey" or "greaterKey" needs to be correct to reduce friction. ++ * @notice Emitted when a new rate feed is added to the breaker box. ++ * @param rateFeedID The address of the rate feed. + */ -+ function update( -+ SortedLinkedListWithMedian.List storage list, -+ address key, -+ uint256 value, -+ address lesserKey, -+ address greaterKey -+ ) -+ public -+ { -+ list.update(toBytes(key), value, toBytes(lesserKey), toBytes(greaterKey)); -+ } ++ event RateFeedAdded(address indexed rateFeedID); + + /** -+ * @notice Returns whether or not a particular key is present in the sorted list. -+ * @param list A storage pointer to the underlying list. -+ * @param key The element key. -+ * @return Whether or not the key is in the sorted list. ++ * @notice Emitted when dependencies for a rate feed are set. ++ * @param rateFeedID The address of the rate feed. ++ * @param dependencies The addresses of the dependendent rate feeds. + */ -+ function contains(SortedLinkedListWithMedian.List storage list, address key) public view returns (bool) { -+ return list.contains(toBytes(key)); -+ } ++ event RateFeedDependenciesSet(address indexed rateFeedID, address[] indexed dependencies); + + /** -+ * @notice Returns the value for a particular key in the sorted list. -+ * @param list A storage pointer to the underlying list. -+ * @param key The element key. -+ * @return The element value. ++ * @notice Emitted when a rate feed is removed from the breaker box. ++ * @param rateFeedID The address of the rate feed. + */ -+ function getValue(SortedLinkedListWithMedian.List storage list, address key) public view returns (uint256) { -+ return list.getValue(toBytes(key)); -+ } ++ event RateFeedRemoved(address indexed rateFeedID); + + /** -+ * @notice Returns the median value of the sorted list. -+ * @param list A storage pointer to the underlying list. -+ * @return The median value. ++ * @notice Emitted when the trading mode for a rate feed is updated ++ * @param rateFeedID The address of the rate feed. ++ * @param tradingMode The new trading mode. + */ -+ function getMedianValue(SortedLinkedListWithMedian.List storage list) public view returns (uint256) { -+ return list.getValue(list.median); -+ } ++ event TradingModeUpdated(address indexed rateFeedID, uint256 tradingMode); + + /** -+ * @notice Returns the key of the first element in the list. -+ * @param list A storage pointer to the underlying list. -+ * @return The key of the first element in the list. ++ * @notice Emitted after a reset attempt is successful. ++ * @param rateFeedID The address of the rate feed. ++ * @param breaker The address of the breaker. + */ -+ function getHead(SortedLinkedListWithMedian.List storage list) external view returns (address) { -+ return toAddress(list.getHead()); -+ } ++ event ResetSuccessful(address indexed rateFeedID, address indexed breaker); + + /** -+ * @notice Returns the key of the median element in the list. -+ * @param list A storage pointer to the underlying list. -+ * @return The key of the median element in the list. ++ * @notice Emitted after a reset attempt fails when the ++ * rate feed fails the breakers reset criteria. ++ * @param rateFeedID The address of the rate feed. ++ * @param breaker The address of the breaker. + */ -+ function getMedian(SortedLinkedListWithMedian.List storage list) external view returns (address) { -+ return toAddress(list.getMedian()); -+ } ++ event ResetAttemptCriteriaFail(address indexed rateFeedID, address indexed breaker); + + /** -+ * @notice Returns the key of the last element in the list. -+ * @param list A storage pointer to the underlying list. -+ * @return The key of the last element in the list. ++ * @notice Emitted after a reset attempt fails when cooldown time has not elapsed. ++ * @param rateFeedID The address of the rate feed. ++ * @param breaker The address of the breaker. + */ -+ function getTail(SortedLinkedListWithMedian.List storage list) external view returns (address) { -+ return toAddress(list.getTail()); -+ } ++ event ResetAttemptNotCool(address indexed rateFeedID, address indexed breaker); + + /** -+ * @notice Returns the number of elements in the list. -+ * @param list A storage pointer to the underlying list. -+ * @return The number of elements in the list. ++ * @notice Emitted when the sortedOracles address is updated. ++ * @param newSortedOracles The address of the new sortedOracles. + */ -+ function getNumElements(SortedLinkedListWithMedian.List storage list) external view returns (uint256) { -+ return list.getNumElements(); -+ } ++ event SortedOraclesUpdated(address indexed newSortedOracles); + + /** -+ * @notice Gets all elements from the doubly linked list. -+ * @param list A storage pointer to the underlying list. -+ * @return Array of all keys in the list. -+ * @return Values corresponding to keys, which will be ordered largest to smallest. -+ * @return Array of relations to median of corresponding list elements. ++ * @notice Emitted when the breaker is enabled or disabled for a rate feed. ++ * @param breaker The address of the breaker. ++ * @param rateFeedID The address of the rate feed. ++ * @param status Indicating the status. ++ */ ++ event BreakerStatusUpdated(address breaker, address rateFeedID, bool status); ++ ++ /** ++ * @notice Checks breakers for the rateFeedID and sets correct trading mode ++ * if any breakers are tripped or need to be reset. ++ * @param rateFeedID The address of the rate feed to run checks for. ++ */ ++ function checkAndSetBreakers(address rateFeedID) external; ++ ++ /** ++ * @notice Retrives an array of all breaker addresses. ++ */ ++ function getBreakers() external view returns (address[] memory); ++ ++ /** ++ * @notice Checks if a breaker with the specified address has been added to the breaker box. ++ * @param breaker The address of the breaker to check; ++ * @return A bool indicating whether or not the breaker has been added. ++ */ ++ function isBreaker(address breaker) external view returns (bool); ++ ++ /** ++ * @notice Gets the trading mode for the specified rateFeedID. ++ * @param rateFeedID The address of the rate feed to retrieve the trading mode for. + */ -+ function getElements(SortedLinkedListWithMedian.List storage list) -+ public -+ view -+ returns (address[] memory, uint256[] memory, SortedLinkedListWithMedian.MedianRelation[] memory) -+ { -+ bytes32[] memory byteKeys = list.getKeys(); -+ address[] memory keys = new address[](byteKeys.length); -+ uint256[] memory values = new uint256[](byteKeys.length); -+ // prettier-ignore -+ SortedLinkedListWithMedian.MedianRelation[] memory relations = -+ new SortedLinkedListWithMedian.MedianRelation[](keys.length); -+ for (uint256 i = 0; i < byteKeys.length; i++) { -+ keys[i] = toAddress(byteKeys[i]); -+ values[i] = list.getValue(byteKeys[i]); -+ relations[i] = list.relation[byteKeys[i]]; -+ } -+ return (keys, values, relations); -+ } ++ function getRateFeedTradingMode(address rateFeedID) external view returns (uint8 tradingMode); +}
@@ -30569,9 +132643,9 @@
@@ -30586,7 +132660,7 @@
@@ -30596,180 +132670,25 @@
-
+162
+
+7
-0
-
diff --git OP/packages/contracts-bedrock/src/celo/common/linkedlists/LinkedList.sol CELO/packages/contracts-bedrock/src/celo/common/linkedlists/LinkedList.sol +
diff --git OP/packages/contracts-bedrock/src/celo/stability/interfaces/IOracle.sol CELO/packages/contracts-bedrock/src/celo/stability/interfaces/IOracle.sol new file mode 100644 -index 0000000000000000000000000000000000000000..d04e8b7e027cbb3f8e665e07420b8ca16205d084 +index 0000000000000000000000000000000000000000..b3ae66a92756c915ede5a6c5b1f57387b2edc254 --- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/common/linkedlists/LinkedList.sol -@@ -0,0 +1,162 @@ ++++ CELO/packages/contracts-bedrock/src/celo/stability/interfaces/IOracle.sol +@@ -0,0 +1,7 @@ +// SPDX-License-Identifier: MIT -+pragma solidity ^0.8.15; -+ -+/** -+ * @title Maintains a doubly linked list keyed by bytes32. -+ * @dev Following the `next` pointers will lead you to the head, rather than the tail. -+ */ -+library LinkedList { -+ struct Element { -+ bytes32 previousKey; -+ bytes32 nextKey; -+ bool exists; -+ } -+ -+ struct List { -+ bytes32 head; -+ bytes32 tail; -+ uint256 numElements; -+ mapping(bytes32 => Element) elements; -+ } -+ -+ /** -+ * @notice Inserts an element into a doubly linked list. -+ * @param list A storage pointer to the underlying list. -+ * @param key The key of the element to insert. -+ * @param previousKey The key of the element that comes before the element to insert. -+ * @param nextKey The key of the element that comes after the element to insert. -+ */ -+ function insert(List storage list, bytes32 key, bytes32 previousKey, bytes32 nextKey) internal { -+ require(key != bytes32(0), "Key must be defined"); -+ require(!contains(list, key), "Can't insert an existing element"); -+ require(previousKey != key && nextKey != key, "Key cannot be the same as previousKey or nextKey"); -+ -+ Element storage element = list.elements[key]; -+ element.exists = true; -+ -+ if (list.numElements == 0) { -+ list.tail = key; -+ list.head = key; -+ } else { -+ require(previousKey != bytes32(0) || nextKey != bytes32(0), "Either previousKey or nextKey must be defined"); -+ -+ element.previousKey = previousKey; -+ element.nextKey = nextKey; -+ -+ if (previousKey != bytes32(0)) { -+ require(contains(list, previousKey), "If previousKey is defined, it must exist in the list"); -+ Element storage previousElement = list.elements[previousKey]; -+ require(previousElement.nextKey == nextKey, "previousKey must be adjacent to nextKey"); -+ previousElement.nextKey = key; -+ } else { -+ list.tail = key; -+ } -+ -+ if (nextKey != bytes32(0)) { -+ require(contains(list, nextKey), "If nextKey is defined, it must exist in the list"); -+ Element storage nextElement = list.elements[nextKey]; -+ require(nextElement.previousKey == previousKey, "previousKey must be adjacent to nextKey"); -+ nextElement.previousKey = key; -+ } else { -+ list.head = key; -+ } -+ } -+ -+ list.numElements = list.numElements + 1; -+ } -+ -+ /** -+ * @notice Inserts an element at the tail of the doubly linked list. -+ * @param list A storage pointer to the underlying list. -+ * @param key The key of the element to insert. -+ */ -+ function push(List storage list, bytes32 key) internal { -+ insert(list, key, bytes32(0), list.tail); -+ } -+ -+ /** -+ * @notice Removes an element from the doubly linked list. -+ * @param list A storage pointer to the underlying list. -+ * @param key The key of the element to remove. -+ */ -+ function remove(List storage list, bytes32 key) internal { -+ Element storage element = list.elements[key]; -+ require(key != bytes32(0) && contains(list, key), "key not in list"); -+ if (element.previousKey != bytes32(0)) { -+ Element storage previousElement = list.elements[element.previousKey]; -+ previousElement.nextKey = element.nextKey; -+ } else { -+ list.tail = element.nextKey; -+ } -+ -+ if (element.nextKey != bytes32(0)) { -+ Element storage nextElement = list.elements[element.nextKey]; -+ nextElement.previousKey = element.previousKey; -+ } else { -+ list.head = element.previousKey; -+ } -+ -+ delete list.elements[key]; -+ list.numElements = list.numElements - 1; -+ } -+ -+ /** -+ * @notice Updates an element in the list. -+ * @param list A storage pointer to the underlying list. -+ * @param key The element key. -+ * @param previousKey The key of the element that comes before the updated element. -+ * @param nextKey The key of the element that comes after the updated element. -+ */ -+ function update(List storage list, bytes32 key, bytes32 previousKey, bytes32 nextKey) internal { -+ require(key != bytes32(0) && key != previousKey && key != nextKey && contains(list, key), "key on in list"); -+ remove(list, key); -+ insert(list, key, previousKey, nextKey); -+ } -+ -+ /** -+ * @notice Returns whether or not a particular key is present in the sorted list. -+ * @param list A storage pointer to the underlying list. -+ * @param key The element key. -+ * @return Whether or not the key is in the sorted list. -+ */ -+ function contains(List storage list, bytes32 key) internal view returns (bool) { -+ return list.elements[key].exists; -+ } -+ -+ /** -+ * @notice Returns Element based on key. -+ * @param list A storage pointer to the underlying list. -+ * @param key The element key. -+ * @return Whether or not the key is in the sorted list. -+ */ -+ function get(List storage list, bytes32 key) internal view returns (Element memory) { -+ return list.elements[key]; -+ } -+ -+ /** -+ * @notice Returns the keys of the N elements at the head of the list. -+ * @param list A storage pointer to the underlying list. -+ * @param n The number of elements to return. -+ * @return The keys of the N elements at the head of the list. -+ * @dev Reverts if n is greater than the number of elements in the list. -+ */ -+ function headN(List storage list, uint256 n) internal view returns (bytes32[] memory) { -+ require(n <= list.numElements, "not enough elements"); -+ bytes32[] memory keys = new bytes32[](n); -+ bytes32 key = list.head; -+ for (uint256 i = 0; i < n; i = i + 1) { -+ keys[i] = key; -+ key = list.elements[key].previousKey; -+ } -+ return keys; -+ } ++pragma solidity >=0.5.13 <0.9.0; + -+ /** -+ * @notice Gets all element keys from the doubly linked list. -+ * @param list A storage pointer to the underlying list. -+ * @return All element keys from head to tail. -+ */ -+ function getKeys(List storage list) internal view returns (bytes32[] memory) { -+ return headN(list, list.numElements); -+ } ++/// Possibly not final version ++interface IOracle { ++ function getExchangeRate(address token) external view returns (uint256 numerator, uint256 denominator); +}
@@ -30777,9 +132696,9 @@
@@ -30794,7 +132713,7 @@
@@ -30804,235 +132723,497 @@
-
+218
+
+14
-0
-
diff --git OP/packages/contracts-bedrock/src/celo/common/linkedlists/SortedLinkedList.sol CELO/packages/contracts-bedrock/src/celo/common/linkedlists/SortedLinkedList.sol +
diff --git OP/packages/contracts-bedrock/src/celo/stability/interfaces/ISortedOracles.sol CELO/packages/contracts-bedrock/src/celo/stability/interfaces/ISortedOracles.sol new file mode 100644 -index 0000000000000000000000000000000000000000..9703cf565523deace3374d6a334ecfdc7c0589eb +index 0000000000000000000000000000000000000000..ecea4210cd40e4fb48a7a101b74625ff9746edcc --- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/common/linkedlists/SortedLinkedList.sol -@@ -0,0 +1,218 @@ ++++ CELO/packages/contracts-bedrock/src/celo/stability/interfaces/ISortedOracles.sol +@@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.15; + -+import "./LinkedList.sol"; ++interface ISortedOracles { ++ function addOracle(address, address) external; ++ function removeOracle(address, address, uint256) external; ++ function report(address, uint256, address, address) external; ++ function removeExpiredReports(address, uint256) external; ++ function isOldestReportExpired(address token) external view returns (bool, address); ++ function numRates(address) external view returns (uint256); ++ function medianRate(address) external view returns (uint256, uint256); ++ function numTimestamps(address) external view returns (uint256); ++ function medianTimestamp(address) external view returns (uint256); ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+420
+
-0
+ +
+ +
+
+
diff --git OP/packages/contracts-bedrock/src/celo/testing/FeeCurrency.sol CELO/packages/contracts-bedrock/src/celo/testing/FeeCurrency.sol +new file mode 100644 +index 0000000000000000000000000000000000000000..fd00f42c01bbb45a455790ec9e7cd3d181742319 +--- /dev/null ++++ CELO/packages/contracts-bedrock/src/celo/testing/FeeCurrency.sol +@@ -0,0 +1,420 @@ ++// SPDX-License-Identifier: MIT ++// Modified from OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/ERC20.sol) ++ ++pragma solidity ^0.8.0; ++ ++import "../../../lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; ++import "../../../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol"; ++import "../../../lib/openzeppelin-contracts/contracts/utils/Context.sol"; ++ ++import "../CalledByVm.sol"; + +/** -+ * @title Maintains a sorted list of unsigned ints keyed by bytes32. ++ * @dev Implementation of the {IERC20} interface + Celo debit/creditGasFees. ++ * ++ * This implementation is agnostic to the way tokens are created. This means ++ * that a supply mechanism has to be added in a derived contract using {_mint}. ++ * For a generic mechanism see {ERC20PresetMinterPauser}. ++ * ++ * TIP: For a detailed writeup see our guide ++ * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How ++ * to implement supply mechanisms]. ++ * ++ * We have followed general OpenZeppelin Contracts guidelines: functions revert ++ * instead returning `false` on failure. This behavior is nonetheless ++ * conventional and does not conflict with the expectations of ERC20 ++ * applications. ++ * ++ * Additionally, an {Approval} event is emitted on calls to {transferFrom}. ++ * This allows applications to reconstruct the allowance for all accounts just ++ * by listening to said events. Other implementations of the EIP may not emit ++ * these events, as it isn't required by the specification. ++ * ++ * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} ++ * functions have been added to mitigate the well-known issues around setting ++ * allowances. See {IERC20-approve}. + */ -+library SortedLinkedList { -+ using LinkedList for LinkedList.List; ++contract FeeCurrency is Context, IERC20, IERC20Metadata, CalledByVm { ++ mapping(address => uint256) private _balances; + -+ struct List { -+ LinkedList.List list; -+ mapping(bytes32 => uint256) values; ++ mapping(address => mapping(address => uint256)) private _allowances; ++ ++ uint256 private _totalSupply; ++ ++ string private _name; ++ string private _symbol; ++ ++ /** ++ * @dev Sets the values for {name} and {symbol}. ++ * ++ * The default value of {decimals} is 18. To select a different value for ++ * {decimals} you should overload it. ++ * ++ * All two of these values are immutable: they can only be set once during ++ * construction. ++ */ ++ constructor(string memory name_, string memory symbol_) { ++ _name = name_; ++ _symbol = symbol_; + } + + /** -+ * @notice Inserts an element into a doubly linked list. -+ * @param list A storage pointer to the underlying list. -+ * @param key The key of the element to insert. -+ * @param value The element value. -+ * @param lesserKey The key of the element less than the element to insert. -+ * @param greaterKey The key of the element greater than the element to insert. ++ * @dev Returns the name of the token. + */ -+ function insert(List storage list, bytes32 key, uint256 value, bytes32 lesserKey, bytes32 greaterKey) internal { -+ require(key != bytes32(0) && key != lesserKey && key != greaterKey && !contains(list, key), "invalid key"); -+ require( -+ (lesserKey != bytes32(0) || greaterKey != bytes32(0)) || list.list.numElements == 0, -+ "greater and lesser key zero" -+ ); -+ require(contains(list, lesserKey) || lesserKey == bytes32(0), "invalid lesser key"); -+ require(contains(list, greaterKey) || greaterKey == bytes32(0), "invalid greater key"); -+ (lesserKey, greaterKey) = getLesserAndGreater(list, value, lesserKey, greaterKey); -+ list.list.insert(key, lesserKey, greaterKey); -+ list.values[key] = value; ++ function name() public view virtual override returns (string memory) { ++ return _name; + } + + /** -+ * @notice Removes an element from the doubly linked list. -+ * @param list A storage pointer to the underlying list. -+ * @param key The key of the element to remove. ++ * @dev Returns the symbol of the token, usually a shorter version of the ++ * name. + */ -+ function remove(List storage list, bytes32 key) internal { -+ list.list.remove(key); -+ list.values[key] = 0; ++ function symbol() public view virtual override returns (string memory) { ++ return _symbol; + } + + /** -+ * @notice Updates an element in the list. -+ * @param list A storage pointer to the underlying list. -+ * @param key The element key. -+ * @param value The element value. -+ * @param lesserKey The key of the element will be just left of `key` after the update. -+ * @param greaterKey The key of the element will be just right of `key` after the update. -+ * @dev Note that only one of "lesserKey" or "greaterKey" needs to be correct to reduce friction. ++ * @dev Returns the number of decimals used to get its user representation. ++ * For example, if `decimals` equals `2`, a balance of `505` tokens should ++ * be displayed to a user as `5.05` (`505 / 10 ** 2`). ++ * ++ * Tokens usually opt for a value of 18, imitating the relationship between ++ * Ether and Wei. This is the value {ERC20} uses, unless this function is ++ * overridden; ++ * ++ * NOTE: This information is only used for _display_ purposes: it in ++ * no way affects any of the arithmetic of the contract, including ++ * {IERC20-balanceOf} and {IERC20-transfer}. + */ -+ function update(List storage list, bytes32 key, uint256 value, bytes32 lesserKey, bytes32 greaterKey) internal { -+ remove(list, key); -+ insert(list, key, value, lesserKey, greaterKey); ++ function decimals() public view virtual override returns (uint8) { ++ return 18; ++ } ++ ++ /** ++ * @dev See {IERC20-totalSupply}. ++ */ ++ function totalSupply() public view virtual override returns (uint256) { ++ return _totalSupply; ++ } ++ ++ /** ++ * @dev See {IERC20-balanceOf}. ++ */ ++ function balanceOf(address account) public view virtual override returns (uint256) { ++ return _balances[account]; ++ } ++ ++ /** ++ * @dev See {IERC20-transfer}. ++ * ++ * Requirements: ++ * ++ * - `to` cannot be the zero address. ++ * - the caller must have a balance of at least `amount`. ++ */ ++ function transfer(address to, uint256 amount) public virtual override returns (bool) { ++ address owner = _msgSender(); ++ _transfer(owner, to, amount); ++ return true; ++ } ++ ++ /** ++ * @dev See {IERC20-allowance}. ++ */ ++ function allowance(address owner, address spender) public view virtual override returns (uint256) { ++ return _allowances[owner][spender]; ++ } ++ ++ /** ++ * @dev See {IERC20-approve}. ++ * ++ * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on ++ * `transferFrom`. This is semantically equivalent to an infinite approval. ++ * ++ * Requirements: ++ * ++ * - `spender` cannot be the zero address. ++ */ ++ function approve(address spender, uint256 amount) public virtual override returns (bool) { ++ address owner = _msgSender(); ++ _approve(owner, spender, amount); ++ return true; ++ } ++ ++ /** ++ * @dev See {IERC20-transferFrom}. ++ * ++ * Emits an {Approval} event indicating the updated allowance. This is not ++ * required by the EIP. See the note at the beginning of {ERC20}. ++ * ++ * NOTE: Does not update the allowance if the current allowance ++ * is the maximum `uint256`. ++ * ++ * Requirements: ++ * ++ * - `from` and `to` cannot be the zero address. ++ * - `from` must have a balance of at least `amount`. ++ * - the caller must have allowance for ``from``'s tokens of at least ++ * `amount`. ++ */ ++ function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) { ++ address spender = _msgSender(); ++ _spendAllowance(from, spender, amount); ++ _transfer(from, to, amount); ++ return true; ++ } ++ ++ /** ++ * @dev Atomically increases the allowance granted to `spender` by the caller. ++ * ++ * This is an alternative to {approve} that can be used as a mitigation for ++ * problems described in {IERC20-approve}. ++ * ++ * Emits an {Approval} event indicating the updated allowance. ++ * ++ * Requirements: ++ * ++ * - `spender` cannot be the zero address. ++ */ ++ function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { ++ address owner = _msgSender(); ++ _approve(owner, spender, allowance(owner, spender) + addedValue); ++ return true; ++ } ++ ++ /** ++ * @dev Atomically decreases the allowance granted to `spender` by the caller. ++ * ++ * This is an alternative to {approve} that can be used as a mitigation for ++ * problems described in {IERC20-approve}. ++ * ++ * Emits an {Approval} event indicating the updated allowance. ++ * ++ * Requirements: ++ * ++ * - `spender` cannot be the zero address. ++ * - `spender` must have allowance for the caller of at least ++ * `subtractedValue`. ++ */ ++ function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { ++ address owner = _msgSender(); ++ uint256 currentAllowance = allowance(owner, spender); ++ require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); ++ unchecked { ++ _approve(owner, spender, currentAllowance - subtractedValue); ++ } ++ ++ return true; ++ } ++ ++ /** ++ * @dev Moves `amount` of tokens from `from` to `to`. ++ * ++ * This internal function is equivalent to {transfer}, and can be used to ++ * e.g. implement automatic token fees, slashing mechanisms, etc. ++ * ++ * Emits a {Transfer} event. ++ * ++ * Requirements: ++ * ++ * - `from` cannot be the zero address. ++ * - `to` cannot be the zero address. ++ * - `from` must have a balance of at least `amount`. ++ */ ++ function _transfer(address from, address to, uint256 amount) internal virtual { ++ require(from != address(0), "ERC20: transfer from the zero address"); ++ require(to != address(0), "ERC20: transfer to the zero address"); ++ ++ _beforeTokenTransfer(from, to, amount); ++ ++ uint256 fromBalance = _balances[from]; ++ require(fromBalance >= amount, "ERC20: transfer amount exceeds balance"); ++ unchecked { ++ _balances[from] = fromBalance - amount; ++ } ++ _balances[to] += amount; ++ ++ emit Transfer(from, to, amount); ++ ++ _afterTokenTransfer(from, to, amount); + } + + /** -+ * @notice Inserts an element at the tail of the doubly linked list. -+ * @param list A storage pointer to the underlying list. -+ * @param key The key of the element to insert. ++ * @dev Creates `amount` tokens and assigns them to `account`, increasing ++ * the total supply. ++ * ++ * Emits a {Transfer} event with `from` set to the zero address. ++ * ++ * Requirements: ++ * ++ * - `account` cannot be the zero address. + */ -+ function push(List storage list, bytes32 key) internal { -+ insert(list, key, 0, bytes32(0), list.list.tail); ++ function _mint(address account, uint256 amount) internal virtual { ++ require(account != address(0), "ERC20: mint to the zero address"); ++ ++ _beforeTokenTransfer(address(0), account, amount); ++ ++ _totalSupply += amount; ++ _balances[account] += amount; ++ emit Transfer(address(0), account, amount); ++ ++ _afterTokenTransfer(address(0), account, amount); + } + + /** -+ * @notice Removes N elements from the head of the list and returns their keys. -+ * @param list A storage pointer to the underlying list. -+ * @param n The number of elements to pop. -+ * @return The keys of the popped elements. ++ * @dev Destroys `amount` tokens from `account`, reducing the ++ * total supply. ++ * ++ * Emits a {Transfer} event with `to` set to the zero address. ++ * ++ * Requirements: ++ * ++ * - `account` cannot be the zero address. ++ * - `account` must have at least `amount` tokens. + */ -+ function popN(List storage list, uint256 n) internal returns (bytes32[] memory) { -+ require(n <= list.list.numElements, "not enough elements"); -+ bytes32[] memory keys = new bytes32[](n); -+ for (uint256 i = 0; i < n; i = i + 1) { -+ bytes32 key = list.list.head; -+ keys[i] = key; -+ remove(list, key); ++ function _burn(address account, uint256 amount) internal virtual { ++ require(account != address(0), "ERC20: burn from the zero address"); ++ ++ _beforeTokenTransfer(account, address(0), amount); ++ ++ uint256 accountBalance = _balances[account]; ++ require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); ++ unchecked { ++ _balances[account] = accountBalance - amount; + } -+ return keys; -+ } ++ _totalSupply -= amount; + -+ /** -+ * @notice Returns whether or not a particular key is present in the sorted list. -+ * @param list A storage pointer to the underlying list. -+ * @param key The element key. -+ * @return Whether or not the key is in the sorted list. -+ */ -+ function contains(List storage list, bytes32 key) internal view returns (bool) { -+ return list.list.contains(key); ++ emit Transfer(account, address(0), amount); ++ ++ _afterTokenTransfer(account, address(0), amount); + } + + /** -+ * @notice Returns Element based on key. -+ * @param list A storage pointer to the underlying list. -+ * @param key The element key. -+ * @return Whether or not the key is in the sorted list. ++ * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. ++ * ++ * This internal function is equivalent to `approve`, and can be used to ++ * e.g. set automatic allowances for certain subsystems, etc. ++ * ++ * Emits an {Approval} event. ++ * ++ * Requirements: ++ * ++ * - `owner` cannot be the zero address. ++ * - `spender` cannot be the zero address. + */ -+ function get(List storage list, bytes32 key) internal view returns (LinkedList.Element memory) { -+ return list.list.get(key); ++ function _approve(address owner, address spender, uint256 amount) internal virtual { ++ require(owner != address(0), "ERC20: approve from the zero address"); ++ require(spender != address(0), "ERC20: approve to the zero address"); ++ ++ _allowances[owner][spender] = amount; ++ emit Approval(owner, spender, amount); + } + + /** -+ * @notice Returns the value for a particular key in the sorted list. -+ * @param list A storage pointer to the underlying list. -+ * @param key The element key. -+ * @return The element value. ++ * @dev Updates `owner` s allowance for `spender` based on spent `amount`. ++ * ++ * Does not update the allowance amount in case of infinite allowance. ++ * Revert if not enough allowance is available. ++ * ++ * Might emit an {Approval} event. + */ -+ function getValue(List storage list, bytes32 key) internal view returns (uint256) { -+ return list.values[key]; ++ function _spendAllowance(address owner, address spender, uint256 amount) internal virtual { ++ uint256 currentAllowance = allowance(owner, spender); ++ if (currentAllowance != type(uint256).max) { ++ require(currentAllowance >= amount, "ERC20: insufficient allowance"); ++ unchecked { ++ _approve(owner, spender, currentAllowance - amount); ++ } ++ } + } + + /** -+ * @notice Gets all elements from the doubly linked list. -+ * @param list A storage pointer to the underlying list. -+ * @return Array of all keys in the list. -+ * @return Values corresponding to keys, which will be ordered largest to smallest. ++ * @dev Hook that is called before any transfer of tokens. This includes ++ * minting and burning. ++ * ++ * Calling conditions: ++ * ++ * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens ++ * will be transferred to `to`. ++ * - when `from` is zero, `amount` tokens will be minted for `to`. ++ * - when `to` is zero, `amount` of ``from``'s tokens will be burned. ++ * - `from` and `to` are never both zero. ++ * ++ * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ -+ function getElements(List storage list) internal view returns (bytes32[] memory, uint256[] memory) { -+ bytes32[] memory keys = getKeys(list); -+ uint256[] memory values = new uint256[](keys.length); -+ for (uint256 i = 0; i < keys.length; i = i + 1) { -+ values[i] = list.values[keys[i]]; -+ } -+ return (keys, values); -+ } ++ function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { } + + /** -+ * @notice Gets all element keys from the doubly linked list. -+ * @param list A storage pointer to the underlying list. -+ * @return All element keys from head to tail. ++ * @dev Hook that is called after any transfer of tokens. This includes ++ * minting and burning. ++ * ++ * Calling conditions: ++ * ++ * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens ++ * has been transferred to `to`. ++ * - when `from` is zero, `amount` tokens have been minted for `to`. ++ * - when `to` is zero, `amount` of ``from``'s tokens have been burned. ++ * - `from` and `to` are never both zero. ++ * ++ * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ -+ function getKeys(List storage list) internal view returns (bytes32[] memory) { -+ return list.list.getKeys(); -+ } ++ function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual { } + + /** -+ * @notice Returns first N greatest elements of the list. -+ * @param list A storage pointer to the underlying list. -+ * @param n The number of elements to return. -+ * @return The keys of the first n elements. -+ * @dev Reverts if n is greater than the number of elements in the list. ++ * @notice Reserve balance for making payments for gas in this StableToken currency. ++ * @param from The account to reserve balance from ++ * @param value The amount of balance to reserve ++ * @dev Note that this function is called by the protocol when paying for tx fees in this ++ * currency. After the tx is executed, gas is refunded to the sender and credited to the ++ * various tx fee recipients via a call to `creditGasFees`. Note too that the events emitted ++ * by `creditGasFees` reflect the *net* gas fee payments for the transaction. + */ -+ function headN(List storage list, uint256 n) internal view returns (bytes32[] memory) { -+ return list.list.headN(n); ++ function debitGasFees(address from, uint256 value) external onlyVm { ++ _balances[from] -= value; ++ _totalSupply -= value; + } + + /** -+ * @notice Returns the keys of the elements greaterKey than and less than the provided value. -+ * @param list A storage pointer to the underlying list. -+ * @param value The element value. -+ * @param lesserKey The key of the element which could be just left of the new value. -+ * @param greaterKey The key of the element which could be just right of the new value. -+ * @return The correct lesserKey keys. -+ * @return The correct greaterKey keys. ++ * @notice Alternative function to credit balance after making payments ++ * for gas in this StableToken currency. ++ * @param from The account to debit balance from ++ * @param feeRecipient Coinbase address ++ * legacy param gatewayFeeRecipient Gateway address (UNUSED!) ++ * @param communityFund Community fund address ++ * @param tipTxFee Coinbase fee ++ * @param baseTxFee Community fund fee ++ * legacy param gatewayFee Gateway fee (UNUSED!) ++ * @dev Note that this function is called by the protocol when paying for tx fees in this ++ * currency. Before the tx is executed, gas is debited from the sender via a call to ++ * `debitGasFees`. Note too that the events emitted by `creditGasFees` reflect the *net* gas fee ++ * payments for the transaction. + */ -+ function getLesserAndGreater( -+ List storage list, -+ uint256 value, -+ bytes32 lesserKey, -+ bytes32 greaterKey ++ function creditGasFees( ++ address from, ++ address feeRecipient, ++ address, // gatewayFeeRecipient ++ address communityFund, ++ uint256 refund, ++ uint256 tipTxFee, ++ uint256, // gatewayFee ++ uint256 baseTxFee + ) -+ private -+ view -+ returns (bytes32, bytes32) ++ external ++ onlyVm + { -+ // Check for one of the following conditions and fail if none are met: -+ // 1. The value is less than the current lowest value -+ // 2. The value is greater than the current greatest value -+ // 3. The value is just greater than the value for `lesserKey` -+ // 4. The value is just less than the value for `greaterKey` -+ if (lesserKey == bytes32(0) && isValueBetween(list, value, lesserKey, list.list.tail)) { -+ return (lesserKey, list.list.tail); -+ } else if (greaterKey == bytes32(0) && isValueBetween(list, value, list.list.head, greaterKey)) { -+ return (list.list.head, greaterKey); -+ } else if ( -+ lesserKey != bytes32(0) && isValueBetween(list, value, lesserKey, list.list.elements[lesserKey].nextKey) -+ ) { -+ return (lesserKey, list.list.elements[lesserKey].nextKey); -+ } else if ( -+ greaterKey != bytes32(0) -+ && isValueBetween(list, value, list.list.elements[greaterKey].previousKey, greaterKey) -+ ) { -+ return (list.list.elements[greaterKey].previousKey, greaterKey); -+ } ++ _balances[from] += refund; + -+ require(false, "get lesser and greater failure"); -+ return (0, 0); ++ refund += _creditGas(from, communityFund, baseTxFee); ++ refund += _creditGas(from, feeRecipient, tipTxFee); ++ _totalSupply += refund; + } + -+ /** -+ * @notice Returns whether or not a given element is between two other elements. -+ * @param list A storage pointer to the underlying list. -+ * @param value The element value. -+ * @param lesserKey The key of the element whose value should be lesserKey. -+ * @param greaterKey The key of the element whose value should be greaterKey. -+ * @return True if the given element is between the two other elements. -+ */ -+ function isValueBetween( -+ List storage list, -+ uint256 value, -+ bytes32 lesserKey, -+ bytes32 greaterKey -+ ) -+ private -+ view -+ returns (bool) -+ { -+ bool isLesser = lesserKey == bytes32(0) || list.values[lesserKey] <= value; -+ bool isGreater = greaterKey == bytes32(0) || list.values[greaterKey] >= value; -+ return isLesser && isGreater; ++ function _creditGas(address from, address to, uint256 value) internal returns (uint256) { ++ if (to == address(0)) { ++ return 0; ++ } ++ _balances[to] += value; ++ emit Transfer(from, to, value); ++ return value; + } +}
@@ -31041,9 +133222,9 @@
@@ -31058,7 +133239,7 @@
@@ -31068,270 +133249,69 @@
-
+253
+
+52
-0
-
diff --git OP/packages/contracts-bedrock/src/celo/common/linkedlists/SortedLinkedListWithMedian.sol CELO/packages/contracts-bedrock/src/celo/common/linkedlists/SortedLinkedListWithMedian.sol +
diff --git OP/packages/contracts-bedrock/src/celo/testing/MockSortedOracles.sol CELO/packages/contracts-bedrock/src/celo/testing/MockSortedOracles.sol new file mode 100644 -index 0000000000000000000000000000000000000000..458ef554220772c97273526478a794885fa6ac45 +index 0000000000000000000000000000000000000000..d51fa2a7c56c47dc97af8fd34c1db22b8832e7ec --- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/common/linkedlists/SortedLinkedListWithMedian.sol -@@ -0,0 +1,253 @@ ++++ CELO/packages/contracts-bedrock/src/celo/testing/MockSortedOracles.sol +@@ -0,0 +1,52 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.15; + -+import "./LinkedList.sol"; -+import "./SortedLinkedList.sol"; ++import { IOracle } from "../interfaces/IOracle.sol"; + +/** -+ * @title Maintains a sorted list of unsigned ints keyed by bytes32. ++ * @title A mock SortedOracles for testing. + */ -+library SortedLinkedListWithMedian { -+ using SortedLinkedList for SortedLinkedList.List; -+ -+ enum MedianAction { -+ None, -+ Lesser, -+ Greater -+ } -+ -+ enum MedianRelation { -+ Undefined, -+ Lesser, -+ Greater, -+ Equal -+ } -+ -+ struct List { -+ SortedLinkedList.List list; -+ bytes32 median; -+ mapping(bytes32 => MedianRelation) relation; -+ } -+ -+ /** -+ * @notice Inserts an element into a doubly linked list. -+ * @param list A storage pointer to the underlying list. -+ * @param key The key of the element to insert. -+ * @param value The element value. -+ * @param lesserKey The key of the element less than the element to insert. -+ * @param greaterKey The key of the element greater than the element to insert. -+ */ -+ function insert(List storage list, bytes32 key, uint256 value, bytes32 lesserKey, bytes32 greaterKey) internal { -+ list.list.insert(key, value, lesserKey, greaterKey); -+ LinkedList.Element storage element = list.list.list.elements[key]; -+ -+ MedianAction action = MedianAction.None; -+ if (list.list.list.numElements == 1) { -+ list.median = key; -+ list.relation[key] = MedianRelation.Equal; -+ } else if (list.list.list.numElements % 2 == 1) { -+ // When we have an odd number of elements, and the element that we inserted is less than -+ // the previous median, we need to slide the median down one element, since we had previously -+ // selected the greater of the two middle elements. -+ if (element.previousKey == bytes32(0) || list.relation[element.previousKey] == MedianRelation.Lesser) { -+ action = MedianAction.Lesser; -+ list.relation[key] = MedianRelation.Lesser; -+ } else { -+ list.relation[key] = MedianRelation.Greater; -+ } -+ } else { -+ // When we have an even number of elements, and the element that we inserted is greater than -+ // the previous median, we need to slide the median up one element, since we always select -+ // the greater of the two middle elements. -+ if (element.nextKey == bytes32(0) || list.relation[element.nextKey] == MedianRelation.Greater) { -+ action = MedianAction.Greater; -+ list.relation[key] = MedianRelation.Greater; -+ } else { -+ list.relation[key] = MedianRelation.Lesser; -+ } -+ } -+ updateMedian(list, action); -+ } -+ -+ /** -+ * @notice Removes an element from the doubly linked list. -+ * @param list A storage pointer to the underlying list. -+ * @param key The key of the element to remove. -+ */ -+ function remove(List storage list, bytes32 key) internal { -+ MedianAction action = MedianAction.None; -+ if (list.list.list.numElements == 0) { -+ list.median = bytes32(0); -+ } else if (list.list.list.numElements % 2 == 0) { -+ // When we have an even number of elements, we always choose the higher of the two medians. -+ // Thus, if the element we're removing is greaterKey than or equal to the median we need to -+ // slide the median left by one. -+ if (list.relation[key] == MedianRelation.Greater || list.relation[key] == MedianRelation.Equal) { -+ action = MedianAction.Lesser; -+ } -+ } else { -+ // When we don't have an even number of elements, we just choose the median value. -+ // Thus, if the element we're removing is less than or equal to the median, we need to slide -+ // median right by one. -+ if (list.relation[key] == MedianRelation.Lesser || list.relation[key] == MedianRelation.Equal) { -+ action = MedianAction.Greater; -+ } -+ } -+ updateMedian(list, action); -+ -+ list.list.remove(key); -+ } -+ -+ /** -+ * @notice Updates an element in the list. -+ * @param list A storage pointer to the underlying list. -+ * @param key The element key. -+ * @param value The element value. -+ * @param lesserKey The key of the element will be just left of `key` after the update. -+ * @param greaterKey The key of the element will be just right of `key` after the update. -+ * @dev Note that only one of "lesserKey" or "greaterKey" needs to be correct to reduce friction. -+ */ -+ function update(List storage list, bytes32 key, uint256 value, bytes32 lesserKey, bytes32 greaterKey) internal { -+ remove(list, key); -+ insert(list, key, value, lesserKey, greaterKey); -+ } -+ -+ /** -+ * @notice Inserts an element at the tail of the doubly linked list. -+ * @param list A storage pointer to the underlying list. -+ * @param key The key of the element to insert. -+ */ -+ function push(List storage list, bytes32 key) internal { -+ insert(list, key, 0, bytes32(0), list.list.list.tail); -+ } -+ -+ /** -+ * @notice Removes N elements from the head of the list and returns their keys. -+ * @param list A storage pointer to the underlying list. -+ * @param n The number of elements to pop. -+ * @return The keys of the popped elements. -+ */ -+ function popN(List storage list, uint256 n) internal returns (bytes32[] memory) { -+ require(n <= list.list.list.numElements, "not enough elements"); -+ bytes32[] memory keys = new bytes32[](n); -+ for (uint256 i = 0; i < n; i++) { -+ bytes32 key = list.list.list.head; -+ keys[i] = key; -+ remove(list, key); -+ } -+ return keys; -+ } -+ -+ /** -+ * @notice Returns whether or not a particular key is present in the sorted list. -+ * @param list A storage pointer to the underlying list. -+ * @param key The element key. -+ * @return Whether or not the key is in the sorted list. -+ */ -+ function contains(List storage list, bytes32 key) internal view returns (bool) { -+ return list.list.contains(key); -+ } -+ -+ /** -+ * @notice Returns the value for a particular key in the sorted list. -+ * @param list A storage pointer to the underlying list. -+ * @param key The element key. -+ * @return The element value. -+ */ -+ function getValue(List storage list, bytes32 key) internal view returns (uint256) { -+ return list.list.values[key]; -+ } -+ -+ /** -+ * @notice Returns the median value of the sorted list. -+ * @param list A storage pointer to the underlying list. -+ * @return The median value. -+ */ -+ function getMedianValue(List storage list) internal view returns (uint256) { -+ return getValue(list, list.median); -+ } -+ -+ /** -+ * @notice Returns the key of the first element in the list. -+ * @param list A storage pointer to the underlying list. -+ * @return The key of the first element in the list. -+ */ -+ function getHead(List storage list) internal view returns (bytes32) { -+ return list.list.list.head; -+ } ++contract MockSortedOracles is IOracle { ++ uint256 public constant DENOMINATOR = 1000000000000000000000000; ++ mapping(address => uint256) public numerators; ++ mapping(address => uint256) public medianTimestamp; ++ mapping(address => uint256) public numRates; ++ mapping(address => bool) public expired; + -+ /** -+ * @notice Returns the key of the median element in the list. -+ * @param list A storage pointer to the underlying list. -+ * @return The key of the median element in the list. -+ */ -+ function getMedian(List storage list) internal view returns (bytes32) { -+ return list.median; ++ function setMedianRate(address token, uint256 numerator) external returns (bool) { ++ numerators[token] = numerator; ++ return true; + } + -+ /** -+ * @notice Returns the key of the last element in the list. -+ * @param list A storage pointer to the underlying list. -+ * @return The key of the last element in the list. -+ */ -+ function getTail(List storage list) internal view returns (bytes32) { -+ return list.list.list.tail; ++ function setMedianTimestamp(address token, uint256 timestamp) external { ++ medianTimestamp[token] = timestamp; + } + -+ /** -+ * @notice Returns the number of elements in the list. -+ * @param list A storage pointer to the underlying list. -+ * @return The number of elements in the list. -+ */ -+ function getNumElements(List storage list) internal view returns (uint256) { -+ return list.list.list.numElements; ++ function setMedianTimestampToNow(address token) external { ++ // solhint-disable-next-line not-rely-on-time ++ medianTimestamp[token] = uint128(block.timestamp); + } -+ -+ /** -+ * @notice Gets all elements from the doubly linked list. -+ * @param list A storage pointer to the underlying list. -+ * @return Array of all keys in the list. -+ * @return Values corresponding to keys, which will be ordered largest to smallest. -+ * @return Array of relations to median of corresponding list elements. -+ */ -+ function getElements(List storage list) -+ internal -+ view -+ returns (bytes32[] memory, uint256[] memory, MedianRelation[] memory) -+ { -+ bytes32[] memory keys = getKeys(list); -+ uint256[] memory values = new uint256[](keys.length); -+ MedianRelation[] memory relations = new MedianRelation[](keys.length); -+ for (uint256 i = 0; i < keys.length; i++) { -+ values[i] = list.list.values[keys[i]]; -+ relations[i] = list.relation[keys[i]]; -+ } -+ return (keys, values, relations); ++ ++ function setNumRates(address token, uint256 rate) external { ++ numRates[token] = rate; // This change may break something, TODO + } + -+ /** -+ * @notice Gets all element keys from the doubly linked list. -+ * @param list A storage pointer to the underlying list. -+ * @return All element keys from head to tail. -+ */ -+ function getKeys(List storage list) internal view returns (bytes32[] memory) { -+ return list.list.getKeys(); ++ function getExchangeRate(address token) external view returns (uint256 numerator, uint256 denominator) { ++ return medianRate(token); + } + -+ /** -+ * @notice Moves the median pointer right or left of its current value. -+ * @param list A storage pointer to the underlying list. -+ * @param action Which direction to move the median pointer. -+ */ -+ function updateMedian(List storage list, MedianAction action) private { -+ LinkedList.Element storage previousMedian = list.list.list.elements[list.median]; -+ if (action == MedianAction.Lesser) { -+ list.relation[list.median] = MedianRelation.Greater; -+ list.median = previousMedian.previousKey; -+ } else if (action == MedianAction.Greater) { -+ list.relation[list.median] = MedianRelation.Lesser; -+ list.median = previousMedian.nextKey; ++ function medianRate(address token) public view returns (uint256, uint256) { ++ if (numerators[token] > 0) { ++ return (numerators[token], DENOMINATOR); + } -+ list.relation[list.median] = MedianRelation.Equal; ++ return (0, 0); ++ } ++ ++ function isOldestReportExpired(address token) public view returns (bool, address) { ++ return (expired[token], token); ++ } ++ ++ function setOldestReportExpired(address token) public { ++ expired[token] = true; + } +}
@@ -31340,9 +133320,9 @@
@@ -31357,7 +133337,7 @@
@@ -31367,76 +133347,24 @@
-
+58
+
+6
-0
-
diff --git OP/packages/contracts-bedrock/src/celo/governance/interfaces/IElection.sol CELO/packages/contracts-bedrock/src/celo/governance/interfaces/IElection.sol +
diff --git OP/packages/contracts-bedrock/src/celo/uniswap/interfaces/IUniswapV2FactoryMin.sol CELO/packages/contracts-bedrock/src/celo/uniswap/interfaces/IUniswapV2FactoryMin.sol new file mode 100644 -index 0000000000000000000000000000000000000000..f099ce364a2705987e0b242c07fbc1871371077b +index 0000000000000000000000000000000000000000..14c6495920a1ff49978917c124c7a7fd82d7c6b6 --- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/governance/interfaces/IElection.sol -@@ -0,0 +1,58 @@ ++++ CELO/packages/contracts-bedrock/src/celo/uniswap/interfaces/IUniswapV2FactoryMin.sol +@@ -0,0 +1,6 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity ^0.8.15; + -+interface IElection { -+ function electValidatorSigners() external view returns (address[] memory); -+ function electNValidatorSigners(uint256, uint256) external view returns (address[] memory); -+ function vote(address, uint256, address, address) external returns (bool); -+ function activate(address) external returns (bool); -+ function revokeActive(address, uint256, address, address, uint256) external returns (bool); -+ function revokeAllActive(address, address, address, uint256) external returns (bool); -+ function revokePending(address, uint256, address, address, uint256) external returns (bool); -+ function markGroupIneligible(address) external; -+ function markGroupEligible(address, address, address) external; -+ function allowedToVoteOverMaxNumberOfGroups(address) external returns (bool); -+ function forceDecrementVotes( -+ address, -+ uint256, -+ address[] calldata, -+ address[] calldata, -+ uint256[] calldata -+ ) -+ external -+ returns (uint256); -+ function setAllowedToVoteOverMaxNumberOfGroups(bool flag) external; -+ -+ // view functions -+ function getElectableValidators() external view returns (uint256, uint256); -+ function getElectabilityThreshold() external view returns (uint256); -+ function getNumVotesReceivable(address) external view returns (uint256); -+ function getTotalVotes() external view returns (uint256); -+ function getActiveVotes() external view returns (uint256); -+ function getTotalVotesByAccount(address) external view returns (uint256); -+ function getPendingVotesForGroupByAccount(address, address) external view returns (uint256); -+ function getActiveVotesForGroupByAccount(address, address) external view returns (uint256); -+ function getTotalVotesForGroupByAccount(address, address) external view returns (uint256); -+ function getActiveVoteUnitsForGroupByAccount(address, address) external view returns (uint256); -+ function getTotalVotesForGroup(address) external view returns (uint256); -+ function getActiveVotesForGroup(address) external view returns (uint256); -+ function getPendingVotesForGroup(address) external view returns (uint256); -+ function getGroupEligibility(address) external view returns (bool); -+ function getGroupEpochRewards(address, uint256, uint256[] calldata) external view returns (uint256); -+ function getGroupsVotedForByAccount(address) external view returns (address[] memory); -+ function getEligibleValidatorGroups() external view returns (address[] memory); -+ function getTotalVotesForEligibleValidatorGroups() external view returns (address[] memory, uint256[] memory); -+ function getCurrentValidatorSigners() external view returns (address[] memory); -+ function canReceiveVotes(address, uint256) external view returns (bool); -+ function hasActivatablePendingVotes(address, address) external view returns (bool); -+ function validatorSignerAddressFromCurrentSet(uint256 index) external view returns (address); -+ function numberValidatorsInCurrentSet() external view returns (uint256); -+ -+ // only owner -+ function setElectableValidators(uint256, uint256) external returns (bool); -+ function setMaxNumGroupsVotedFor(uint256) external returns (bool); -+ function setElectabilityThreshold(uint256) external returns (bool); -+ -+ // only VM -+ function distributeEpochRewards(address, uint256, address, address) external; ++interface IUniswapV2FactoryMin { ++ function getPair(address tokenA, address tokenB) external view returns (address pair); +}
@@ -31444,9 +133372,9 @@
@@ -31461,7 +133389,7 @@
@@ -31471,42 +133399,40 @@
-
+24
+
+22
-0
-
diff --git OP/packages/contracts-bedrock/src/celo/governance/interfaces/IGovernance.sol CELO/packages/contracts-bedrock/src/celo/governance/interfaces/IGovernance.sol +
diff --git OP/packages/contracts-bedrock/src/celo/uniswap/interfaces/IUniswapV2RouterMin.sol CELO/packages/contracts-bedrock/src/celo/uniswap/interfaces/IUniswapV2RouterMin.sol new file mode 100644 -index 0000000000000000000000000000000000000000..883844ea8f219feaaa747a6fd61f33424c6828a8 +index 0000000000000000000000000000000000000000..f1755edb137d00b91696baa96ac6d44ae601ca28 --- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/governance/interfaces/IGovernance.sol -@@ -0,0 +1,24 @@ ++++ CELO/packages/contracts-bedrock/src/celo/uniswap/interfaces/IUniswapV2RouterMin.sol +@@ -0,0 +1,22 @@ +// SPDX-License-Identifier: LGPL-3.0-only +pragma solidity ^0.8.15; + -+interface IGovernance { -+ function votePartially( -+ uint256 proposalId, -+ uint256 index, -+ uint256 yesVotes, -+ uint256 noVotes, -+ uint256 abstainVotes ++interface IUniswapV2RouterMin { ++ function factory() external pure returns (address); ++ function swapExactTokensForTokens( ++ uint256 amountIn, ++ uint256 amountOutMin, ++ address[] calldata path, ++ address to, ++ uint256 deadline + ) + external -+ returns (bool); -+ -+ function isVoting(address) external view returns (bool); -+ function getAmountOfGoldUsedForVoting(address account) external view returns (uint256); -+ -+ function getProposal(uint256 proposalId) ++ returns (uint256[] memory amounts); ++ function getAmountsOut( ++ uint256 amountIn, ++ address[] calldata path ++ ) + external + view -+ returns (address, uint256, uint256, uint256, string memory, uint256, bool); -+ -+ function getReferendumStageDuration() external view returns (uint256); ++ returns (uint256[] memory amounts); +}
@@ -31514,9 +133440,9 @@
@@ -31525,13 +133451,13 @@
- (new) + OP
@@ -31541,57 +133467,75 @@
-
+29
-
-0
+
+21
+
-16
-
diff --git OP/packages/contracts-bedrock/src/celo/governance/interfaces/ILockedGold.sol CELO/packages/contracts-bedrock/src/celo/governance/interfaces/ILockedGold.sol -new file mode 100644 -index 0000000000000000000000000000000000000000..38002d58914c70665df042ea9e3a3051d2c53091 ---- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/governance/interfaces/ILockedGold.sol -@@ -0,0 +1,29 @@ -+// SPDX-License-Identifier: LGPL-3.0-only -+pragma solidity ^0.8.15; +
diff --git OP/packages/contracts-bedrock/src/dispute/interfaces/IAnchorStateRegistry.sol CELO/packages/contracts-bedrock/src/dispute/interfaces/IAnchorStateRegistry.sol +index dd7724538e58cab8ee1142148e91463a02146cb1..28c544c0d408bba691dfa885c6695051763e16b1 100644 +--- OP/packages/contracts-bedrock/src/dispute/interfaces/IAnchorStateRegistry.sol ++++ CELO/packages/contracts-bedrock/src/dispute/interfaces/IAnchorStateRegistry.sol +@@ -3,27 +3,32 @@ pragma solidity ^0.8.0; +  + import { IFaultDisputeGame } from "src/dispute/interfaces/IFaultDisputeGame.sol"; + import { IDisputeGameFactory } from "src/dispute/interfaces/IDisputeGameFactory.sol"; +- ++import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol"; + import "src/dispute/lib/Types.sol"; +  +-/// @title IAnchorStateRegistry +-/// @notice Describes a contract that stores the anchor state for each game type. + interface IAnchorStateRegistry { +- /// @notice Returns the anchor state for the given game type. +- /// @param _gameType The game type to get the anchor state for. +- /// @return The anchor state for the given game type. +- function anchors(GameType _gameType) external view returns (Hash, uint256); ++ struct StartingAnchorRoot { ++ GameType gameType; ++ OutputRoot outputRoot; ++ } + -+interface ILockedGold { -+ function lock() external payable; -+ function incrementNonvotingAccountBalance(address, uint256) external; -+ function decrementNonvotingAccountBalance(address, uint256) external; -+ function getAccountTotalLockedGold(address) external view returns (uint256); -+ function getTotalLockedGold() external view returns (uint256); -+ function getPendingWithdrawals(address) external view returns (uint256[] memory, uint256[] memory); -+ function getPendingWithdrawal(address account, uint256 index) external view returns (uint256, uint256); -+ function getTotalPendingWithdrawals(address) external view returns (uint256); -+ function unlock(uint256) external; -+ function relock(uint256, uint256) external; -+ function withdraw(uint256) external; -+ function slash( -+ address account, -+ uint256 penalty, -+ address reporter, -+ uint256 reward, -+ address[] calldata lessers, -+ address[] calldata greaters, -+ uint256[] calldata indices ++ error InvalidGameStatus(); ++ error Unauthorized(); ++ error UnregisteredGame(); ++ ++ event Initialized(uint8 version); +  +- /// @notice Returns the DisputeGameFactory address. +- /// @return DisputeGameFactory address. ++ function anchors(GameType) external view returns (Hash root, uint256 l2BlockNumber); + function disputeGameFactory() external view returns (IDisputeGameFactory); +- +- /// @notice Callable by FaultDisputeGame contracts to update the anchor state. Pulls the anchor state directly from +- /// the FaultDisputeGame contract and stores it in the registry if the new anchor state is valid and the +- /// state is newer than the current anchor state. ++ function initialize( ++ StartingAnchorRoot[] memory _startingAnchorRoots, ++ ISuperchainConfig _superchainConfig + ) + external; -+ function isSlasher(address) external view returns (bool); -+ function unlockingPeriod() external view returns (uint256); -+ function getAccountNonvotingLockedGold(address account) external view returns (uint256); -+}
++ function setAnchorState(IFaultDisputeGame _game) external; ++ function superchainConfig() external view returns (ISuperchainConfig); + function tryUpdateAnchorState() external; ++ function version() external view returns (string memory); +  +- /// @notice Sets the anchor state given the game. +- /// @param _game The game to set the anchor state for. +- function setAnchorState(IFaultDisputeGame _game) external; ++ function __constructor__(IDisputeGameFactory _disputeGameFactory) external; + }
@@ -31600,13 +133544,13 @@
- (new) + OP
@@ -31616,82 +133560,89 @@
-
+54
-
-0
+
+14
+
-32
-
diff --git OP/packages/contracts-bedrock/src/celo/governance/interfaces/IReleaseGold.sol CELO/packages/contracts-bedrock/src/celo/governance/interfaces/IReleaseGold.sol -new file mode 100644 -index 0000000000000000000000000000000000000000..e211ce7399e37478a43b3b5e0335339e5c253265 ---- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/governance/interfaces/IReleaseGold.sol -@@ -0,0 +1,54 @@ -+// SPDX-License-Identifier: LGPL-3.0-only -+pragma solidity ^0.8.15; -+ -+interface IReleaseGold { -+ function transfer(address, uint256) external; -+ function unlockGold(uint256) external; -+ function withdrawLockedGold(uint256) external; -+ function authorizeVoteSigner(address payable, uint8, bytes32, bytes32) external; -+ function authorizeValidatorSigner(address payable, uint8, bytes32, bytes32) external; -+ function authorizeValidatorSignerWithPublicKey(address payable, uint8, bytes32, bytes32, bytes calldata) external; -+ function authorizeValidatorSignerWithKeys( -+ address payable, -+ uint8, -+ bytes32, -+ bytes32, -+ bytes calldata, -+ bytes calldata, -+ bytes calldata -+ ) -+ external; -+ function authorizeAttestationSigner(address payable, uint8, bytes32, bytes32) external; -+ function revokeActive(address, uint256, address, address, uint256) external; -+ function revokePending(address, uint256, address, address, uint256) external; -+ -+ // view functions -+ function getTotalBalance() external view returns (uint256); -+ function getRemainingTotalBalance() external view returns (uint256); -+ function getRemainingUnlockedBalance() external view returns (uint256); -+ function getRemainingLockedBalance() external view returns (uint256); -+ function getCurrentReleasedTotalAmount() external view returns (uint256); -+ function isRevoked() external view returns (bool); -+ -+ // only beneficiary -+ function setCanExpire(bool) external; -+ function withdraw(uint256) external; -+ function lockGold(uint256) external; -+ function relockGold(uint256, uint256) external; -+ function setAccount(string calldata, bytes calldata, address, uint8, bytes32, bytes32) external; -+ function createAccount() external; -+ function setAccountName(string calldata) external; -+ function setAccountWalletAddress(address, uint8, bytes32, bytes32) external; -+ function setAccountDataEncryptionKey(bytes calldata) external; -+ function setAccountMetadataURL(string calldata) external; -+ -+ // only owner -+ function setBeneficiary(address payable) external; -+ -+ // only release owner -+ function setLiquidityProvision() external; -+ function setMaxDistribution(uint256) external; -+ function refundAndFinalize() external; -+ function revoke() external; -+ function expire() external; -+}
+
diff --git OP/packages/contracts-bedrock/src/dispute/interfaces/IDelayedWETH.sol CELO/packages/contracts-bedrock/src/dispute/interfaces/IDelayedWETH.sol +index 80b90c69b8604336bb3807c1102971a99dbab378..7a7b36052f3dead3fb85573be93e433bf6420701 100644 +--- OP/packages/contracts-bedrock/src/dispute/interfaces/IDelayedWETH.sol ++++ CELO/packages/contracts-bedrock/src/dispute/interfaces/IDelayedWETH.sol +@@ -1,48 +1,30 @@ + // SPDX-License-Identifier: MIT + pragma solidity ^0.8.0; +  +-import { IWETH } from "src/dispute/interfaces/IWETH.sol"; ++import { IWETH } from "src/universal/interfaces/IWETH.sol"; ++import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol"; +  +-/// @title IDelayedWETH +-/// @notice Interface for the DelayedWETH contract. + interface IDelayedWETH is IWETH { +- /// @notice Represents a withdrawal request. + struct WithdrawalRequest { + uint256 amount; + uint256 timestamp; + } +  +- /// @notice Emitted when an unwrap is started. +- /// @param src The address that started the unwrap. +- /// @param wad The amount of WETH that was unwrapped. + event Unwrap(address indexed src, uint256 wad); +  +- /// @notice Returns the withdrawal delay in seconds. +- /// @return The withdrawal delay in seconds. +- function delay() external view returns (uint256); ++ fallback() external payable; ++ receive() external payable; +  +- /// @notice Returns a withdrawal request for the given address. +- /// @param _owner The address to query the withdrawal request of. +- /// @param _guy Sub-account to query the withdrawal request of. +- /// @return The withdrawal request for the given address-subaccount pair. +- function withdrawals(address _owner, address _guy) external view returns (uint256, uint256); +- +- /// @notice Unlocks withdrawals for the sender's account, after a time delay. +- /// @param _guy Sub-account to unlock. +- /// @param _wad The amount of WETH to unlock. ++ function config() external view returns (ISuperchainConfig); ++ function delay() external view returns (uint256); ++ function hold(address _guy, uint256 _wad) external; ++ function initialize(address _owner, ISuperchainConfig _config) external; ++ function owner() external view returns (address); ++ function recover(uint256 _wad) external; ++ function transferOwnership(address newOwner) external; ++ function renounceOwnership() external; + function unlock(address _guy, uint256 _wad) external; +- +- /// @notice Extension to withdrawal, must provide a sub-account to withdraw from. +- /// @param _guy Sub-account to withdraw from. +- /// @param _wad The amount of WETH to withdraw. + function withdraw(address _guy, uint256 _wad) external; +- +- /// @notice Allows the owner to recover from error cases by pulling ETH out of the contract. +- /// @param _wad The amount of WETH to recover. +- function recover(uint256 _wad) external; +- +- /// @notice Allows the owner to recover from error cases by pulling ETH from a specific owner. +- /// @param _guy The address to recover the WETH from. +- /// @param _wad The amount of WETH to recover. +- function hold(address _guy, uint256 _wad) external; ++ function withdrawals(address _owner, address _guy) external view returns (uint256, uint256); ++ function version() external view returns (string memory); + }
@@ -31700,13 +133651,13 @@
- (new) + OP
@@ -31716,113 +133667,608 @@
-
+85
-
-0
+
+3
+
-52
-
diff --git OP/packages/contracts-bedrock/src/celo/governance/interfaces/IValidators.sol CELO/packages/contracts-bedrock/src/celo/governance/interfaces/IValidators.sol -new file mode 100644 -index 0000000000000000000000000000000000000000..8a10e91fc8129cfb736057443bbec7c63170921e ---- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/governance/interfaces/IValidators.sol -@@ -0,0 +1,85 @@ -+// SPDX-License-Identifier: LGPL-3.0-only -+pragma solidity ^0.8.15; -+ -+interface IValidators { -+ function registerValidator(bytes calldata, bytes calldata, bytes calldata) external returns (bool); -+ function deregisterValidator(uint256) external returns (bool); -+ function affiliate(address) external returns (bool); -+ function deaffiliate() external returns (bool); -+ function updateBlsPublicKey(bytes calldata, bytes calldata) external returns (bool); -+ function registerValidatorGroup(uint256) external returns (bool); -+ function deregisterValidatorGroup(uint256) external returns (bool); -+ function addMember(address) external returns (bool); -+ function addFirstMember(address, address, address) external returns (bool); -+ function removeMember(address) external returns (bool); -+ function reorderMember(address, address, address) external returns (bool); -+ function updateCommission() external; -+ function setNextCommissionUpdate(uint256) external; -+ function resetSlashingMultiplier() external; -+ -+ // only owner -+ function setCommissionUpdateDelay(uint256) external; -+ function setMaxGroupSize(uint256) external returns (bool); -+ function setMembershipHistoryLength(uint256) external returns (bool); -+ function setValidatorScoreParameters(uint256, uint256) external returns (bool); -+ function setGroupLockedGoldRequirements(uint256, uint256) external returns (bool); -+ function setValidatorLockedGoldRequirements(uint256, uint256) external returns (bool); -+ function setSlashingMultiplierResetPeriod(uint256) external; -+ -+ // view functions -+ function getMaxGroupSize() external view returns (uint256); -+ function getCommissionUpdateDelay() external view returns (uint256); -+ function getValidatorScoreParameters() external view returns (uint256, uint256); -+ function getMembershipHistory(address) +
diff --git OP/packages/contracts-bedrock/src/dispute/interfaces/IDisputeGame.sol CELO/packages/contracts-bedrock/src/dispute/interfaces/IDisputeGame.sol +index 7e9389b4ddafb4c47908e106d872f8eaafce5e3c..f5a650202d0ce13a8e8f7efa3352df825041f74d 100644 +--- OP/packages/contracts-bedrock/src/dispute/interfaces/IDisputeGame.sol ++++ CELO/packages/contracts-bedrock/src/dispute/interfaces/IDisputeGame.sol +@@ -2,68 +2,19 @@ // SPDX-License-Identifier: MIT + pragma solidity ^0.8.0; +  + import { IInitializable } from "src/dispute/interfaces/IInitializable.sol"; +- + import "src/dispute/lib/Types.sol"; +  +-/// @title IDisputeGame +-/// @notice The generic interface for a DisputeGame contract. + interface IDisputeGame is IInitializable { +- /// @notice Emitted when the game is resolved. +- /// @param status The status of the game after resolution. + event Resolved(GameStatus indexed status); +  +- /// @notice Returns the timestamp that the DisputeGame contract was created at. +- /// @return createdAt_ The timestamp that the DisputeGame contract was created at. +- function createdAt() external view returns (Timestamp createdAt_); +- +- /// @notice Returns the timestamp that the DisputeGame contract was resolved at. +- /// @return resolvedAt_ The timestamp that the DisputeGame contract was resolved at. +- function resolvedAt() external view returns (Timestamp resolvedAt_); +- +- /// @notice Returns the current status of the game. +- /// @return status_ The current status of the game. +- function status() external view returns (GameStatus status_); +- +- /// @notice Getter for the game type. +- /// @dev The reference impl should be entirely different depending on the type (fault, validity) +- /// i.e. The game type should indicate the security model. +- /// @return gameType_ The type of proof system being used. ++ function createdAt() external view returns (Timestamp); ++ function resolvedAt() external view returns (Timestamp); ++ function status() external view returns (GameStatus); + function gameType() external view returns (GameType gameType_); +- +- /// @notice Getter for the creator of the dispute game. +- /// @dev `clones-with-immutable-args` argument #1 +- /// @return creator_ The creator of the dispute game. + function gameCreator() external pure returns (address creator_); +- +- /// @notice Getter for the root claim. +- /// @dev `clones-with-immutable-args` argument #2 +- /// @return rootClaim_ The root claim of the DisputeGame. + function rootClaim() external pure returns (Claim rootClaim_); +- +- /// @notice Getter for the parent hash of the L1 block when the dispute game was created. +- /// @dev `clones-with-immutable-args` argument #3 +- /// @return l1Head_ The parent hash of the L1 block when the dispute game was created. + function l1Head() external pure returns (Hash l1Head_); +- +- /// @notice Getter for the extra data. +- /// @dev `clones-with-immutable-args` argument #4 +- /// @return extraData_ Any extra data supplied to the dispute game contract by the creator. + function extraData() external pure returns (bytes memory extraData_); +- +- /// @notice If all necessary information has been gathered, this function should mark the game +- /// status as either `CHALLENGER_WINS` or `DEFENDER_WINS` and return the status of +- /// the resolved game. It is at this stage that the bonds should be awarded to the +- /// necessary parties. +- /// @dev May only be called if the `status` is `IN_PROGRESS`. +- /// @return status_ The status of the game after resolution. + function resolve() external returns (GameStatus status_); +- +- /// @notice A compliant implementation of this interface should return the components of the +- /// game UUID's preimage provided in the cwia payload. The preimage of the UUID is +- /// constructed as `keccak256(gameType . rootClaim . extraData)` where `.` denotes +- /// concatenation. +- /// @return gameType_ The type of proof system being used. +- /// @return rootClaim_ The root claim of the DisputeGame. +- /// @return extraData_ Any extra data supplied to the dispute game contract by the creator. + function gameData() external view returns (GameType gameType_, Claim rootClaim_, bytes memory extraData_); + }
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+36
+
-99
+ +
+ +
+
+
diff --git OP/packages/contracts-bedrock/src/dispute/interfaces/IDisputeGameFactory.sol CELO/packages/contracts-bedrock/src/dispute/interfaces/IDisputeGameFactory.sol +index 5021de04d62a874a37e1d9331a47002364ee0c26..1e70cbbb05bf11ff4b7c3ef71089c78966ed148f 100644 +--- OP/packages/contracts-bedrock/src/dispute/interfaces/IDisputeGameFactory.sol ++++ CELO/packages/contracts-bedrock/src/dispute/interfaces/IDisputeGameFactory.sol +@@ -1,30 +1,10 @@ + // SPDX-License-Identifier: MIT + pragma solidity ^0.8.0; +  +-import { IDisputeGame } from "./IDisputeGame.sol"; +- ++import { IDisputeGame } from "src/dispute/interfaces/IDisputeGame.sol"; + import "src/dispute/lib/Types.sol"; +  +-/// @title IDisputeGameFactory +-/// @notice The interface for a DisputeGameFactory contract. + interface IDisputeGameFactory { +- /// @notice Emitted when a new dispute game is created +- /// @param disputeProxy The address of the dispute game proxy +- /// @param gameType The type of the dispute game proxy's implementation +- /// @param rootClaim The root claim of the dispute game +- event DisputeGameCreated(address indexed disputeProxy, GameType indexed gameType, Claim indexed rootClaim); +- +- /// @notice Emitted when a new game implementation added to the factory +- /// @param impl The implementation contract for the given `GameType`. +- /// @param gameType The type of the DisputeGame. +- event ImplementationSet(address indexed impl, GameType indexed gameType); +- +- /// @notice Emitted when a game type's initialization bond is updated +- /// @param gameType The type of the DisputeGame. +- /// @param newBond The new bond (in wei) for initializing the game type. +- event InitBondUpdated(GameType indexed gameType, uint256 indexed newBond); +- +- /// @notice Information about a dispute game found in a `findLatestGames` search. + struct GameSearchResult { + uint256 index; + GameId metadata; +@@ -33,85 +13,46 @@ Claim rootClaim; + bytes extraData; + } +  +- /// @notice The total number of dispute games created by this factory. +- /// @return gameCount_ The total number of dispute games created by this factory. +- function gameCount() external view returns (uint256 gameCount_); ++ error GameAlreadyExists(Hash uuid); ++ error IncorrectBondAmount(); ++ error NoImplementation(GameType gameType); +  +- /// @notice `games` queries an internal mapping that maps the hash of +- /// `gameType ++ rootClaim ++ extraData` to the deployed `DisputeGame` clone. +- /// @dev `++` equates to concatenation. +- /// @param _gameType The type of the DisputeGame - used to decide the proxy implementation +- /// @param _rootClaim The root claim of the DisputeGame. +- /// @param _extraData Any extra data that should be provided to the created dispute game. +- /// @return proxy_ The clone of the `DisputeGame` created with the given parameters. +- /// Returns `address(0)` if nonexistent. +- /// @return timestamp_ The timestamp of the creation of the dispute game. +- function games( ++ event DisputeGameCreated(address indexed disputeProxy, GameType indexed gameType, Claim indexed rootClaim); ++ event ImplementationSet(address indexed impl, GameType indexed gameType); ++ event InitBondUpdated(GameType indexed gameType, uint256 indexed newBond); ++ event Initialized(uint8 version); ++ event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); ++ ++ function create( + GameType _gameType, + Claim _rootClaim, +- bytes calldata _extraData ++ bytes memory _extraData ++ ) + external ++ payable ++ returns (IDisputeGame proxy_); ++ function findLatestGames( ++ GameType _gameType, ++ uint256 _start, ++ uint256 _n + ) + external + view +- returns (IDisputeGame proxy_, Timestamp timestamp_); +- +- /// @notice `gameAtIndex` returns the dispute game contract address and its creation timestamp +- /// at the given index. Each created dispute game increments the underlying index. +- /// @param _index The index of the dispute game. +- /// @return gameType_ The type of the DisputeGame - used to decide the proxy implementation. +- /// @return timestamp_ The timestamp of the creation of the dispute game. +- /// @return proxy_ The clone of the `DisputeGame` created with the given parameters. +- /// Returns `address(0)` if nonexistent. ++ returns (GameSearchResult[] memory games_); + function gameAtIndex(uint256 _index) + external + view + returns (GameType gameType_, Timestamp timestamp_, IDisputeGame proxy_); +- +- /// @notice `gameImpls` is a mapping that maps `GameType`s to their respective +- /// `IDisputeGame` implementations. +- /// @param _gameType The type of the dispute game. +- /// @return impl_ The address of the implementation of the game type. +- /// Will be cloned on creation of a new dispute game with the given `gameType`. +- function gameImpls(GameType _gameType) external view returns (IDisputeGame impl_); +- +- /// @notice Returns the required bonds for initializing a dispute game of the given type. +- /// @param _gameType The type of the dispute game. +- /// @return bond_ The required bond for initializing a dispute game of the given type. +- function initBonds(GameType _gameType) external view returns (uint256 bond_); +- +- /// @notice Creates a new DisputeGame proxy contract. +- /// @param _gameType The type of the DisputeGame - used to decide the proxy implementation. +- /// @param _rootClaim The root claim of the DisputeGame. +- /// @param _extraData Any extra data that should be provided to the created dispute game. +- /// @return proxy_ The address of the created DisputeGame proxy. +- function create( ++ function gameCount() external view returns (uint256 gameCount_); ++ function gameImpls(GameType) external view returns (IDisputeGame); ++ function games( + GameType _gameType, + Claim _rootClaim, +- bytes calldata _extraData ++ bytes memory _extraData + ) + external +- payable +- returns (IDisputeGame proxy_); +- +- /// @notice Sets the implementation contract for a specific `GameType`. +- /// @dev May only be called by the `owner`. +- /// @param _gameType The type of the DisputeGame. +- /// @param _impl The implementation contract for the given `GameType`. +- function setImplementation(GameType _gameType, IDisputeGame _impl) external; +- +- /// @notice Sets the bond (in wei) for initializing a game type. +- /// @dev May only be called by the `owner`. +- /// @param _gameType The type of the DisputeGame. +- /// @param _initBond The bond (in wei) for initializing a game type. +- function setInitBond(GameType _gameType, uint256 _initBond) external; +- +- /// @notice Returns a unique identifier for the given dispute game parameters. +- /// @dev Hashes the concatenation of `gameType . rootClaim . extraData` +- /// without expanding memory. +- /// @param _gameType The type of the DisputeGame. +- /// @param _rootClaim The root claim of the DisputeGame. +- /// @param _extraData Any extra data that should be provided to the created dispute game. +- /// @return uuid_ The unique identifier for the given dispute game parameters. + view -+ returns (uint256[] memory, address[] memory, uint256, uint256); -+ function calculateEpochScore(uint256) external view returns (uint256); -+ function calculateGroupEpochScore(uint256[] calldata) external view returns (uint256); -+ function getAccountLockedGoldRequirement(address) external view returns (uint256); -+ function meetsAccountLockedGoldRequirements(address) external view returns (bool); -+ function getValidatorBlsPublicKeyFromSigner(address) external view returns (bytes memory); -+ function getValidator(address account) ++ returns (IDisputeGame proxy_, Timestamp timestamp_); + function getGameUUID( + GameType _gameType, + Claim _rootClaim, +@@ -120,18 +61,14 @@ ) + external + pure + returns (Hash uuid_); ++ function initBonds(GameType) external view returns (uint256); ++ function initialize(address _owner) external; ++ function owner() external view returns (address); ++ function renounceOwnership() external; ++ function setImplementation(GameType _gameType, IDisputeGame _impl) external; ++ function setInitBond(GameType _gameType, uint256 _initBond) external; ++ function transferOwnership(address newOwner) external; ++ function version() external view returns (string memory); +  +- /// @notice Finds the `_n` most recent `GameId`'s of type `_gameType` starting at `_start`. If there are less than +- /// `_n` games of type `_gameType` starting at `_start`, then the returned array will be shorter than `_n`. +- /// @param _gameType The type of game to find. +- /// @param _start The index to start the reverse search from. +- /// @param _n The number of games to find. +- function findLatestGames( +- GameType _gameType, +- uint256 _start, +- uint256 _n +- ) +- external +- view +- returns (GameSearchResult[] memory games_); ++ function __constructor__() external; + }
+
+ + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+98
+
-68
+ +
+ +
+
+
diff --git OP/packages/contracts-bedrock/src/dispute/interfaces/IFaultDisputeGame.sol CELO/packages/contracts-bedrock/src/dispute/interfaces/IFaultDisputeGame.sol +index 43de378ac06d174b846c87c03a944cd60d549c3d..379c4fcb6a485a6dd4746608a261e518b2feabee 100644 +--- OP/packages/contracts-bedrock/src/dispute/interfaces/IFaultDisputeGame.sol ++++ CELO/packages/contracts-bedrock/src/dispute/interfaces/IFaultDisputeGame.sol +@@ -1,14 +1,14 @@ + // SPDX-License-Identifier: MIT + pragma solidity ^0.8.0; +  +-import { IDisputeGame } from "./IDisputeGame.sol"; +- ++import { IDisputeGame } from "src/dispute/interfaces/IDisputeGame.sol"; ++import { IDelayedWETH } from "src/dispute/interfaces/IDelayedWETH.sol"; ++import { IAnchorStateRegistry } from "src/dispute/interfaces/IAnchorStateRegistry.sol"; ++import { IBigStepper } from "src/dispute/interfaces/IBigStepper.sol"; ++import { Types } from "src/libraries/Types.sol"; + import "src/dispute/lib/Types.sol"; +  +-/// @title IFaultDisputeGame +-/// @notice The interface for a fault proof backed dispute game. + interface IFaultDisputeGame is IDisputeGame { +- /// @notice The `ClaimData` struct represents the data associated with a Claim. + struct ClaimData { + uint32 parentIndex; + address counteredBy; +@@ -19,7 +19,6 @@ Position position; + Clock clock; + } +  +- /// @notice The `ResolutionCheckpoint` struct represents the data associated with an in-progress claim resolution. + struct ResolutionCheckpoint { + bool initialCheckpointComplete; + uint32 subgameIndex; +@@ -27,73 +26,104 @@ Position leftmostPosition; + address counteredBy; + } +  +- /// @notice Emitted when a new claim is added to the DAG by `claimant` +- /// @param parentIndex The index within the `claimData` array of the parent claim +- /// @param claim The claim being added +- /// @param claimant The address of the claimant ++ error AlreadyInitialized(); ++ error AnchorRootNotFound(); ++ error BlockNumberMatches(); ++ error BondTransferFailed(); ++ error CannotDefendRootClaim(); ++ error ClaimAboveSplit(); ++ error ClaimAlreadyExists(); ++ error ClaimAlreadyResolved(); ++ error ClockNotExpired(); ++ error ClockTimeExceeded(); ++ error ContentLengthMismatch(); ++ error DuplicateStep(); ++ error EmptyItem(); ++ error GameDepthExceeded(); ++ error GameNotInProgress(); ++ error IncorrectBondAmount(); ++ error InvalidChallengePeriod(); ++ error InvalidClockExtension(); ++ error InvalidDataRemainder(); ++ error InvalidDisputedClaimIndex(); ++ error InvalidHeader(); ++ error InvalidHeaderRLP(); ++ error InvalidLocalIdent(); ++ error InvalidOutputRootProof(); ++ error InvalidParent(); ++ error InvalidPrestate(); ++ error InvalidSplitDepth(); ++ error L2BlockNumberChallenged(); ++ error MaxDepthTooLarge(); ++ error NoCreditToClaim(); ++ error OutOfOrderResolution(); ++ error UnexpectedList(); ++ error UnexpectedRootClaim(Claim rootClaim); ++ error UnexpectedString(); ++ error ValidStep(); ++ + event Move(uint256 indexed parentIndex, Claim indexed claim, address indexed claimant); +  +- /// @notice Attack a disagreed upon `Claim`. +- /// @param _disputed The `Claim` being attacked. +- /// @param _parentIndex Index of the `Claim` to attack in the `claimData` array. This must match the `_disputed` +- /// claim. +- /// @param _claim The `Claim` at the relative attack position. ++ function absolutePrestate() external view returns (Claim absolutePrestate_); ++ function addLocalData(uint256 _ident, uint256 _execLeafIdx, uint256 _partOffset) external; ++ function anchorStateRegistry() external view returns (IAnchorStateRegistry registry_); + function attack(Claim _disputed, uint256 _parentIndex, Claim _claim) external payable; +- +- /// @notice Defend an agreed upon `Claim`. +- /// @notice _disputed The `Claim` being defended. +- /// @param _parentIndex Index of the claim to defend in the `claimData` array. This must match the `_disputed` +- /// claim. +- /// @param _claim The `Claim` at the relative defense position. ++ function challengeRootL2Block(Types.OutputRootProof memory _outputRootProof, bytes memory _headerRLP) external; ++ function claimCredit(address _recipient) external; ++ function claimData(uint256) + external + view -+ returns (bytes memory, bytes memory, address, uint256, address); -+ function getValidatorGroup(address) ++ returns ( ++ uint32 parentIndex, ++ address counteredBy, ++ address claimant, ++ uint128 bond, ++ Claim claim, ++ Position position, ++ Clock clock ++ ); ++ function claimDataLen() external view returns (uint256 len_); ++ function claims(Hash) external view returns (bool); ++ function clockExtension() external view returns (Duration clockExtension_); ++ function credit(address) external view returns (uint256); + function defend(Claim _disputed, uint256 _parentIndex, Claim _claim) external payable; +- +- /// @notice Perform an instruction step via an on-chain fault proof processor. +- /// @dev This function should point to a fault proof processor in order to execute +- /// a step in the fault proof program on-chain. The interface of the fault proof +- /// processor contract should adhere to the `IBigStepper` interface. +- /// @param _claimIndex The index of the challenged claim within `claimData`. +- /// @param _isAttack Whether or not the step is an attack or a defense. +- /// @param _stateData The stateData of the step is the preimage of the claim at the given +- /// prestate, which is at `_stateIndex` if the move is an attack and `_claimIndex` if +- /// the move is a defense. If the step is an attack on the first instruction, it is +- /// the absolute prestate of the fault proof VM. +- /// @param _proof Proof to access memory nodes in the VM's merkle state tree. +- function step(uint256 _claimIndex, bool _isAttack, bytes calldata _stateData, bytes calldata _proof) external; +- +- /// @notice Posts the requested local data to the VM's `PreimageOralce`. +- /// @param _ident The local identifier of the data to post. +- /// @param _execLeafIdx The index of the leaf claim in an execution subgame that requires the local data for a step. +- /// @param _partOffset The offset of the data to post. +- function addLocalData(uint256 _ident, uint256 _execLeafIdx, uint256 _partOffset) external; +- +- /// @notice Resolves the subgame rooted at the given claim index. `_numToResolve` specifies how many children of +- /// the subgame will be checked in this call. If `_numToResolve` is less than the number of children, an +- /// internal cursor will be updated and this function may be called again to complete resolution of the +- /// subgame. +- /// @dev This function must be called bottom-up in the DAG +- /// A subgame is a tree of claims that has a maximum depth of 1. +- /// A subgame root claims is valid if, and only if, all of its child claims are invalid. +- /// At the deepest level in the DAG, a claim is invalid if there's a successful step against it. +- /// @param _claimIndex The index of the subgame root claim to resolve. +- /// @param _numToResolve The number of subgames to resolve in this call. If the input is `0`, and this is the first +- /// page, this function will attempt to check all of the subgame's children at once. ++ function getChallengerDuration(uint256 _claimIndex) external view returns (Duration duration_); ++ function getNumToResolve(uint256 _claimIndex) external view returns (uint256 numRemainingChildren_); ++ function getRequiredBond(Position _position) external view returns (uint256 requiredBond_); ++ function l2BlockNumber() external pure returns (uint256 l2BlockNumber_); ++ function l2BlockNumberChallenged() external view returns (bool); ++ function l2BlockNumberChallenger() external view returns (address); ++ function l2ChainId() external view returns (uint256 l2ChainId_); ++ function maxClockDuration() external view returns (Duration maxClockDuration_); ++ function maxGameDepth() external view returns (uint256 maxGameDepth_); ++ function move(Claim _disputed, uint256 _challengeIndex, Claim _claim, bool _isAttack) external payable; ++ function resolutionCheckpoints(uint256) + external + view -+ returns (address[] memory, uint256, uint256, uint256, uint256[] memory, uint256, uint256); -+ function getGroupNumMembers(address) external view returns (uint256); -+ function getTopGroupValidators(address, uint256) external view returns (address[] memory); -+ function getGroupsNumMembers(address[] calldata accounts) external view returns (uint256[] memory); -+ function getNumRegisteredValidators() external view returns (uint256); -+ function groupMembershipInEpoch(address, uint256, uint256) external view returns (address); -+ -+ // only registered contract -+ function updateEcdsaPublicKey(address, address, bytes calldata) external returns (bool); -+ function updatePublicKeys( -+ address, -+ address, -+ bytes calldata, -+ bytes calldata, -+ bytes calldata ++ returns (bool initialCheckpointComplete, uint32 subgameIndex, Position leftmostPosition, address counteredBy); + function resolveClaim(uint256 _claimIndex, uint256 _numToResolve) external; +- +- /// @notice Returns the number of children that still need to be resolved in order to fully resolve a subgame rooted +- /// at `_claimIndex`. +- /// @param _claimIndex The subgame root claim's index within `claimData`. +- /// @return numRemainingChildren_ The number of children that still need to be checked to resolve the subgame. +- function getNumToResolve(uint256 _claimIndex) external view returns (uint256 numRemainingChildren_); +- +- /// @notice The l2BlockNumber of the disputed output root in the `L2OutputOracle`. +- function l2BlockNumber() external view returns (uint256 l2BlockNumber_); +- +- /// @notice Starting output root and block number of the game. +- function startingOutputRoot() external view returns (Hash startingRoot_, uint256 l2BlockNumber_); +- +- /// @notice Only the starting block number of the game. ++ function resolvedSubgames(uint256) external view returns (bool); ++ function splitDepth() external view returns (uint256 splitDepth_); + function startingBlockNumber() external view returns (uint256 startingBlockNumber_); ++ function startingOutputRoot() external view returns (Hash root, uint256 l2BlockNumber); ++ function startingRootHash() external view returns (Hash startingRootHash_); ++ function step(uint256 _claimIndex, bool _isAttack, bytes memory _stateData, bytes memory _proof) external; ++ function subgames(uint256, uint256) external view returns (uint256); ++ function version() external view returns (string memory); ++ function vm() external view returns (IBigStepper vm_); ++ function weth() external view returns (IDelayedWETH weth_); +  +- /// @notice Only the starting output root of the game. +- function startingRootHash() external view returns (Hash startingRootHash_); ++ function __constructor__( ++ GameType _gameType, ++ Claim _absolutePrestate, ++ uint256 _maxGameDepth, ++ uint256 _splitDepth, ++ Duration _clockExtension, ++ Duration _maxClockDuration, ++ IBigStepper _vm, ++ IDelayedWETH _weth, ++ IAnchorStateRegistry _anchorStateRegistry, ++ uint256 _l2ChainId + ) -+ external -+ returns (bool); -+ function getValidatorLockedGoldRequirements() external view returns (uint256, uint256); -+ function getGroupLockedGoldRequirements() external view returns (uint256, uint256); -+ function getRegisteredValidators() external view returns (address[] memory); -+ function getRegisteredValidatorSigners() external view returns (address[] memory); -+ function getRegisteredValidatorGroups() external view returns (address[] memory); -+ function isValidatorGroup(address) external view returns (bool); -+ function isValidator(address) external view returns (bool); -+ function getValidatorGroupSlashingMultiplier(address) external view returns (uint256); -+ function getMembershipInLastEpoch(address) external view returns (address); -+ function getMembershipInLastEpochFromSigner(address) external view returns (address); -+ -+ // only VM -+ function updateValidatorScoreFromSigner(address, uint256) external; -+ function distributeEpochPaymentsFromSigner(address, uint256) external returns (uint256); -+ -+ // only slasher -+ function forceDeaffiliateIfValidator(address) external; -+ function halveSlashingMultiplier(address) external; -+}
++ external; + }
+ + + +
+ + +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+0
+
-4
+ +
+ +
+
+
diff --git OP/packages/contracts-bedrock/src/dispute/interfaces/IInitializable.sol CELO/packages/contracts-bedrock/src/dispute/interfaces/IInitializable.sol +index 5968b45f9bfb5b2eb0643708ec59a6a94fa8d064..a3bb74b82f3a6959d5c8385e05ec61334f1e2b4a 100644 +--- OP/packages/contracts-bedrock/src/dispute/interfaces/IInitializable.sol ++++ CELO/packages/contracts-bedrock/src/dispute/interfaces/IInitializable.sol +@@ -1,10 +1,6 @@ + // SPDX-License-Identifier: MIT + pragma solidity ^0.8.0; +  +-/// @title IInitializable +-/// @notice An interface for initializable contracts. + interface IInitializable { +- /// @notice Initializes the contract. +- /// @dev This function may only be called once. + function initialize() external payable; + }
@@ -31837,7 +134283,7 @@
@@ -31847,53 +134293,155 @@
-
+35
+
+137
-0
-
diff --git OP/packages/contracts-bedrock/src/celo/identity/interfaces/IAttestations.sol CELO/packages/contracts-bedrock/src/celo/identity/interfaces/IAttestations.sol +
diff --git OP/packages/contracts-bedrock/src/dispute/interfaces/IPermissionedDisputeGame.sol CELO/packages/contracts-bedrock/src/dispute/interfaces/IPermissionedDisputeGame.sol new file mode 100644 -index 0000000000000000000000000000000000000000..5c1a1d7a8f484e1cedc6336b39144ceea0941c97 +index 0000000000000000000000000000000000000000..5fda4e9163b25cff8058ab46c9c6df1b49676d95 --- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/identity/interfaces/IAttestations.sol -@@ -0,0 +1,35 @@ -+// SPDX-License-Identifier: LGPL-3.0-only -+pragma solidity ^0.8.15; ++++ CELO/packages/contracts-bedrock/src/dispute/interfaces/IPermissionedDisputeGame.sol +@@ -0,0 +1,137 @@ ++// SPDX-License-Identifier: MIT ++pragma solidity ^0.8.0; + -+interface IAttestations { -+ function revoke(bytes32, uint256) external; -+ function withdraw(address) external; ++import { Types } from "src/libraries/Types.sol"; ++import "src/dispute/lib/Types.sol"; ++ ++import { IAnchorStateRegistry } from "src/dispute/interfaces/IAnchorStateRegistry.sol"; ++import { IDelayedWETH } from "src/dispute/interfaces/IDelayedWETH.sol"; ++import { IBigStepper } from "src/dispute/interfaces/IBigStepper.sol"; ++import { IDisputeGame } from "src/dispute/interfaces/IDisputeGame.sol"; ++ ++interface IPermissionedDisputeGame is IDisputeGame { ++ struct ClaimData { ++ uint32 parentIndex; ++ address counteredBy; ++ address claimant; ++ uint128 bond; ++ Claim claim; ++ Position position; ++ Clock clock; ++ } + -+ // view functions -+ function getUnselectedRequest(bytes32, address) external view returns (uint32, uint32, address); -+ function getAttestationIssuers(bytes32, address) external view returns (address[] memory); -+ function getAttestationStats(bytes32, address) external view returns (uint32, uint32); -+ function batchGetAttestationStats(bytes32[] calldata) ++ struct ResolutionCheckpoint { ++ bool initialCheckpointComplete; ++ uint32 subgameIndex; ++ Position leftmostPosition; ++ address counteredBy; ++ } ++ ++ error AlreadyInitialized(); ++ error AnchorRootNotFound(); ++ error BlockNumberMatches(); ++ error BondTransferFailed(); ++ error CannotDefendRootClaim(); ++ error ClaimAboveSplit(); ++ error ClaimAlreadyExists(); ++ error ClaimAlreadyResolved(); ++ error ClockNotExpired(); ++ error ClockTimeExceeded(); ++ error ContentLengthMismatch(); ++ error DuplicateStep(); ++ error EmptyItem(); ++ error GameDepthExceeded(); ++ error GameNotInProgress(); ++ error IncorrectBondAmount(); ++ error InvalidChallengePeriod(); ++ error InvalidClockExtension(); ++ error InvalidDataRemainder(); ++ error InvalidDisputedClaimIndex(); ++ error InvalidHeader(); ++ error InvalidHeaderRLP(); ++ error InvalidLocalIdent(); ++ error InvalidOutputRootProof(); ++ error InvalidParent(); ++ error InvalidPrestate(); ++ error InvalidSplitDepth(); ++ error L2BlockNumberChallenged(); ++ error MaxDepthTooLarge(); ++ error NoCreditToClaim(); ++ error OutOfOrderResolution(); ++ error UnexpectedList(); ++ error UnexpectedRootClaim(Claim rootClaim); ++ error UnexpectedString(); ++ error ValidStep(); ++ ++ event Move(uint256 indexed parentIndex, Claim indexed claim, address indexed claimant); ++ ++ function absolutePrestate() external view returns (Claim absolutePrestate_); ++ function addLocalData(uint256 _ident, uint256 _execLeafIdx, uint256 _partOffset) external; ++ function anchorStateRegistry() external view returns (IAnchorStateRegistry registry_); ++ function attack(Claim _disputed, uint256 _parentIndex, Claim _claim) external payable; ++ function challengeRootL2Block(Types.OutputRootProof memory _outputRootProof, bytes memory _headerRLP) external; ++ function claimCredit(address _recipient) external; ++ function claimData(uint256) + external + view -+ returns (uint256[] memory, address[] memory, uint64[] memory, uint64[] memory); -+ function getAttestationState(bytes32, address, address) external view returns (uint8, uint32, address); -+ function getCompletableAttestations( -+ bytes32, -+ address -+ ) ++ returns ( ++ uint32 parentIndex, ++ address counteredBy, ++ address claimant, ++ uint128 bond, ++ Claim claim, ++ Position position, ++ Clock clock ++ ); ++ function claimDataLen() external view returns (uint256 len_); ++ function claims(Hash) external view returns (bool); ++ function clockExtension() external view returns (Duration clockExtension_); ++ function credit(address) external view returns (uint256); ++ function defend(Claim _disputed, uint256 _parentIndex, Claim _claim) external payable; ++ function getChallengerDuration(uint256 _claimIndex) external view returns (Duration duration_); ++ function getNumToResolve(uint256 _claimIndex) external view returns (uint256 numRemainingChildren_); ++ function getRequiredBond(Position _position) external view returns (uint256 requiredBond_); ++ function l2BlockNumber() external pure returns (uint256 l2BlockNumber_); ++ function l2BlockNumberChallenged() external view returns (bool); ++ function l2BlockNumberChallenger() external view returns (address); ++ function l2ChainId() external view returns (uint256 l2ChainId_); ++ function maxClockDuration() external view returns (Duration maxClockDuration_); ++ function maxGameDepth() external view returns (uint256 maxGameDepth_); ++ function move(Claim _disputed, uint256 _challengeIndex, Claim _claim, bool _isAttack) external payable; ++ function resolutionCheckpoints(uint256) + external + view -+ returns (uint32[] memory, address[] memory, uint256[] memory, bytes memory); -+ function getAttestationRequestFee(address) external view returns (uint256); -+ function getMaxAttestations() external view returns (uint256); -+ function validateAttestationCode(bytes32, address, uint8, bytes32, bytes32) external view returns (address); -+ function lookupAccountsForIdentifier(bytes32) external view returns (address[] memory); -+ function requireNAttestationsRequested(bytes32, address, uint32) external view; -+ -+ // only owner -+ function setAttestationRequestFee(address, uint256) external; -+ function setAttestationExpiryBlocks(uint256) external; -+ function setSelectIssuersWaitBlocks(uint256) external; -+ function setMaxAttestations(uint256) external; ++ returns (bool initialCheckpointComplete, uint32 subgameIndex, Position leftmostPosition, address counteredBy); ++ function resolveClaim(uint256 _claimIndex, uint256 _numToResolve) external; ++ function resolvedSubgames(uint256) external view returns (bool); ++ function splitDepth() external view returns (uint256 splitDepth_); ++ function startingBlockNumber() external view returns (uint256 startingBlockNumber_); ++ function startingOutputRoot() external view returns (Hash root, uint256 l2BlockNumber); ++ function startingRootHash() external view returns (Hash startingRootHash_); ++ function step(uint256 _claimIndex, bool _isAttack, bytes memory _stateData, bytes memory _proof) external; ++ function subgames(uint256, uint256) external view returns (uint256); ++ function version() external view returns (string memory); ++ function vm() external view returns (IBigStepper vm_); ++ function weth() external view returns (IDelayedWETH weth_); ++ ++ error BadAuth(); ++ ++ function proposer() external view returns (address proposer_); ++ function challenger() external view returns (address challenger_); ++ ++ function __constructor__( ++ GameType _gameType, ++ Claim _absolutePrestate, ++ uint256 _maxGameDepth, ++ uint256 _splitDepth, ++ Duration _clockExtension, ++ Duration _maxClockDuration, ++ IBigStepper _vm, ++ IDelayedWETH _weth, ++ IAnchorStateRegistry _anchorStateRegistry, ++ uint256 _l2ChainId, ++ address _proposer, ++ address _challenger ++ ) ++ external; +}
@@ -31901,9 +134449,9 @@
@@ -31918,7 +134466,7 @@
@@ -31928,57 +134476,70 @@
-
+39
+
+52
-0
-
diff --git OP/packages/contracts-bedrock/src/celo/identity/interfaces/IEscrow.sol CELO/packages/contracts-bedrock/src/celo/identity/interfaces/IEscrow.sol +
diff --git OP/packages/contracts-bedrock/src/governance/interfaces/IGovernanceToken.sol CELO/packages/contracts-bedrock/src/governance/interfaces/IGovernanceToken.sol new file mode 100644 -index 0000000000000000000000000000000000000000..87c145a4a1bb9bf3aa469bb8ec5ca6e92073525f +index 0000000000000000000000000000000000000000..04a0490adc9b23b08b02915eefbf5ddbb388d861 --- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/identity/interfaces/IEscrow.sol -@@ -0,0 +1,39 @@ ++++ CELO/packages/contracts-bedrock/src/governance/interfaces/IGovernanceToken.sol +@@ -0,0 +1,52 @@ +// SPDX-License-Identifier: MIT -+pragma solidity ^0.8.15; ++pragma solidity ^0.8.0; + -+interface IEscrow { -+ function transfer( -+ bytes32 identifier, -+ address token, -+ uint256 value, -+ uint256 expirySeconds, -+ address paymentId, -+ uint256 minAttestations -+ ) -+ external -+ returns (bool); -+ function transferWithTrustedIssuers( -+ bytes32 identifier, -+ address token, ++import { ERC20Votes } from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol"; ++ ++interface IGovernanceToken { ++ event Approval(address indexed owner, address indexed spender, uint256 value); ++ event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate); ++ event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance); ++ event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); ++ event Transfer(address indexed from, address indexed to, uint256 value); ++ ++ function DOMAIN_SEPARATOR() external view returns (bytes32); ++ function allowance(address owner, address spender) external view returns (uint256); ++ function approve(address spender, uint256 amount) external returns (bool); ++ function balanceOf(address account) external view returns (uint256); ++ function burn(uint256 amount) external; ++ function burnFrom(address account, uint256 amount) external; ++ function checkpoints(address account, uint32 pos) external view returns (ERC20Votes.Checkpoint memory); ++ function decimals() external view returns (uint8); ++ function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool); ++ function delegate(address delegatee) external; ++ function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external; ++ function delegates(address account) external view returns (address); ++ function getPastTotalSupply(uint256 blockNumber) external view returns (uint256); ++ function getPastVotes(address account, uint256 blockNumber) external view returns (uint256); ++ function getVotes(address account) external view returns (uint256); ++ function increaseAllowance(address spender, uint256 addedValue) external returns (bool); ++ function mint(address _account, uint256 _amount) external; ++ function name() external view returns (string memory); ++ function nonces(address owner) external view returns (uint256); ++ function numCheckpoints(address account) external view returns (uint32); ++ function owner() external view returns (address); ++ function permit( ++ address owner, ++ address spender, + uint256 value, -+ uint256 expirySeconds, -+ address paymentId, -+ uint256 minAttestations, -+ address[] calldata trustedIssuers ++ uint256 deadline, ++ uint8 v, ++ bytes32 r, ++ bytes32 s + ) -+ external -+ returns (bool); -+ function withdraw(address paymentID, uint8 v, bytes32 r, bytes32 s) external returns (bool); -+ function revoke(address paymentID) external returns (bool); -+ -+ // view functions -+ function getReceivedPaymentIds(bytes32 identifier) external view returns (address[] memory); -+ function getSentPaymentIds(address sender) external view returns (address[] memory); -+ function getTrustedIssuersPerPayment(address paymentId) external view returns (address[] memory); -+ function getDefaultTrustedIssuers() external view returns (address[] memory); -+ function MAX_TRUSTED_ISSUERS_PER_PAYMENT() external view returns (uint256); ++ external; ++ function renounceOwnership() external; ++ function symbol() external view returns (string memory); ++ function totalSupply() external view returns (uint256); ++ function transfer(address to, uint256 amount) external returns (bool); ++ function transferFrom(address from, address to, uint256 amount) external returns (bool); ++ function transferOwnership(address newOwner) external; + -+ // onlyOwner functions -+ function addDefaultTrustedIssuer(address trustedIssuer) external; -+ function removeDefaultTrustedIssuer(address trustedIssuer, uint256 index) external; ++ function __constructor__() external; +}
@@ -31986,9 +134547,9 @@
@@ -32003,7 +134564,7 @@
@@ -32013,80 +134574,39 @@
-
+62
+
+21
-0
-
diff --git OP/packages/contracts-bedrock/src/celo/identity/interfaces/IFederatedAttestations.sol CELO/packages/contracts-bedrock/src/celo/identity/interfaces/IFederatedAttestations.sol +
diff --git OP/packages/contracts-bedrock/src/governance/interfaces/IMintManager.sol CELO/packages/contracts-bedrock/src/governance/interfaces/IMintManager.sol new file mode 100644 -index 0000000000000000000000000000000000000000..c0586eb9e44dc7a10fdd0e86de09a7753c6e4974 +index 0000000000000000000000000000000000000000..e769f3042e5372a1114e13fe4763318d839d49a2 --- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/identity/interfaces/IFederatedAttestations.sol -@@ -0,0 +1,62 @@ ++++ CELO/packages/contracts-bedrock/src/governance/interfaces/IMintManager.sol +@@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT -+pragma solidity ^0.8.15; ++pragma solidity ^0.8.0; + -+interface IFederatedAttestations { -+ function registerAttestationAsIssuer(bytes32 identifier, address account, uint64 issuedOn) external; -+ function registerAttestation( -+ bytes32 identifier, -+ address issuer, -+ address account, -+ address signer, -+ uint64 issuedOn, -+ uint8 v, -+ bytes32 r, -+ bytes32 s -+ ) -+ external; -+ function revokeAttestation(bytes32 identifier, address issuer, address account) external; -+ function batchRevokeAttestations( -+ address issuer, -+ bytes32[] calldata identifiers, -+ address[] calldata accounts -+ ) -+ external; ++import { IGovernanceToken } from "src/governance/interfaces/IGovernanceToken.sol"; + -+ // view functions -+ function lookupAttestations( -+ bytes32 identifier, -+ address[] calldata trustedIssuers -+ ) -+ external -+ view -+ returns (uint256[] memory, address[] memory, address[] memory, uint64[] memory, uint64[] memory); -+ function lookupIdentifiers( -+ address account, -+ address[] calldata trustedIssuers -+ ) -+ external -+ view -+ returns (uint256[] memory, bytes32[] memory); -+ function validateAttestationSig( -+ bytes32 identifier, -+ address issuer, -+ address account, -+ address signer, -+ uint64 issuedOn, -+ uint8 v, -+ bytes32 r, -+ bytes32 s -+ ) -+ external -+ view; -+ function getUniqueAttestationHash( -+ bytes32 identifier, -+ address issuer, -+ address account, -+ address signer, -+ uint64 issuedOn -+ ) -+ external -+ pure -+ returns (bytes32); ++interface IMintManager { ++ event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); ++ ++ function DENOMINATOR() external view returns (uint256); ++ function MINT_CAP() external view returns (uint256); ++ function MINT_PERIOD() external view returns (uint256); ++ function governanceToken() external view returns (IGovernanceToken); ++ function mint(address _account, uint256 _amount) external; ++ function mintPermittedAfter() external view returns (uint256); ++ function owner() external view returns (address); ++ function renounceOwnership() external; ++ function transferOwnership(address newOwner) external; ++ function upgrade(address _newMintManager) external; ++ ++ function __constructor__(address _upgrader, address _governanceToken) external; +}
@@ -32094,9 +134614,9 @@
@@ -32105,13 +134625,13 @@
- (new) + OP
@@ -32121,35 +134641,35 @@
-
+7
-
-0
+
+1
+
-1
-
diff --git OP/packages/contracts-bedrock/src/celo/identity/interfaces/IOdisPayments.sol CELO/packages/contracts-bedrock/src/celo/identity/interfaces/IOdisPayments.sol -new file mode 100644 -index 0000000000000000000000000000000000000000..ca188432c0dda414dfa563d857cccc600947de9e ---- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/identity/interfaces/IOdisPayments.sol -@@ -0,0 +1,7 @@ -+// SPDX-License-Identifier: MIT -+pragma solidity ^0.8.15; -+ -+interface IOdisPayments { -+ function payInCUSD(address account, uint256 value) external; -+ function totalPaidCUSD(address) external view returns (uint256); -+}
+
diff --git OP/packages/contracts-bedrock/src/legacy/interfaces/IDeployerWhitelist.sol CELO/packages/contracts-bedrock/src/legacy/interfaces/IDeployerWhitelist.sol +index 6914eefabb3df4f5bdb7806626e6adb70cd58946..050748f1786e8bca368a4192ba890763a1b1d95a 100644 +--- OP/packages/contracts-bedrock/src/legacy/interfaces/IDeployerWhitelist.sol ++++ CELO/packages/contracts-bedrock/src/legacy/interfaces/IDeployerWhitelist.sol +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: MIT + pragma solidity ^0.8.0; +  +-import { ISemver } from "src/universal/ISemver.sol"; ++import { ISemver } from "src/universal/interfaces/ISemver.sol"; +  + /// @title IDeployerWhitelist + /// @notice Interface for the DeployerWhitelist contract.
@@ -32158,13 +134678,13 @@
- (new) + OP
@@ -32174,37 +134694,35 @@
-
+9
-
-0
+
+1
+
-1
-
diff --git OP/packages/contracts-bedrock/src/celo/identity/interfaces/IRandom.sol CELO/packages/contracts-bedrock/src/celo/identity/interfaces/IRandom.sol -new file mode 100644 -index 0000000000000000000000000000000000000000..65cf3082d685cd4a5a9a2e38d8254e85de1bb2e5 ---- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/identity/interfaces/IRandom.sol -@@ -0,0 +1,9 @@ -+// SPDX-License-Identifier: LGPL-3.0-only -+pragma solidity ^0.8.15; -+ -+interface IRandom { -+ function revealAndCommit(bytes32, bytes32, address) external; -+ function randomnessBlockRetentionWindow() external view returns (uint256); -+ function random() external view returns (bytes32); -+ function getBlockRandomness(uint256) external view returns (bytes32); -+}
+
diff --git OP/packages/contracts-bedrock/src/legacy/interfaces/IL1BlockNumber.sol CELO/packages/contracts-bedrock/src/legacy/interfaces/IL1BlockNumber.sol +index 1b59b53e396fff6945de3c086fc472fa6d047381..7634cc67c69062ab2d584ecc78c6878af6703fb8 100644 +--- OP/packages/contracts-bedrock/src/legacy/interfaces/IL1BlockNumber.sol ++++ CELO/packages/contracts-bedrock/src/legacy/interfaces/IL1BlockNumber.sol +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: MIT + pragma solidity ^0.8.0; +  +-import { ISemver } from "src/universal/ISemver.sol"; ++import { ISemver } from "src/universal/interfaces/ISemver.sol"; +  + /// @title IL1BlockNumber + /// @notice Interface for the L1BlockNumber contract.
@@ -32213,13 +134731,13 @@
- (new) + OP
@@ -32229,76 +134747,35 @@
-
+48
+
+2
-0
-
diff --git OP/packages/contracts-bedrock/src/celo/interfaces/IAccounts.sol CELO/packages/contracts-bedrock/src/celo/interfaces/IAccounts.sol -new file mode 100644 -index 0000000000000000000000000000000000000000..734dcddeb941d89c467af92a24ba0a488df4ab57 ---- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/interfaces/IAccounts.sol -@@ -0,0 +1,48 @@ -+// SPDX-License-Identifier: LGPL-3.0-only -+pragma solidity ^0.8.15; -+ -+interface IAccounts { -+ function isAccount(address) external view returns (bool); -+ function voteSignerToAccount(address) external view returns (address); -+ function validatorSignerToAccount(address) external view returns (address); -+ function attestationSignerToAccount(address) external view returns (address); -+ function signerToAccount(address) external view returns (address); -+ function getAttestationSigner(address) external view returns (address); -+ function getValidatorSigner(address) external view returns (address); -+ function getVoteSigner(address) external view returns (address); -+ function hasAuthorizedVoteSigner(address) external view returns (bool); -+ function hasAuthorizedValidatorSigner(address) external view returns (bool); -+ function hasAuthorizedAttestationSigner(address) external view returns (bool); -+ -+ function setAccountDataEncryptionKey(bytes calldata) external; -+ function setMetadataURL(string calldata) external; -+ function setName(string calldata) external; -+ function setWalletAddress(address, uint8, bytes32, bytes32) external; -+ function setAccount(string calldata, bytes calldata, address, uint8, bytes32, bytes32) external; -+ -+ function getDataEncryptionKey(address) external view returns (bytes memory); -+ function getWalletAddress(address) external view returns (address); -+ function getMetadataURL(address) external view returns (string memory); -+ function batchGetMetadataURL(address[] calldata) external view returns (uint256[] memory, bytes memory); -+ function getName(address) external view returns (string memory); -+ -+ function authorizeVoteSigner(address, uint8, bytes32, bytes32) external; -+ function authorizeValidatorSigner(address, uint8, bytes32, bytes32) external; -+ function authorizeValidatorSignerWithPublicKey(address, uint8, bytes32, bytes32, bytes calldata) external; -+ function authorizeValidatorSignerWithKeys( -+ address, -+ uint8, -+ bytes32, -+ bytes32, -+ bytes calldata, -+ bytes calldata, -+ bytes calldata -+ ) -+ external; -+ function authorizeAttestationSigner(address, uint8, bytes32, bytes32) external; -+ function createAccount() external returns (bool); -+ -+ function setPaymentDelegation(address, uint256) external; -+ function getPaymentDelegation(address) external view returns (address, uint256); -+ function isSigner(address, address, bytes32) external view returns (bool); -+}
+
diff --git OP/packages/contracts-bedrock/src/legacy/interfaces/IL1ChugSplashProxy.sol CELO/packages/contracts-bedrock/src/legacy/interfaces/IL1ChugSplashProxy.sol +index f4ca59fb551136cbf42394b14d794d36f4457d7c..863c89906751b48e1bc854e9bb355b3c2ac7854a 100644 +--- OP/packages/contracts-bedrock/src/legacy/interfaces/IL1ChugSplashProxy.sol ++++ CELO/packages/contracts-bedrock/src/legacy/interfaces/IL1ChugSplashProxy.sol +@@ -13,6 +13,8 @@ function getOwner() external returns (address); + function setCode(bytes memory _code) external; + function setOwner(address _owner) external; + function setStorage(bytes32 _key, bytes32 _value) external; ++ ++ function __constructor__(address _owner) external; + } +  + /// @title IStaticL1ChugSplashProxy
@@ -32307,13 +134784,13 @@
- (new) + OP
@@ -32323,39 +134800,35 @@
-
+11
-
-0
+
+1
+
-1
-
diff --git OP/packages/contracts-bedrock/src/celo/interfaces/ICeloRegistry.sol CELO/packages/contracts-bedrock/src/celo/interfaces/ICeloRegistry.sol -new file mode 100644 -index 0000000000000000000000000000000000000000..95e586da3954ffc48f18c7e781161990abab7936 ---- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/interfaces/ICeloRegistry.sol -@@ -0,0 +1,11 @@ -+// SPDX-License-Identifier: LGPL-3.0-only -+pragma solidity ^0.8.15; -+ -+interface ICeloRegistry { -+ function setAddressFor(string calldata, address) external; -+ function getAddressForOrDie(bytes32) external view returns (address); -+ function getAddressFor(bytes32) external view returns (address); -+ function getAddressForStringOrDie(string calldata identifier) external view returns (address); -+ function getAddressForString(string calldata identifier) external view returns (address); -+ function isOneOf(bytes32[] calldata, address) external view returns (bool); -+}
+
diff --git OP/packages/contracts-bedrock/src/legacy/interfaces/ILegacyMessagePasser.sol CELO/packages/contracts-bedrock/src/legacy/interfaces/ILegacyMessagePasser.sol +index 79e03871f23654dc3096b5c54b91bbfc21213397..a5fde0fdb65dec4f9d0d3483b24a031a84ddc565 100644 +--- OP/packages/contracts-bedrock/src/legacy/interfaces/ILegacyMessagePasser.sol ++++ CELO/packages/contracts-bedrock/src/legacy/interfaces/ILegacyMessagePasser.sol +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: MIT + pragma solidity ^0.8.0; +  +-import { ISemver } from "src/universal/ISemver.sol"; ++import { ISemver } from "src/universal/interfaces/ISemver.sol"; +  + /// @title ILegacyMessagePasser + /// @notice Interface for the LegacyMessagePasser contract.
@@ -32364,13 +134837,13 @@
- (new) + OP
@@ -32380,42 +134853,46 @@
-
+14
-
-0
+
+3
+
-3
-
diff --git OP/packages/contracts-bedrock/src/celo/interfaces/ICeloToken.sol CELO/packages/contracts-bedrock/src/celo/interfaces/ICeloToken.sol -new file mode 100644 -index 0000000000000000000000000000000000000000..5bf2033f31726110e6504078561108cfee40a42d ---- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/interfaces/ICeloToken.sol -@@ -0,0 +1,14 @@ -+// SPDX-License-Identifier: LGPL-3.0-only -+pragma solidity ^0.8.15; -+ -+/** -+ * @title This interface describes the non- ERC20 shared interface for all Celo Tokens, and -+ * in the absence of interface inheritance is intended as a companion to IERC20.sol. -+ */ -+interface ICeloToken { -+ function transferWithComment(address, uint256, string calldata) external returns (bool); -+ function name() external view returns (string memory); -+ function symbol() external view returns (string memory); -+ function decimals() external view returns (uint8); -+ function burn(uint256 value) external returns (bool); -+}
+
diff --git OP/packages/contracts-bedrock/src/periphery/op-nft/AttestationStation.sol CELO/packages/contracts-bedrock/src/periphery/op-nft/AttestationStation.sol +index b9af730a71d4a8b4f12e5d11b09d6d1e50ffaba7..4d15862d43580c1293b6ebd0c2577926b057a732 100644 +--- OP/packages/contracts-bedrock/src/periphery/op-nft/AttestationStation.sol ++++ CELO/packages/contracts-bedrock/src/periphery/op-nft/AttestationStation.sol +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: MIT + pragma solidity 0.8.15; +  +-import { ISemver } from "src/universal/ISemver.sol"; ++import { ISemver } from "src/universal/interfaces/ISemver.sol"; +  + /// @title AttestationStation + /// @author Optimism Collective +@@ -29,8 +29,8 @@ /// @param val Value of the attestation. + event AttestationCreated(address indexed creator, address indexed about, bytes32 indexed key, bytes val); +  + /// @notice Semantic version. +- /// @custom:semver 1.2.0 +- string public constant version = "1.2.0"; ++ /// @custom:semver 1.2.1-beta.1 ++ string public constant version = "1.2.1-beta.1"; +  + /// @notice Allows anyone to create an attestation. + /// @param _about Address that the attestation is about.
@@ -32424,13 +134901,13 @@
- (new) + OP
@@ -32440,41 +134917,46 @@
-
+13
-
-0
+
+3
+
-3
-
diff --git OP/packages/contracts-bedrock/src/celo/interfaces/ICeloVersionedContract.sol CELO/packages/contracts-bedrock/src/celo/interfaces/ICeloVersionedContract.sol -new file mode 100644 -index 0000000000000000000000000000000000000000..37b1538c2a121b4dd73b5762db9ba4a97364581c ---- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/interfaces/ICeloVersionedContract.sol -@@ -0,0 +1,13 @@ -+// SPDX-License-Identifier: LGPL-3.0-only -+pragma solidity ^0.8.15; -+ -+interface ICeloVersionedContract { -+ /** -+ * @notice Returns the storage, major, minor, and patch version of the contract. -+ * @return Storage version of the contract. -+ * @return Major version of the contract. -+ * @return Minor version of the contract. -+ * @return Patch version of the contract. -+ */ -+ function getVersionNumber() external pure returns (uint256, uint256, uint256, uint256); -+}
+
diff --git OP/packages/contracts-bedrock/src/periphery/op-nft/Optimist.sol CELO/packages/contracts-bedrock/src/periphery/op-nft/Optimist.sol +index 74d04b087d865f9191d438657222505703e764d3..b15c0f00044c6cdf4bb3ed5e61525cc3c7ff2f9e 100644 +--- OP/packages/contracts-bedrock/src/periphery/op-nft/Optimist.sol ++++ CELO/packages/contracts-bedrock/src/periphery/op-nft/Optimist.sol +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: MIT + pragma solidity 0.8.15; +  +-import { ISemver } from "src/universal/ISemver.sol"; ++import { ISemver } from "src/universal/interfaces/ISemver.sol"; + import { ERC721BurnableUpgradeable } from + "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721BurnableUpgradeable.sol"; + import { AttestationStation } from "src/periphery/op-nft/AttestationStation.sol"; +@@ -26,8 +26,8 @@ /// @notice Address of the OptimistAllowlist contract. + OptimistAllowlist public immutable OPTIMIST_ALLOWLIST; +  + /// @notice Semantic version. +- /// @custom:semver 2.1.0 +- string public constant version = "2.1.0"; ++ /// @custom:semver 2.1.1-beta.1 ++ string public constant version = "2.1.1-beta.1"; +  + /// @param _name Token name. + /// @param _symbol Token symbol.
@@ -32483,13 +134965,13 @@
- (new) + OP
@@ -32499,57 +134981,110 @@
-
+29
-
-0
+
+3
+
-3
-
diff --git OP/packages/contracts-bedrock/src/celo/interfaces/IFeeCurrencyDirectory.sol CELO/packages/contracts-bedrock/src/celo/interfaces/IFeeCurrencyDirectory.sol -new file mode 100644 -index 0000000000000000000000000000000000000000..5c6ab9051ccf28eebd9f8482ae22b9e9df8e939f ---- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/interfaces/IFeeCurrencyDirectory.sol -@@ -0,0 +1,29 @@ -+// SPDX-License-Identifier: MIT -+pragma solidity ^0.8.0; -+ -+interface IFeeCurrencyDirectory { -+ struct CurrencyConfig { -+ address oracle; -+ uint256 intrinsicGas; -+ } -+ -+ /** -+ * @notice Returns the list of all currency addresses. -+ * @return An array of addresses. -+ */ -+ function getCurrencies() external view returns (address[] memory); -+ /** -+ * @notice Returns the configuration for a currency. -+ * @param token The address of the token. -+ * @return Currency configuration of the token. -+ */ -+ function getCurrencyConfig(address token) external view returns (CurrencyConfig memory); -+ -+ /** -+ * @notice Retrieves exchange rate between token and CELO. -+ * @param token The token address whose price is to be fetched. -+ * @return numerator The exchange rate numerator. -+ * @return denominator The exchange rate denominator. -+ */ -+ function getExchangeRate(address token) external view returns (uint256 numerator, uint256 denominator); -+}
+
diff --git OP/packages/contracts-bedrock/src/periphery/op-nft/OptimistAllowlist.sol CELO/packages/contracts-bedrock/src/periphery/op-nft/OptimistAllowlist.sol +index b8212a37c67442e4ef94477005aa4c59441c966e..ffa46116a4c59a846f2abaf09c539490723b37e8 100644 +--- OP/packages/contracts-bedrock/src/periphery/op-nft/OptimistAllowlist.sol ++++ CELO/packages/contracts-bedrock/src/periphery/op-nft/OptimistAllowlist.sol +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: MIT + pragma solidity 0.8.15; +  +-import { ISemver } from "src/universal/ISemver.sol"; ++import { ISemver } from "src/universal/interfaces/ISemver.sol"; + import { AttestationStation } from "src/periphery/op-nft/AttestationStation.sol"; + import { OptimistConstants } from "src/periphery/op-nft/libraries/OptimistConstants.sol"; +  +@@ -31,8 +31,8 @@ /// attestations. + address public immutable OPTIMIST_INVITER; +  + /// @notice Semantic version. +- /// @custom:semver 1.1.0 +- string public constant version = "1.1.0"; ++ /// @custom:semver 1.1.1-beta.1 ++ string public constant version = "1.1.1-beta.1"; +  + /// @param _attestationStation Address of the AttestationStation contract. + /// @param _allowlistAttestor Address of the allowlist attestor.
+ +
+
+
+ + OP + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+3
+
-3
+ +
+ +
+
+
diff --git OP/packages/contracts-bedrock/src/periphery/op-nft/OptimistInviter.sol CELO/packages/contracts-bedrock/src/periphery/op-nft/OptimistInviter.sol +index 222405d77c33626ffc1896e8a0608f6a70a34b93..ae0ab9d92657c1e0bf69d579398bd609420bfa53 100644 +--- OP/packages/contracts-bedrock/src/periphery/op-nft/OptimistInviter.sol ++++ CELO/packages/contracts-bedrock/src/periphery/op-nft/OptimistInviter.sol +@@ -2,7 +2,7 @@ // SPDX-License-Identifier: MIT + pragma solidity 0.8.15; +  + import { OptimistConstants } from "src/periphery/op-nft/libraries/OptimistConstants.sol"; +-import { ISemver } from "src/universal/ISemver.sol"; ++import { ISemver } from "src/universal/interfaces/ISemver.sol"; + import { AttestationStation } from "src/periphery/op-nft/AttestationStation.sol"; + import { SignatureChecker } from "@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol"; + import { EIP712Upgradeable } from "@openzeppelin/contracts-upgradeable/utils/cryptography/draft-EIP712Upgradeable.sol"; +@@ -88,8 +88,8 @@ /// @notice Maps from addresses to number of invites they have. + mapping(address => uint256) public inviteCounts; +  + /// @notice Semantic version. +- /// @custom:semver 1.1.0 +- string public constant version = "1.1.0"; ++ /// @custom:semver 1.1.1-beta.1 ++ string public constant version = "1.1.1-beta.1"; +  + /// @param _inviteGranter Address of the invite granter. + /// @param _attestationStation Address of the AttestationStation contract.
+
+ + +
+ @@ -32564,7 +135099,7 @@
@@ -32574,24 +135109,56 @@
-
+6
+
+38
-0
-
diff --git OP/packages/contracts-bedrock/src/celo/interfaces/IFreezer.sol CELO/packages/contracts-bedrock/src/celo/interfaces/IFreezer.sol +
diff --git OP/packages/contracts-bedrock/src/universal/interfaces/ICrossDomainMessenger.sol CELO/packages/contracts-bedrock/src/universal/interfaces/ICrossDomainMessenger.sol new file mode 100644 -index 0000000000000000000000000000000000000000..a629b3325a5ba883298aa61d85f260573fe042a8 +index 0000000000000000000000000000000000000000..ed2fb20ea453c1e2ff29322718670edfcd954916 --- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/interfaces/IFreezer.sol -@@ -0,0 +1,6 @@ -+// SPDX-License-Identifier: LGPL-3.0-only -+pragma solidity ^0.8.15; ++++ CELO/packages/contracts-bedrock/src/universal/interfaces/ICrossDomainMessenger.sol +@@ -0,0 +1,38 @@ ++// SPDX-License-Identifier: MIT ++pragma solidity ^0.8.0; + -+interface IFreezer { -+ function isFrozen(address) external view returns (bool); ++interface ICrossDomainMessenger { ++ event FailedRelayedMessage(bytes32 indexed msgHash); ++ event Initialized(uint8 version); ++ event RelayedMessage(bytes32 indexed msgHash); ++ event SentMessage(address indexed target, address sender, bytes message, uint256 messageNonce, uint256 gasLimit); ++ event SentMessageExtension1(address indexed sender, uint256 value); ++ ++ function MESSAGE_VERSION() external view returns (uint16); ++ function MIN_GAS_CALLDATA_OVERHEAD() external view returns (uint64); ++ function MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR() external view returns (uint64); ++ function MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR() external view returns (uint64); ++ function OTHER_MESSENGER() external view returns (ICrossDomainMessenger); ++ function RELAY_CALL_OVERHEAD() external view returns (uint64); ++ function RELAY_CONSTANT_OVERHEAD() external view returns (uint64); ++ function RELAY_GAS_CHECK_BUFFER() external view returns (uint64); ++ function RELAY_RESERVED_GAS() external view returns (uint64); ++ function baseGas(bytes memory _message, uint32 _minGasLimit) external pure returns (uint64); ++ function failedMessages(bytes32) external view returns (bool); ++ function messageNonce() external view returns (uint256); ++ function otherMessenger() external view returns (ICrossDomainMessenger); ++ function paused() external view returns (bool); ++ function relayMessage( ++ uint256 _nonce, ++ address _sender, ++ address _target, ++ uint256 _value, ++ uint256 _minGasLimit, ++ bytes memory _message ++ ) ++ external ++ payable; ++ function sendMessage(address _target, bytes memory _message, uint32 _minGasLimit) external payable; ++ function successfulMessages(bytes32) external view returns (bool); ++ function xDomainMessageSender() external view returns (address); +}
@@ -32599,9 +135166,9 @@
@@ -32616,7 +135183,7 @@
@@ -32626,61 +135193,65 @@
-
+43
+
+47
-0
-
diff --git OP/packages/contracts-bedrock/src/celo/interfaces/IMetaTransactionWallet.sol CELO/packages/contracts-bedrock/src/celo/interfaces/IMetaTransactionWallet.sol +
diff --git OP/packages/contracts-bedrock/src/universal/interfaces/IERC721Bridge.sol CELO/packages/contracts-bedrock/src/universal/interfaces/IERC721Bridge.sol new file mode 100644 -index 0000000000000000000000000000000000000000..5c7f392814b615b6b35ec6de7e4a044708fec8df +index 0000000000000000000000000000000000000000..ccb2d5f0a4836e4e6b0572a9c4e302c269d414de --- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/interfaces/IMetaTransactionWallet.sol -@@ -0,0 +1,43 @@ -+// SPDX-License-Identifier: LGPL-3.0-only -+pragma solidity ^0.8.15; ++++ CELO/packages/contracts-bedrock/src/universal/interfaces/IERC721Bridge.sol +@@ -0,0 +1,47 @@ ++// SPDX-License-Identifier: MIT ++pragma solidity ^0.8.0; + -+interface IMetaTransactionWallet { -+ function setEip712DomainSeparator() external; -+ function executeMetaTransaction( -+ address, -+ uint256, -+ bytes calldata, -+ uint8, -+ bytes32, -+ bytes32 -+ ) -+ external -+ returns (bytes memory); -+ function executeTransaction(address, uint256, bytes calldata) external returns (bytes memory); -+ function executeTransactions( -+ address[] calldata, -+ uint256[] calldata, -+ bytes calldata, -+ uint256[] calldata -+ ) -+ external -+ returns (bytes memory, uint256[] memory); ++import { ICrossDomainMessenger } from "src/universal/interfaces/ICrossDomainMessenger.sol"; + -+ // view functions -+ function getMetaTransactionDigest(address, uint256, bytes calldata, uint256) external view returns (bytes32); -+ function getMetaTransactionSigner( -+ address, -+ uint256, -+ bytes calldata, -+ uint256, -+ uint8, -+ bytes32, -+ bytes32 ++interface IERC721Bridge { ++ event ERC721BridgeFinalized( ++ address indexed localToken, ++ address indexed remoteToken, ++ address indexed from, ++ address to, ++ uint256 tokenId, ++ bytes extraData ++ ); ++ event ERC721BridgeInitiated( ++ address indexed localToken, ++ address indexed remoteToken, ++ address indexed from, ++ address to, ++ uint256 tokenId, ++ bytes extraData ++ ); ++ event Initialized(uint8 version); ++ ++ function MESSENGER() external view returns (ICrossDomainMessenger); ++ function OTHER_BRIDGE() external view returns (IERC721Bridge); ++ function bridgeERC721( ++ address _localToken, ++ address _remoteToken, ++ uint256 _tokenId, ++ uint32 _minGasLimit, ++ bytes memory _extraData + ) -+ external -+ view -+ returns (address); -+ -+ //only owner -+ function setSigner(address) external; ++ external; ++ function bridgeERC721To( ++ address _localToken, ++ address _remoteToken, ++ address _to, ++ uint256 _tokenId, ++ uint32 _minGasLimit, ++ bytes memory _extraData ++ ) ++ external; ++ function messenger() external view returns (ICrossDomainMessenger); ++ function otherBridge() external view returns (IERC721Bridge); ++ function paused() external view returns (bool); +}
@@ -32688,9 +135259,9 @@
@@ -32705,7 +135276,7 @@
@@ -32715,24 +135286,41 @@
-
+6
+
+23
-0
-
diff --git OP/packages/contracts-bedrock/src/celo/interfaces/IMetaTransactionWalletDeployer.sol CELO/packages/contracts-bedrock/src/celo/interfaces/IMetaTransactionWalletDeployer.sol +
diff --git OP/packages/contracts-bedrock/src/universal/interfaces/IFeeVault.sol CELO/packages/contracts-bedrock/src/universal/interfaces/IFeeVault.sol new file mode 100644 -index 0000000000000000000000000000000000000000..5828bee3c7467f9386974465a6a3fee00c3ef65f +index 0000000000000000000000000000000000000000..1742a0029c7d8cfd491379b0ede9b6ee1a243816 --- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/interfaces/IMetaTransactionWalletDeployer.sol -@@ -0,0 +1,6 @@ -+// SPDX-License-Identifier: LGPL-3.0-only -+pragma solidity ^0.8.15; ++++ CELO/packages/contracts-bedrock/src/universal/interfaces/IFeeVault.sol +@@ -0,0 +1,23 @@ ++// SPDX-License-Identifier: MIT ++pragma solidity ^0.8.0; ++ ++interface IFeeVault { ++ enum WithdrawalNetwork { ++ L1, ++ L2 ++ } + -+interface IMetaTransactionWalletDeployer { -+ function deploy(address, address, bytes calldata) external; ++ event Withdrawal(uint256 value, address to, address from); ++ event Withdrawal(uint256 value, address to, address from, WithdrawalNetwork withdrawalNetwork); ++ ++ receive() external payable; ++ ++ function MIN_WITHDRAWAL_AMOUNT() external view returns (uint256); ++ function RECIPIENT() external view returns (address); ++ function WITHDRAWAL_NETWORK() external view returns (WithdrawalNetwork); ++ function minWithdrawalAmount() external view returns (uint256 amount_); ++ function recipient() external view returns (address recipient_); ++ function totalProcessed() external view returns (uint256); ++ function withdraw() external; ++ function withdrawalNetwork() external view returns (WithdrawalNetwork network_); +}
@@ -32740,9 +135328,9 @@
@@ -32757,7 +135345,7 @@
@@ -32767,35 +135355,25 @@
-
+7
+
+0
-0
-
diff --git OP/packages/contracts-bedrock/src/celo/interfaces/IOracle.sol CELO/packages/contracts-bedrock/src/celo/interfaces/IOracle.sol -new file mode 100644 -index 0000000000000000000000000000000000000000..b3ae66a92756c915ede5a6c5b1f57387b2edc254 ---- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/interfaces/IOracle.sol -@@ -0,0 +1,7 @@ -+// SPDX-License-Identifier: MIT -+pragma solidity >=0.5.13 <0.9.0; -+ -+/// Possibly not final version -+interface IOracle { -+ function getExchangeRate(address token) external view returns (uint256 numerator, uint256 denominator); -+}
+
diff --git OP/packages/contracts-bedrock/src/universal/IOptimismMintableERC20.sol CELO/packages/contracts-bedrock/src/universal/interfaces/IOptimismMintableERC20.sol +rename from packages/contracts-bedrock/src/universal/IOptimismMintableERC20.sol +rename to packages/contracts-bedrock/src/universal/interfaces/IOptimismMintableERC20.sol
@@ -32810,7 +135388,7 @@
@@ -32820,117 +135398,56 @@
-
+99
+
+38
-0
-
diff --git OP/packages/contracts-bedrock/src/celo/interfaces/IStableToken.sol CELO/packages/contracts-bedrock/src/celo/interfaces/IStableToken.sol +
diff --git OP/packages/contracts-bedrock/src/universal/interfaces/IOptimismMintableERC20Factory.sol CELO/packages/contracts-bedrock/src/universal/interfaces/IOptimismMintableERC20Factory.sol new file mode 100644 -index 0000000000000000000000000000000000000000..b13febff81fc8c95da5bc8567fdbcc64938c9d19 +index 0000000000000000000000000000000000000000..91f6eba6c1756cfb255fee3b23de9c980bf48646 --- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/interfaces/IStableToken.sol -@@ -0,0 +1,99 @@ -+// SPDX-License-Identifier: GPL-3.0-or-later -+pragma solidity >=0.5.17 <9.0.0; -+ -+interface IStableTokenV2 { -+ function totalSupply() external view returns (uint256); -+ -+ function balanceOf(address account) external view returns (uint256); -+ -+ function transfer(address recipient, uint256 amount) external returns (bool); -+ -+ function allowance(address owner, address spender) external view returns (uint256); -+ -+ function approve(address spender, uint256 amount) external returns (bool); -+ -+ function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); -+ -+ function mint(address, uint256) external returns (bool); -+ -+ function burn(uint256) external returns (bool); ++++ CELO/packages/contracts-bedrock/src/universal/interfaces/IOptimismMintableERC20Factory.sol +@@ -0,0 +1,38 @@ ++// SPDX-License-Identifier: MIT ++pragma solidity ^0.8.0; + -+ function permit( -+ address owner, -+ address spender, -+ uint256 value, -+ uint256 deadline, -+ uint8 v, -+ bytes32 r, -+ bytes32 s ++interface IOptimismMintableERC20Factory { ++ event Initialized(uint8 version); ++ event OptimismMintableERC20Created(address indexed localToken, address indexed remoteToken, address deployer); ++ event StandardL2TokenCreated(address indexed remoteToken, address indexed localToken); ++ ++ function BRIDGE() external view returns (address); ++ function bridge() external view returns (address); ++ function createOptimismMintableERC20( ++ address _remoteToken, ++ string memory _name, ++ string memory _symbol + ) -+ external; -+ -+ /** -+ * @notice Transfer token for a specified address -+ * @param to The address to transfer to. -+ * @param value The amount to be transferred. -+ * @param comment The transfer comment. -+ * @return True if the transaction succeeds. -+ */ -+ function transferWithComment(address to, uint256 value, string calldata comment) external returns (bool); -+ -+ /** -+ * @notice Initializes a StableTokenV2. -+ * It keeps the same signature as the original initialize() function -+ * in legacy/StableToken.sol -+ * @param _name The name of the stable token (English) -+ * @param _symbol A short symbol identifying the token (e.g. "cUSD") -+ * @param initialBalanceAddresses Array of addresses with an initial balance. -+ * @param initialBalanceValues Array of balance values corresponding to initialBalanceAddresses. -+ * deprecated-param exchangeIdentifier String identifier of exchange in registry (for specific fiat pairs) -+ */ -+ function initialize( -+ string calldata _name, -+ string calldata _symbol, -+ address[] calldata initialBalanceAddresses, -+ uint256[] calldata initialBalanceValues ++ external ++ returns (address); ++ function createOptimismMintableERC20WithDecimals( ++ address _remoteToken, ++ string memory _name, ++ string memory _symbol, ++ uint8 _decimals + ) -+ external; -+ -+ /** -+ * @notice Initializes a StableTokenV2 contract -+ * when upgrading from legacy/StableToken.sol. -+ * It sets the addresses that were previously read from the Registry. -+ * It runs the ERC20PermitUpgradeable initializer. -+ * @dev This function is only callable once. -+ * @param _broker The address of the Broker contract. -+ * @param _validators The address of the Validators contract. -+ * @param _exchange The address of the Exchange contract. -+ */ -+ function initializeV2(address _broker, address _validators, address _exchange) external; -+ -+ /** -+ * @notice Gets the address of the Broker contract. -+ */ -+ function broker() external returns (address); -+ -+ /** -+ * @notice Gets the address of the Validators contract. -+ */ -+ function validators() external returns (address); -+ -+ /** -+ * @notice Gets the address of the Exchange contract. -+ */ -+ function exchange() external returns (address); -+ -+ function debitGasFees(address from, uint256 value) external; -+ -+ function creditGasFees( -+ address from, -+ address feeRecipient, -+ address gatewayFeeRecipient, -+ address communityFund, -+ uint256 refund, -+ uint256 tipTxFee, -+ uint256 gatewayFee, -+ uint256 baseTxFee ++ external ++ returns (address); ++ function createStandardL2Token( ++ address _remoteToken, ++ string memory _name, ++ string memory _symbol + ) -+ external; ++ external ++ returns (address); ++ function deployments(address) external view returns (address); ++ function initialize(address _bridge) external; ++ function version() external view returns (string memory); ++ ++ function __constructor__() external; +}
@@ -32938,9 +135455,9 @@
@@ -32955,7 +135472,7 @@
@@ -32965,55 +135482,25 @@
-
+27
+
+0
-0
-
diff --git OP/packages/contracts-bedrock/src/celo/interfaces/IStableTokenMento.sol CELO/packages/contracts-bedrock/src/celo/interfaces/IStableTokenMento.sol -new file mode 100644 -index 0000000000000000000000000000000000000000..b309071d9f0ad88f27ece5e2648d4fa51465b741 ---- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/interfaces/IStableTokenMento.sol -@@ -0,0 +1,27 @@ -+// SPDX-License-Identifier: LGPL-3.0-only -+pragma solidity ^0.8.15; -+ -+/** -+ * @title This interface describes the functions specific to Celo Stable Tokens, and in the -+ * absence of interface inheritance is intended as a companion to IERC20.sol and ICeloToken.sol. -+ */ -+interface IStableTokenMento { -+ function mint(address, uint256) external returns (bool); -+ -+ function burn(uint256) external returns (bool); -+ -+ function setInflationParameters(uint256, uint256) external; -+ -+ function valueToUnits(uint256) external view returns (uint256); -+ -+ function unitsToValue(uint256) external view returns (uint256); -+ -+ function getInflationParameters() external view returns (uint256, uint256, uint256, uint256); -+ -+ // NOTE: duplicated with IERC20.sol, remove once interface inheritance is supported. -+ function balanceOf(address) external view returns (uint256); -+ -+ function getExchangeRegistryId() external view returns (bytes32); -+ -+ function approve(address spender, uint256 value) external returns (bool); -+}
+
diff --git OP/packages/contracts-bedrock/src/universal/IOptimismMintableERC721.sol CELO/packages/contracts-bedrock/src/universal/interfaces/IOptimismMintableERC721.sol +rename from packages/contracts-bedrock/src/universal/IOptimismMintableERC721.sol +rename to packages/contracts-bedrock/src/universal/interfaces/IOptimismMintableERC721.sol
@@ -33028,7 +135515,7 @@
@@ -33038,46 +135525,25 @@
-
+18
+
+0
-0
-
diff --git OP/packages/contracts-bedrock/src/celo/mento/interfaces/IExchange.sol CELO/packages/contracts-bedrock/src/celo/mento/interfaces/IExchange.sol -new file mode 100644 -index 0000000000000000000000000000000000000000..4e15e8a8750d45e28c6fc9eb7e483bf39591fa0b ---- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/mento/interfaces/IExchange.sol -@@ -0,0 +1,18 @@ -+// SPDX-License-Identifier: LGPL-3.0-only -+pragma solidity ^0.8.15; -+ -+interface IExchange { -+ function buy(uint256, uint256, bool) external returns (uint256); -+ -+ function sell(uint256, uint256, bool) external returns (uint256); -+ -+ function exchange(uint256, uint256, bool) external returns (uint256); -+ -+ function setUpdateFrequency(uint256) external; -+ -+ function getBuyTokenAmount(uint256, bool) external view returns (uint256); -+ -+ function getSellTokenAmount(uint256, bool) external view returns (uint256); -+ -+ function getBuyAndSellBuckets(bool) external view returns (uint256, uint256); -+}
+
diff --git OP/packages/contracts-bedrock/src/universal/ISemver.sol CELO/packages/contracts-bedrock/src/universal/interfaces/ISemver.sol +rename from packages/contracts-bedrock/src/universal/ISemver.sol +rename to packages/contracts-bedrock/src/universal/interfaces/ISemver.sol
@@ -33092,7 +135558,7 @@
@@ -33102,50 +135568,82 @@
-
+32
+
+64
-0
-
diff --git OP/packages/contracts-bedrock/src/celo/mento/interfaces/IReserve.sol CELO/packages/contracts-bedrock/src/celo/mento/interfaces/IReserve.sol +
diff --git OP/packages/contracts-bedrock/src/universal/interfaces/IStandardBridge.sol CELO/packages/contracts-bedrock/src/universal/interfaces/IStandardBridge.sol new file mode 100644 -index 0000000000000000000000000000000000000000..14f77c10549a1247f645191e241cd61a23145af5 +index 0000000000000000000000000000000000000000..b92aae27503bcc0650b2c3b40f0b01972a1314c3 --- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/mento/interfaces/IReserve.sol -@@ -0,0 +1,32 @@ -+// SPDX-License-Identifier: LGPL-3.0-only -+pragma solidity ^0.8.15; -+ -+interface IReserve { -+ function setTobinTaxStalenessThreshold(uint256) external; -+ -+ function addToken(address) external returns (bool); -+ -+ function removeToken(address, uint256) external returns (bool); -+ -+ function transferGold(address payable, uint256) external returns (bool); -+ -+ function transferExchangeGold(address payable, uint256) external returns (bool); -+ -+ function getReserveGoldBalance() external view returns (uint256); -+ -+ function getUnfrozenReserveGoldBalance() external view returns (uint256); -+ -+ function getOrComputeTobinTax() external returns (uint256, uint256); -+ -+ function getTokens() external view returns (address[] memory); -+ -+ function getReserveRatio() external view returns (uint256); -+ -+ function addExchangeSpender(address) external; -+ -+ function removeExchangeSpender(address, uint256) external; ++++ CELO/packages/contracts-bedrock/src/universal/interfaces/IStandardBridge.sol +@@ -0,0 +1,64 @@ ++// SPDX-License-Identifier: MIT ++pragma solidity ^0.8.0; + -+ function addSpender(address) external; ++import { ICrossDomainMessenger } from "src/universal/interfaces/ICrossDomainMessenger.sol"; + -+ function removeSpender(address) external; ++interface IStandardBridge { ++ event ERC20BridgeFinalized( ++ address indexed localToken, ++ address indexed remoteToken, ++ address indexed from, ++ address to, ++ uint256 amount, ++ bytes extraData ++ ); ++ event ERC20BridgeInitiated( ++ address indexed localToken, ++ address indexed remoteToken, ++ address indexed from, ++ address to, ++ uint256 amount, ++ bytes extraData ++ ); ++ event ETHBridgeFinalized(address indexed from, address indexed to, uint256 amount, bytes extraData); ++ event ETHBridgeInitiated(address indexed from, address indexed to, uint256 amount, bytes extraData); ++ event Initialized(uint8 version); ++ ++ receive() external payable; ++ ++ function MESSENGER() external view returns (ICrossDomainMessenger); ++ function OTHER_BRIDGE() external view returns (IStandardBridge); ++ function bridgeERC20( ++ address _localToken, ++ address _remoteToken, ++ uint256 _amount, ++ uint32 _minGasLimit, ++ bytes memory _extraData ++ ) ++ external; ++ function bridgeERC20To( ++ address _localToken, ++ address _remoteToken, ++ address _to, ++ uint256 _amount, ++ uint32 _minGasLimit, ++ bytes memory _extraData ++ ) ++ external; ++ function bridgeETH(uint32 _minGasLimit, bytes memory _extraData) external payable; ++ function bridgeETHTo(address _to, uint32 _minGasLimit, bytes memory _extraData) external payable; ++ function deposits(address, address) external view returns (uint256); ++ function finalizeBridgeERC20( ++ address _localToken, ++ address _remoteToken, ++ address _from, ++ address _to, ++ uint256 _amount, ++ bytes memory _extraData ++ ) ++ external; ++ function finalizeBridgeETH(address _from, address _to, uint256 _amount, bytes memory _extraData) external payable; ++ function messenger() external view returns (ICrossDomainMessenger); ++ function otherBridge() external view returns (IStandardBridge); ++ function paused() external view returns (bool); +}
@@ -33153,9 +135651,9 @@
@@ -33170,7 +135668,7 @@
@@ -33180,51 +135678,25 @@
-
+23
+
+0
-0
-
diff --git OP/packages/contracts-bedrock/src/celo/mento/interfaces/IStableToken.sol CELO/packages/contracts-bedrock/src/celo/mento/interfaces/IStableToken.sol -new file mode 100644 -index 0000000000000000000000000000000000000000..c0b681dfb8aee25aa686d5484adea6f3f6f79179 ---- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/mento/interfaces/IStableToken.sol -@@ -0,0 +1,23 @@ -+// SPDX-License-Identifier: LGPL-3.0-only -+pragma solidity ^0.8.15; -+ -+/** -+ * @title This interface describes the functions specific to Celo Stable Tokens, and in the -+ * absence of interface inheritance is intended as a companion to IERC20.sol and ICeloToken.sol. -+ */ -+interface IStableToken { -+ function mint(address, uint256) external returns (bool); -+ -+ function burn(uint256) external returns (bool); -+ -+ function setInflationParameters(uint256, uint256) external; -+ -+ function valueToUnits(uint256) external view returns (uint256); -+ -+ function unitsToValue(uint256) external view returns (uint256); -+ -+ function getInflationParameters() external view returns (uint256, uint256, uint256, uint256); -+ -+ // NOTE: duplicated with IERC20.sol, remove once interface inheritance is supported. -+ function balanceOf(address) external view returns (uint256); -+}
+
diff --git OP/packages/contracts-bedrock/src/dispute/interfaces/IWETH.sol CELO/packages/contracts-bedrock/src/universal/interfaces/IWETH.sol +rename from packages/contracts-bedrock/src/dispute/interfaces/IWETH.sol +rename to packages/contracts-bedrock/src/universal/interfaces/IWETH.sol
@@ -33239,7 +135711,7 @@
@@ -33249,483 +135721,626 @@
-
+466
+
+95
-0
- -
- -
- -
diff --git OP/packages/contracts-bedrock/src/celo/stability/SortedOracles.sol CELO/packages/contracts-bedrock/src/celo/stability/SortedOracles.sol -new file mode 100644 -index 0000000000000000000000000000000000000000..d2209dac5d2c8de4df0d0a1eb0ae0ec3f0e4422b ---- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/stability/SortedOracles.sol -@@ -0,0 +1,466 @@ -+// SPDX-License-Identifier: GPL-3.0-or-later -+pragma solidity ^0.8.15; -+ -+import "../../../lib/openzeppelin-contracts/contracts/access/Ownable.sol"; -+import "../../../lib/openzeppelin-contracts/contracts/utils/math/SafeMath.sol"; -+ -+import "./interfaces/ISortedOracles.sol"; -+import "../common/interfaces/ICeloVersionedContract.sol"; -+import "./interfaces/IBreakerBox.sol"; -+ -+import "../common/FixidityLib.sol"; -+import "../common/Initializable.sol"; -+import "../common/linkedlists/AddressSortedLinkedListWithMedian.sol"; -+import "../common/linkedlists/SortedLinkedListWithMedian.sol"; -+import "./interfaces/IOracle.sol"; -+ -+/** -+ * @title SortedOracles -+ * -+ * @notice This contract stores a collection of exchange rates with CELO -+ * expressed in units of other assets. The most recent exchange rates -+ * are gathered off-chain by oracles, who then use the `report` function to -+ * submit the rates to this contract. Before submitting a rate report, an -+ * oracle's address must be added to the `isOracle` mapping for a specific -+ * rateFeedId, with the flag set to true. While submitting a report requires -+ * an address to be added to the mapping, no additional permissions are needed -+ * to read the reports, the calculated median rate, or the list of oracles. -+ * -+ * @dev A unique rateFeedId identifies each exchange rate. In the initial implementation -+ * of this contract, the rateFeedId was set as the address of the stable -+ * asset contract that used the rate. However, this implementation has since -+ * been updated, and the rateFeedId block.timestamp also refers to an address derived from the -+ * concatenation other asset symbols. This change enables the contract to store multiple exchange rates for a -+ * single token. As a result of this change, there may be instances -+ * where the term "token" is used in the contract code. These useages of the term -+ * "token" are actually referring to the rateFeedId. -+ * -+ */ -+contract SortedOracles is ISortedOracles, IOracle, ICeloVersionedContract, Ownable, Initializable { -+ using SafeMath for uint256; -+ using AddressSortedLinkedListWithMedian for SortedLinkedListWithMedian.List; -+ using FixidityLib for FixidityLib.Fraction; -+ -+ struct EquivalentToken { -+ address token; -+ } -+ -+ uint256 private constant FIXED1_UINT = 1e24; -+ -+ // Maps a rateFeedID to a sorted list of report values. -+ mapping(address => SortedLinkedListWithMedian.List) private rates; -+ // Maps a rateFeedID to a sorted list of report timestamps. -+ mapping(address => SortedLinkedListWithMedian.List) private timestamps; -+ mapping(address => mapping(address => bool)) public isOracle; -+ mapping(address => address[]) public oracles; -+ -+ // `reportExpirySeconds` is the fallback value used to determine reporting -+ // frequency. Initially it was the _only_ value but we later introduced -+ // the per token mapping in `tokenReportExpirySeconds`. If a token -+ // doesn't have a value in the mapping (i.e. it's 0), the fallback is used. -+ // See: #getTokenReportExpirySeconds -+ uint256 public reportExpirySeconds; -+ // Maps a rateFeedId to its report expiry time in seconds. -+ mapping(address => uint256) public tokenReportExpirySeconds; -+ -+ IBreakerBox public breakerBox; -+ // Maps a token address to its equivalent token address. -+ // Original token will return the median value same as the value of equivalent token. -+ mapping(address => EquivalentToken) public equivalentTokens; -+ -+ event OracleAdded(address indexed token, address indexed oracleAddress); -+ event OracleRemoved(address indexed token, address indexed oracleAddress); -+ event OracleReported(address indexed token, address indexed oracle, uint256 timestamp, uint256 value); -+ event OracleReportRemoved(address indexed token, address indexed oracle); -+ event MedianUpdated(address indexed token, uint256 value); -+ event ReportExpirySet(uint256 reportExpiry); -+ event TokenReportExpirySet(address token, uint256 reportExpiry); -+ event BreakerBoxUpdated(address indexed newBreakerBox); -+ event EquivalentTokenSet(address indexed token, address indexed equivalentToken); -+ -+ modifier onlyOracle(address token) { -+ require(isOracle[token][msg.sender], "sender was not an oracle for token addr"); -+ _; -+ } -+ -+ /** -+ * @notice Sets initialized == true on implementation contracts -+ * @param test Set to true to skip implementation initialization -+ */ -+ constructor(bool test) Initializable(test) { } -+ -+ /** -+ * @notice Used in place of the constructor to allow the contract to be upgradable via proxy. -+ * @param _reportExpirySeconds The number of seconds before a report is considered expired. -+ */ -+ function initialize(uint256 _reportExpirySeconds) external initializer { -+ _transferOwnership(msg.sender); -+ setReportExpiry(_reportExpirySeconds); -+ } -+ -+ /** -+ * @notice Sets the report expiry parameter for a rateFeedId. -+ * @param _token The token for which the report expiry is being set. -+ * @param _reportExpirySeconds The number of seconds before a report is considered expired. -+ */ -+ function setTokenReportExpiry(address _token, uint256 _reportExpirySeconds) external onlyOwner { -+ require(_reportExpirySeconds > 0, "report expiry seconds must be > 0"); -+ require(_reportExpirySeconds != tokenReportExpirySeconds[_token], "token reportExpirySeconds hasn't changed"); -+ tokenReportExpirySeconds[_token] = _reportExpirySeconds; -+ emit TokenReportExpirySet(_token, _reportExpirySeconds); -+ } -+ -+ /** -+ * @notice Adds a new Oracle for a specified rate feed. -+ * @param token The token for which the specified oracle is to be added. -+ * @param oracleAddress The address of the oracle. -+ */ -+ function addOracle(address token, address oracleAddress) external onlyOwner { -+ // solhint-disable-next-line reason-string -+ require( -+ token != address(0) && oracleAddress != address(0) && !isOracle[token][oracleAddress], -+ "token addr was null or oracle addr was null or oracle addr is already an oracle for token addr" -+ ); -+ isOracle[token][oracleAddress] = true; -+ oracles[token].push(oracleAddress); -+ emit OracleAdded(token, oracleAddress); -+ } -+ -+ /** -+ * @notice Removes an Oracle from a specified rate feed. -+ * @param token The token from which the specified oracle is to be removed. -+ * @param oracleAddress The address of the oracle. -+ * @param index The index of `oracleAddress` in the list of oracles. -+ */ -+ function removeOracle(address token, address oracleAddress, uint256 index) external onlyOwner { -+ // solhint-disable-next-line reason-string -+ require( -+ token != address(0) && oracleAddress != address(0) && oracles[token].length > index -+ && oracles[token][index] == oracleAddress, -+ "token addr null or oracle addr null or index of token oracle not mapped to oracle addr" -+ ); -+ isOracle[token][oracleAddress] = false; -+ oracles[token][index] = oracles[token][oracles[token].length.sub(1)]; -+ oracles[token].pop(); -+ if (reportExists(token, oracleAddress)) { -+ removeReport(token, oracleAddress); -+ } -+ emit OracleRemoved(token, oracleAddress); -+ } -+ -+ /** -+ * @notice Removes a report that is expired. -+ * @param token The token for which the expired report is to be removed. -+ * @param n The number of expired reports to remove, at most (deterministic upper gas bound). -+ */ -+ function removeExpiredReports(address token, uint256 n) external { -+ require( -+ token != address(0) && n < timestamps[token].getNumElements(), -+ "token addr null or trying to remove too many reports" -+ ); -+ for (uint256 i = 0; i < n; i = i.add(1)) { -+ (bool isExpired, address oldestAddress) = isOldestReportExpired(token); -+ if (isExpired) { -+ removeReport(token, oldestAddress); -+ } else { -+ break; -+ } -+ } -+ } -+ -+ /** -+ * @notice Sets the equivalent token for a token. -+ * @param token The address of the token. -+ * @param equivalentToken The address of the equivalent token. -+ */ -+ function setEquivalentToken(address token, address equivalentToken) external onlyOwner { -+ require(token != address(0), "token address cannot be 0"); -+ require(equivalentToken != address(0), "equivalentToken address cannot be 0"); -+ equivalentTokens[token] = EquivalentToken(equivalentToken); -+ emit EquivalentTokenSet(token, equivalentToken); -+ } -+ -+ /** -+ * @notice Sets the equivalent token for a token. -+ * @param token The address of the token. -+ */ -+ function deleteEquivalentToken(address token) external onlyOwner { -+ require(token != address(0), "token address cannot be 0"); -+ delete equivalentTokens[token]; -+ emit EquivalentTokenSet(token, address(0)); -+ } -+ -+ /** -+ * @notice Updates an oracle value and the median. -+ * @param token The token for which the rate is being reported. -+ * @param value The number of stable asset that equate to one unit of collateral asset, for the -+ * specified rateFeedId, expressed as a fixidity value. -+ * @param lesserKey The element which should be just left of the new oracle value. -+ * @param greaterKey The element which should be just right of the new oracle value. -+ * @dev Note that only one of `lesserKey` or `greaterKey` needs to be correct to reduce friction. -+ */ -+ function report(address token, uint256 value, address lesserKey, address greaterKey) external onlyOracle(token) { -+ uint256 originalMedian = rates[token].getMedianValue(); -+ if (rates[token].contains(msg.sender)) { -+ rates[token].update(msg.sender, value, lesserKey, greaterKey); -+ -+ // Rather than update the timestamp, we remove it and re-add it at the -+ // head of the list later. The reason for this is that we need to handle -+ // a few different cases: -+ // 1. This oracle is the only one to report so far. lesserKey = address(0) -+ // 2. Other oracles have reported since this one's last report. lesserKey = getHead() -+ // 3. Other oracles have reported, but the most recent is this one. -+ // lesserKey = key immediately after getHead() -+ // -+ // However, if we just remove this timestamp, timestamps[token].getHead() -+ // does the right thing in all cases. -+ timestamps[token].remove(msg.sender); -+ } else { -+ rates[token].insert(msg.sender, value, lesserKey, greaterKey); -+ } -+ timestamps[token].insert( -+ msg.sender, -+ // solhint-disable-next-line not-rely-on-time -+ block.timestamp, -+ timestamps[token].getHead(), -+ address(0) -+ ); -+ emit OracleReported(token, msg.sender, block.timestamp, value); -+ uint256 newMedian = rates[token].getMedianValue(); -+ if (newMedian != originalMedian) { -+ emit MedianUpdated(token, newMedian); -+ } + +
+ + + +
diff --git OP/packages/contracts-bedrock/src/vendor/interfaces/IERC20Solady.sol CELO/packages/contracts-bedrock/src/vendor/interfaces/IERC20Solady.sol +new file mode 100644 +index 0000000000000000000000000000000000000000..1e696ad23ac3136f8d7320dbc589c94d8b8e903d +--- /dev/null ++++ CELO/packages/contracts-bedrock/src/vendor/interfaces/IERC20Solady.sol +@@ -0,0 +1,95 @@ ++// SPDX-License-Identifier: MIT ++pragma solidity ^0.8.0; + -+ if (address(breakerBox) != address(0)) { -+ breakerBox.checkAndSetBreakers(token); -+ } -+ } ++interface IERC20Solady { ++ /// @dev The total supply has overflowed. ++ error TotalSupplyOverflow(); + -+ /** -+ * @notice Gets the equivalent token for a token. -+ * @param token The address of the token. -+ * @return The address of the equivalent token. -+ */ -+ function getEquivalentToken(address token) external view returns (address) { -+ return (equivalentTokens[token].token); -+ } ++ /// @dev The allowance has overflowed. ++ error AllowanceOverflow(); + -+ /** -+ * @notice Returns the median timestamp. -+ * @dev Does not take the equivalentTokens mapping into account. -+ * For that, the underlying token should be queried. -+ * @param token The token for which the median timestamp is being retrieved. -+ * @return uint256 The median report timestamp for the specified rateFeedId. -+ */ -+ function medianTimestamp(address token) external view returns (uint256) { -+ return timestamps[token].getMedianValue(); -+ } ++ /// @dev The allowance has underflowed. ++ error AllowanceUnderflow(); + -+ /** -+ * @notice Gets all elements from the doubly linked list. -+ * @dev Does not take the equivalentTokens mapping into account. -+ * For that, the underlying token should be queried. -+ * @param token The token for which the timestamps are being retrieved. -+ * @return keys Keys of nn unpacked list of elements from largest to smallest. -+ * @return values Values of an unpacked list of elements from largest to smallest. -+ * @return relations Relations of an unpacked list of elements from largest to smallest. -+ */ -+ function getTimestamps(address token) -+ external -+ view -+ returns (address[] memory, uint256[] memory, SortedLinkedListWithMedian.MedianRelation[] memory) -+ { -+ return timestamps[token].getElements(); -+ } ++ /// @dev Insufficient balance. ++ error InsufficientBalance(); + -+ /** -+ * @notice Returns the list of oracles for a speficied rateFeedId. -+ * @dev Does not take the equivalentTokens mapping into account. -+ * For that, the underlying token should be queried. -+ * @param token The token for which the oracles are being retrieved. -+ * @return address[] A list of oracles for the given rateFeedId. -+ */ -+ function getOracles(address token) external view returns (address[] memory) { -+ return oracles[token]; -+ } ++ /// @dev Insufficient allowance. ++ error InsufficientAllowance(); + -+ /** -+ * @notice Gets all elements from the doubly linked list. -+ * @dev Does not take the equivalentTokens mapping into account. -+ * For that, the underlying token should be queried. -+ * @param token The token for which the rates are being retrieved. -+ * @return keys Keys of an unpacked list of elements from largest to smallest. -+ * @return values Values of an unpacked list of elements from largest to smallest. -+ * @return relations Relations of an unpacked list of elements from largest to smallest. -+ */ -+ function getRates(address token) -+ external -+ view -+ returns (address[] memory, uint256[] memory, SortedLinkedListWithMedian.MedianRelation[] memory) -+ { -+ return rates[token].getElements(); -+ } ++ /// @dev The permit is invalid. ++ error InvalidPermit(); + -+ /** -+ * @notice Returns the exchange rate for a specified token. -+ * @param token The token for which the exchange rate is being retrieved. -+ * @return numerator uint256 The exchange rate for the specified token. -+ * @return denominator uint256 The denominator for the exchange rate. -+ */ -+ function getExchangeRate(address token) external view returns (uint256 numerator, uint256 denominator) { -+ (numerator, denominator) = medianRate(token); -+ } ++ /// @dev The permit has expired. ++ error PermitExpired(); + -+ /** -+ * @notice Returns the storage, major, minor, and patch version of the contract. -+ * @return Storage version of the contract. -+ * @return Major version of the contract. -+ * @return Minor version of the contract. -+ * @return Patch version of the contract. -+ */ -+ function getVersionNumber() external pure returns (uint256, uint256, uint256, uint256) { -+ return (1, 1, 4, 0); -+ } ++ /// @dev Emitted when `amount` tokens is transferred from `from` to `to`. ++ event Transfer(address indexed from, address indexed to, uint256 amount); + -+ /** -+ * @notice Sets the report expiry parameter. -+ * @param _reportExpirySeconds The number of seconds before a report is considered expired. -+ */ -+ function setReportExpiry(uint256 _reportExpirySeconds) public onlyOwner { -+ require(_reportExpirySeconds > 0, "report expiry seconds must be > 0"); -+ require(_reportExpirySeconds != reportExpirySeconds, "reportExpirySeconds hasn't changed"); -+ reportExpirySeconds = _reportExpirySeconds; -+ emit ReportExpirySet(_reportExpirySeconds); -+ } ++ /// @dev Emitted when `amount` tokens is approved by `owner` to be used by `spender`. ++ event Approval(address indexed owner, address indexed spender, uint256 amount); + -+ /** -+ * @notice Sets the address of the BreakerBox. -+ * @param newBreakerBox The new BreakerBox address. -+ */ -+ function setBreakerBox(IBreakerBox newBreakerBox) public onlyOwner { -+ require(address(newBreakerBox) != address(0), "BreakerBox address must be set"); -+ breakerBox = newBreakerBox; -+ emit BreakerBoxUpdated(address(newBreakerBox)); -+ } ++ /// @dev Returns the name of the token. ++ function name() external view returns (string memory); + -+ /** -+ * @notice Returns the median of the currently stored rates for a specified rateFeedId. -+ * @dev Please note that this function respects the equivalentToken mapping, and so may -+ * return the median identified as an equivalent to the supplied rateFeedId. -+ * @param token The token for which the median value is being retrieved. -+ * @return uint256 The median exchange rate for rateFeedId (fixidity). -+ * @return uint256 denominator -+ */ -+ function medianRate(address token) public view returns (uint256, uint256) { -+ EquivalentToken storage equivalentToken = equivalentTokens[token]; -+ if (equivalentToken.token != address(0)) { -+ (uint256 equivalentMedianRate, uint256 denominator) = -+ medianRateWithoutEquivalentMapping(equivalentToken.token); -+ return (equivalentMedianRate, denominator); -+ } ++ /// @dev Returns the symbol of the token. ++ function symbol() external view returns (string memory); + -+ return medianRateWithoutEquivalentMapping(token); ++ /// @dev Returns the decimals places of the token. ++ function decimals() external view returns (uint8); ++ ++ /// @dev Returns the amount of tokens in existence. ++ function totalSupply() external view returns (uint256 result); ++ ++ /// @dev Returns the amount of tokens owned by `owner` ++ function balanceOf(address owner) external view returns (uint256 result); ++ ++ /// @dev Returns the amount of tokens that `spender` can spend on behalf of `owner`. ++ function allowance(address owner, address spender) external view returns (uint256 result); ++ ++ /// @dev Sets `amount` as the allowance of `spender` over the caller's tokens. ++ /// ++ /// Emits a {Approval} event. ++ function approve(address spender, uint256 amount) external returns (bool); ++ ++ /// @dev Transfer `amount` tokens from the caller to `to`. ++ /// ++ /// Requirements: ++ /// - `from` must at least have `amount`. ++ /// ++ /// Emits a {Transfer} event. ++ function transfer(address to, uint256 amount) external returns (bool); ++ ++ /// @dev Transfers `amount` tokens from `from` to `to`. ++ /// ++ /// Note: Does not update the allowance if it is the maximum uint256 value. ++ /// ++ /// Requirements: ++ /// - `from` must at least have `amount`. ++ /// - The caller must have at least `amount` of allowance to transfer the tokens of `from`. ++ /// ++ /// Emits a {Transfer} event. ++ function transferFrom(address from, address to, uint256 amount) external returns (bool); ++ ++ /// @dev Returns the current nonce for `owner`. ++ /// This value is used to compute the signature for EIP-2612 permit. ++ function nonces(address owner) external view returns (uint256 result); ++ ++ /// @dev Sets `value` as the allowance of `spender` over the tokens of `owner`, ++ /// authorized by a signed approval by `owner`. ++ /// ++ /// Emits a {Approval} event. ++ function permit( ++ address owner, ++ address spender, ++ uint256 value, ++ uint256 deadline, ++ uint8 v, ++ bytes32 r, ++ bytes32 s ++ ) ++ external; ++ ++ /// @dev Returns the EIP-712 domain separator for the EIP-2612 permit. ++ function DOMAIN_SEPARATOR() external view returns (bytes32 result); ++}
+ + + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+83
+
-0
+ +
+ +
+
+
diff --git OP/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/OptimismSuperchainERC20.t.sol CELO/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/OptimismSuperchainERC20.t.sol +new file mode 100644 +index 0000000000000000000000000000000000000000..d90e90a2f811c069f80213cb859ef218d37201e0 +--- /dev/null ++++ CELO/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/OptimismSuperchainERC20.t.sol +@@ -0,0 +1,83 @@ ++// SPDX-License-Identifier: MIT ++pragma solidity 0.8.25; ++ ++// Testing utilities ++import { Test, StdUtils, Vm } from "forge-std/Test.sol"; ++import { StdInvariant } from "forge-std/StdInvariant.sol"; ++import { StdAssertions } from "forge-std/StdAssertions.sol"; ++import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; ++ ++// Libraries ++import { Predeploys } from "src/libraries/Predeploys.sol"; ++import { OptimismSuperchainERC20 } from "src/L2/OptimismSuperchainERC20.sol"; ++import { IL2ToL2CrossDomainMessenger } from "src/L2/interfaces/IL2ToL2CrossDomainMessenger.sol"; ++import { ProtocolGuided } from "./fuzz/Protocol.guided.t.sol"; ++import { ProtocolUnguided } from "./fuzz/Protocol.unguided.t.sol"; ++import { HandlerGetters } from "./helpers/HandlerGetters.t.sol"; ++import { MockL2ToL2CrossDomainMessenger } from "./helpers/MockL2ToL2CrossDomainMessenger.t.sol"; ++ ++contract OptimismSuperchainERC20Handler is HandlerGetters, ProtocolGuided, ProtocolUnguided { } ++ ++contract OptimismSuperchainERC20Properties is Test { ++ OptimismSuperchainERC20Handler internal handler; ++ MockL2ToL2CrossDomainMessenger internal constant MESSENGER = ++ MockL2ToL2CrossDomainMessenger(Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER); ++ ++ function setUp() public { ++ handler = new OptimismSuperchainERC20Handler(); ++ targetContract(address(handler)); + } + -+ /** -+ * @notice Returns the number of rates that are currently stored for a specifed rateFeedId. -+ * @dev Does not take the equivalentTokens mapping into account. -+ * For that, the underlying token should be queried. -+ * @param token The token for which the number of rates is being retrieved. -+ * @return uint256 The number of reported oracle rates stored for the given rateFeedId. -+ */ -+ function numRates(address token) public view returns (uint256) { -+ return rates[token].getNumElements(); ++ // TODO: will need rework after ++ // - `convert` ++ /// @custom:invariant sum of supertoken total supply across all chains is always <= to convert(legacy, super)- ++ /// convert(super, legacy) ++ function invariant_totalSupplyAcrossChainsEqualsMintsMinusFundsInTransit() external view { ++ // iterate over unique deploy salts aka supertokens that are supposed to be compatible with each other ++ for (uint256 deploySaltIndex = 0; deploySaltIndex < handler.deploySaltsLength(); deploySaltIndex++) { ++ uint256 totalSupply = 0; ++ (bytes32 currentSalt, uint256 trackedSupply) = handler.totalSupplyAcrossChainsAtIndex(deploySaltIndex); ++ uint256 fundsInTransit = handler.tokensInTransitForDeploySalt(currentSalt); ++ // and then over all the (mocked) chain ids where that supertoken could be deployed ++ for (uint256 validChainId = 0; validChainId < handler.MAX_CHAINS(); validChainId++) { ++ address supertoken = MESSENGER.superTokenAddresses(validChainId, currentSalt); ++ if (supertoken != address(0)) { ++ totalSupply += OptimismSuperchainERC20(supertoken).totalSupply(); ++ } ++ } ++ assertEq(trackedSupply, totalSupply + fundsInTransit); ++ } + } + -+ /** -+ * @notice Check if last report is expired. -+ * @param token The token for which the expired report is to be checked. -+ * @return bool A bool indicating if the last report is expired. -+ * @return address Oracle address of the last report. -+ */ -+ function isOldestReportExpired(address token) public view returns (bool, address) { -+ // solhint-disable-next-line reason-string -+ require(token != address(0)); -+ address oldest = timestamps[token].getTail(); -+ uint256 timestamp = timestamps[token].getValue(oldest); -+ // solhint-disable-next-line not-rely-on-time -+ if (block.timestamp.sub(timestamp) >= getTokenReportExpirySeconds(token)) { -+ return (true, oldest); ++ // TODO: will need rework after ++ // - `convert` ++ /// @custom:invariant sum of supertoken total supply across all chains is equal to convert(legacy, super)- ++ /// convert(super, legacy) when all when all cross-chain messages are processed ++ function invariant_totalSupplyAcrossChainsEqualsMintsWhenQueueIsEmpty() external view { ++ if (MESSENGER.messageQueueLength() != 0) { ++ return; ++ } ++ // iterate over unique deploy salts aka supertokens that are supposed to be compatible with each other ++ for (uint256 deploySaltIndex = 0; deploySaltIndex < handler.deploySaltsLength(); deploySaltIndex++) { ++ uint256 totalSupply = 0; ++ (bytes32 currentSalt, uint256 trackedSupply) = handler.totalSupplyAcrossChainsAtIndex(deploySaltIndex); ++ // and then over all the (mocked) chain ids where that supertoken could be deployed ++ for (uint256 validChainId = 0; validChainId < handler.MAX_CHAINS(); validChainId++) { ++ address supertoken = MESSENGER.superTokenAddresses(validChainId, currentSalt); ++ if (supertoken != address(0)) { ++ totalSupply += OptimismSuperchainERC20(supertoken).totalSupply(); ++ } ++ } ++ assertEq(trackedSupply, totalSupply); + } -+ return (false, oldest); + } + -+ /** -+ * @notice Returns the median of the currently stored rates for a specified rateFeedId. -+ * @dev Does not take the equivalentTokens mapping into account. -+ * @param token The token for which the median value is being retrieved. -+ * @return uint256 The median exchange rate for rateFeedId (fixidity). -+ * @return uint256 denominator -+ */ -+ function medianRateWithoutEquivalentMapping(address token) public view returns (uint256, uint256) { -+ return (rates[token].getMedianValue(), numRates(token) == 0 ? 0 : FIXED1_UINT); ++ /// @custom:invariant many other assertion mode invariants are also defined under ++ /// `test/invariants/OptimismSuperchainERC20/fuzz/` . ++ /// ++ /// since setting`fail_on_revert=false` also ignores StdAssertion failures, this invariant explicitly asks the ++ /// handler for assertion test failures ++ function invariant_handlerAssertions() external view { ++ assertFalse(handler.failed()); ++ } ++}
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+82
+
-0
+ +
+ +
+
+
diff --git OP/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/PROPERTIES.md CELO/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/PROPERTIES.md +new file mode 100644 +index 0000000000000000000000000000000000000000..18970855ca468238bcc2a7c7b8150b32cfcec24a +--- /dev/null ++++ CELO/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/PROPERTIES.md +@@ -0,0 +1,82 @@ ++# Supertoken advanced testing ++ ++## Milestones ++ ++The supertoken ecosystem consists of not just the supertoken contract, but the required changes to other contracts for liquidity to reach the former. ++ ++Considering only the supertoken contract is merged into the `develop` branch, and work for the other components is still in progress, we define three milestones for the testing campaign: ++ ++- SupERC20: concerned with only the supertoken contract, the first one to be implemented ++- Factories: covers the above + the development of `OptimismSuperchainERC20Factory` and required changes to `OptimismMintableERC20Factory` ++- Liquidity Migration: includes the `convert` function on the `L2StandardBridgeInterop` to migrate liquidity from legacy tokens into supertokens ++ ++## Definitions ++ ++- *legacy token:* an OptimismMintableERC20 or L2StandardERC20 token on the suprechain that has either been deployed by the factory after the liquidity migration upgrade to the latter, or has been deployed before it **but** added to factory’s `deployments` mapping as part of the upgrade. This testing campaign is not concerned with tokens on L1 or not listed in the factory’s `deployments` mapping. ++- *supertoken:* a SuperchainERC20 contract deployed by the `OptimismSuperchainERC20Factory` ++ ++# Ecosystem properties ++ ++legend: ++ ++- `[ ]`: property not yet tested ++- `**[ ]**`: property not yet tested, dev/research team has asked for extra focus on it ++- `[X]`: tested/proven property ++- `[~]`: partially tested/proven property ++- `:(`: property won't be tested due to some limitation ++ ++## Unit test ++ ++| id | milestone | description | tested | ++| --- | --- | --- | --- | ++| 0 | Factories | supertoken token address does not depend on the executing chain’s chainID | [ ] | ++| 1 | Factories | supertoken token address depends on remote token, name, symbol and decimals | [ ] | ++| 2 | Liquidity Migration | convert() should only allow converting legacy tokens to supertoken and viceversa | [ ] | ++| 3 | Liquidity Migration | convert() only allows migrations between tokens representing the same remote asset | [ ] | ++| 4 | Liquidity Migration | convert() only allows migrations from tokens with the same decimals | [ ] | ++| 5 | Liquidity Migration | convert() burns the same amount of legacy token that it mints of supertoken, and viceversa | [ ] | ++| 25 | SupERC20 | supertokens can't be reinitialized | [x] | ++ ++## Valid state ++ ++| id | milestone | description | tested | ++| --- | --- | --- | --- | ++| 6 | SupERC20 | calls to sendERC20 succeed as long as caller has enough balance | [x] | ++| 7 | SupERC20 | calls to relayERC20 always succeed as long as the cross-domain caller is valid | [~] | ++ ++## Variable transition ++ ++| id | milestone | description | tested | ++| --- | --- | --- | --- | ++| 8 | SupERC20 | sendERC20 with a value of zero does not modify accounting | [x] | ++| 9 | SupERC20 | relayERC20 with a value of zero does not modify accounting | [x] | ++| 10 | SupERC20 | sendERC20 decreases the token's totalSupply in the source chain exactly by the input amount | [x] | ++| 26 | SupERC20 | sendERC20 decreases the sender's balance in the source chain exactly by the input amount | [x] | ++| 27 | SupERC20 | relayERC20 increases sender's balance in the destination chain exactly by the input amount | [x] | ++| 11 | SupERC20 | relayERC20 increases the token's totalSupply in the destination chain exactly by the input amount | [ ] | ++| 12 | Liquidity Migration | supertoken total supply only increases on calls to mint() by the L2toL2StandardBridge | [~] | ++| 13 | Liquidity Migration | supertoken total supply only decreases on calls to burn() by the L2toL2StandardBridge | [ ] | ++| 14 | SupERC20 | supertoken total supply starts at zero | [x] | ++| 15 | Factories | deploying a supertoken registers its remote token in the factory | [ ] | ++| 16 | Factories | deploying an OptimismMintableERC20 registers its remote token in the factory | [ ] | ++ ++## High level ++ ++| id | milestone | description | tested | ++| --- | --- | --- | --- | ++| 17 | Liquidity Migration | only calls to convert(legacy, super) can increase a supertoken’s total supply across chains | [ ] | ++| 18 | Liquidity Migration | only calls to convert(super, legacy) can decrease a supertoken’s total supply across chains | [ ] | ++| 19 | Liquidity Migration | sum of supertoken total supply across all chains is always <= to convert(legacy, super)- convert(super, legacy) | [~] | ++| 20 | SupERC20 | tokens sendERC20-ed on a source chain to a destination chain can be relayERC20-ed on it as long as the source chain is in the dependency set of the destination chain | [ ] | ++| 21 | Liquidity Migration | sum of supertoken total supply across all chains is = to convert(legacy, super)- convert(super, legacy) when all cross-chain messages are processed | [~] | ++ ++## Atomic bridging pseudo-properties ++ ++As another layer of defense, the following properties are defined which assume bridging operations to be atomic (that is, the sequencer and L2Inbox and CrossDomainMessenger contracts are fully abstracted away, `sendERC20` triggering the `relayERC20` call on the same transaction) ++It’s worth noting that these properties will not hold for a live system ++ ++| id | milestone | description | tested | ++| --- | --- | --- | --- | ++| 22 | SupERC20 | sendERC20 decreases sender balance in source chain and increases receiver balance in destination chain exactly by the input amount | [x] | ++| 23 | SupERC20 | sendERC20 decreases total supply in source chain and increases it in destination chain exactly by the input amount | [x] | ++| 24 | Liquidity Migration | sum of supertoken total supply across all chains is always equal to convert(legacy, super)- convert(super, legacy) | [~] |
+
+ + +
+ + +
+
+
+ + (new) + +
+ +
+ + CELO + +
+
+
+ +
+ +
+ +
+211
+
-0
+ +
+ +
+
+
diff --git OP/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/fuzz/Protocol.guided.t.sol CELO/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/fuzz/Protocol.guided.t.sol +new file mode 100644 +index 0000000000000000000000000000000000000000..536a4ea7025ae0f0844bdd7ed6b32054e3740d7c +--- /dev/null ++++ CELO/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/fuzz/Protocol.guided.t.sol +@@ -0,0 +1,211 @@ ++// SPDX-License-Identifier: MIT ++pragma solidity ^0.8.25; ++ ++import { MockL2ToL2CrossDomainMessenger } from "../helpers/MockL2ToL2CrossDomainMessenger.t.sol"; ++import { OptimismSuperchainERC20 } from "src/L2/OptimismSuperchainERC20.sol"; ++import { ProtocolHandler } from "../handlers/Protocol.t.sol"; ++import { EnumerableMap } from "@openzeppelin/contracts/utils/structs/EnumerableMap.sol"; ++import { CompatibleAssert } from "../helpers/CompatibleAssert.t.sol"; ++ ++contract ProtocolGuided is ProtocolHandler, CompatibleAssert { ++ using EnumerableMap for EnumerableMap.Bytes32ToUintMap; ++ /// @notice deploy a new supertoken with deploy salt determined by params, to the given (of course mocked) chainId ++ /// @custom:property-id 14 ++ /// @custom:property supertoken total supply starts at zero ++ ++ function fuzz_deployNewSupertoken( ++ TokenDeployParams memory params, ++ uint256 chainId ++ ) ++ external ++ validateTokenDeployParams(params) ++ { ++ chainId = bound(chainId, 0, MAX_CHAINS - 1); ++ OptimismSuperchainERC20 supertoken = _deploySupertoken( ++ remoteTokens[params.remoteTokenIndex], ++ WORDS[params.nameIndex], ++ WORDS[params.symbolIndex], ++ DECIMALS[params.decimalsIndex], ++ chainId ++ ); ++ // 14 ++ compatibleAssert(supertoken.totalSupply() == 0); + } + -+ /** -+ * @notice Returns the number of timestamps. -+ * @dev Does not take the equivalentTokens mapping into account. -+ * For that, the underlying token should be queried. -+ * @param token The token for which the number of timestamps is being retrieved. -+ * @return uint256 The number of oracle report timestamps for the specified rateFeedId. -+ */ -+ function numTimestamps(address token) public view returns (uint256) { -+ return timestamps[token].getNumElements(); ++ /// @custom:property-id 6 ++ /// @custom:property calls to sendERC20 succeed as long as caller has enough balance ++ /// @custom:property-id 22 ++ /// @custom:property sendERC20 decreases sender balance in source chain and increases receiver balance in ++ /// destination chain exactly by the input amount ++ /// @custom:property-id 23 ++ /// @custom:property sendERC20 decreases total supply in source chain and increases it in destination chain exactly ++ /// by the input amount ++ function fuzz_bridgeSupertokenAtomic( ++ uint256 fromIndex, ++ uint256 recipientIndex, ++ uint256 destinationChainId, ++ uint256 amount ++ ) ++ public ++ withActor(msg.sender) ++ { ++ destinationChainId = bound(destinationChainId, 0, MAX_CHAINS - 1); ++ fromIndex = bound(fromIndex, 0, allSuperTokens.length - 1); ++ address recipient = getActorByRawIndex(recipientIndex); ++ OptimismSuperchainERC20 sourceToken = OptimismSuperchainERC20(allSuperTokens[fromIndex]); ++ OptimismSuperchainERC20 destinationToken = ++ MESSENGER.crossChainMessageReceiver(address(sourceToken), destinationChainId); ++ uint256 sourceBalanceBefore = sourceToken.balanceOf(currentActor()); ++ uint256 sourceSupplyBefore = sourceToken.totalSupply(); ++ uint256 destinationBalanceBefore = destinationToken.balanceOf(recipient); ++ uint256 destinationSupplyBefore = destinationToken.totalSupply(); ++ ++ MESSENGER.setAtomic(true); ++ vm.prank(currentActor()); ++ try sourceToken.sendERC20(recipient, amount, destinationChainId) { ++ MESSENGER.setAtomic(false); ++ uint256 sourceBalanceAfter = sourceToken.balanceOf(currentActor()); ++ uint256 destinationBalanceAfter = destinationToken.balanceOf(recipient); ++ // no free mint ++ compatibleAssert( ++ sourceBalanceBefore + destinationBalanceBefore == sourceBalanceAfter + destinationBalanceAfter ++ ); ++ // 22 ++ compatibleAssert(sourceBalanceBefore - amount == sourceBalanceAfter); ++ compatibleAssert(destinationBalanceBefore + amount == destinationBalanceAfter); ++ uint256 sourceSupplyAfter = sourceToken.totalSupply(); ++ uint256 destinationSupplyAfter = destinationToken.totalSupply(); ++ // 23 ++ compatibleAssert(sourceSupplyBefore - amount == sourceSupplyAfter); ++ compatibleAssert(destinationSupplyBefore + amount == destinationSupplyAfter); ++ } catch { ++ MESSENGER.setAtomic(false); ++ // 6 ++ compatibleAssert(address(destinationToken) == address(sourceToken) || sourceBalanceBefore < amount); ++ } + } + -+ /** -+ * @notice Returns the expiry for specified rateFeedId if it exists, if not the default is returned. -+ * @dev Does not take the equivalentTokens mapping into account. -+ * For that, the underlying token should be queried. -+ * @param token The token for which the report expiry is being retrieved. -+ * @return The report expiry in seconds. -+ */ -+ function getTokenReportExpirySeconds(address token) public view returns (uint256) { -+ if (tokenReportExpirySeconds[token] == 0) { -+ return reportExpirySeconds; ++ /// @custom:property-id 6 ++ /// @custom:property calls to sendERC20 succeed as long as caller has enough balance ++ /// @custom:property-id 26 ++ /// @custom:property sendERC20 decreases sender balance in source chain exactly by the input amount ++ /// @custom:property-id 10 ++ /// @custom:property sendERC20 decreases total supply in source chain exactly by the input amount ++ function fuzz_sendERC20( ++ uint256 fromIndex, ++ uint256 recipientIndex, ++ uint256 destinationChainId, ++ uint256 amount ++ ) ++ public ++ withActor(msg.sender) ++ { ++ destinationChainId = bound(destinationChainId, 0, MAX_CHAINS - 1); ++ fromIndex = bound(fromIndex, 0, allSuperTokens.length - 1); ++ address recipient = getActorByRawIndex(recipientIndex); ++ OptimismSuperchainERC20 sourceToken = OptimismSuperchainERC20(allSuperTokens[fromIndex]); ++ OptimismSuperchainERC20 destinationToken = ++ MESSENGER.crossChainMessageReceiver(address(sourceToken), destinationChainId); ++ bytes32 deploySalt = MESSENGER.superTokenInitDeploySalts(address(sourceToken)); ++ uint256 sourceBalanceBefore = sourceToken.balanceOf(currentActor()); ++ uint256 sourceSupplyBefore = sourceToken.totalSupply(); ++ ++ vm.prank(currentActor()); ++ try sourceToken.sendERC20(recipient, amount, destinationChainId) { ++ (, uint256 currentlyInTransit) = ghost_tokensInTransit.tryGet(deploySalt); ++ ghost_tokensInTransit.set(deploySalt, currentlyInTransit + amount); ++ // 26 ++ uint256 sourceBalanceAfter = sourceToken.balanceOf(currentActor()); ++ compatibleAssert(sourceBalanceBefore - amount == sourceBalanceAfter); ++ // 10 ++ uint256 sourceSupplyAfter = sourceToken.totalSupply(); ++ compatibleAssert(sourceSupplyBefore - amount == sourceSupplyAfter); ++ } catch { ++ // 6 ++ compatibleAssert(address(destinationToken) == address(sourceToken) || sourceBalanceBefore < amount); + } ++ } + -+ return tokenReportExpirySeconds[token]; ++ /// @custom:property-id 11 ++ /// @custom:property relayERC20 increases the token's totalSupply in the destination chain exactly by the input ++ /// amount ++ /// @custom:property-id 27 ++ /// @custom:property relayERC20 increases sender's balance in the destination chain exactly by the input amount ++ /// @custom:property-id 7 ++ /// @custom:property calls to relayERC20 always succeed as long as the cross-domain caller is valid ++ function fuzz_relayERC20(uint256 messageIndex) external { ++ MockL2ToL2CrossDomainMessenger.CrossChainMessage memory messageToRelay = MESSENGER.messageQueue(messageIndex); ++ OptimismSuperchainERC20 destinationToken = OptimismSuperchainERC20(messageToRelay.crossDomainMessageSender); ++ uint256 destinationSupplyBefore = destinationToken.totalSupply(); ++ uint256 destinationBalanceBefore = destinationToken.balanceOf(messageToRelay.recipient); ++ ++ try MESSENGER.relayMessageFromQueue(messageIndex) { ++ bytes32 deploySalt = MESSENGER.superTokenInitDeploySalts(address(destinationToken)); ++ (bool success, uint256 currentlyInTransit) = ghost_tokensInTransit.tryGet(deploySalt); ++ // if sendERC20 didnt intialize this, then test suite is broken ++ compatibleAssert(success); ++ ghost_tokensInTransit.set(deploySalt, currentlyInTransit - messageToRelay.amount); ++ // 11 ++ compatibleAssert(destinationSupplyBefore + messageToRelay.amount == destinationToken.totalSupply()); ++ // 27 ++ compatibleAssert( ++ destinationBalanceBefore + messageToRelay.amount == destinationToken.balanceOf(messageToRelay.recipient) ++ ); ++ } catch { ++ // 7 ++ compatibleAssert(false); ++ } + } + -+ /** -+ * @notice Checks if a report exists for a specified rateFeedId from a given oracle. -+ * @dev Does not take the equivalentTokens mapping into account. -+ * For that, the underlying token should be queried. -+ * @param token The token for which the report should be checked. -+ * @param oracle The oracle whose report should be checked. -+ * @return bool True if a report exists, false otherwise. -+ */ -+ function reportExists(address token, address oracle) internal view returns (bool) { -+ return rates[token].contains(oracle) && timestamps[token].contains(oracle); ++ /// @custom:property-id 8 ++ /// @custom:property calls to sendERC20 with a value of zero dont modify accounting ++ // @notice is a subset of fuzz_sendERC20, so we'll just call it ++ // instead of re-implementing it. Keeping the function for visibility of the property. ++ function fuzz_sendZeroDoesNotModifyAccounting( ++ uint256 fromIndex, ++ uint256 recipientIndex, ++ uint256 destinationChainId ++ ) ++ external ++ { ++ fuzz_sendERC20(fromIndex, recipientIndex, destinationChainId, 0); + } + -+ /** -+ * @notice Removes an oracle value and updates the median. -+ * @dev Does not take the equivalentTokens mapping into account. -+ * For that, the underlying token should be queried. -+ * @param token The token for which the oracle report should be removed. -+ * @param oracle The oracle whose value should be removed. -+ * @dev This can be used to delete elements for oracles that have been removed. -+ * However, a > 1 elements reports list should always be maintained -+ */ -+ function removeReport(address token, address oracle) private { -+ if (numTimestamps(token) == 1 && reportExists(token, oracle)) return; -+ uint256 originalMedian = rates[token].getMedianValue(); -+ rates[token].remove(oracle); -+ timestamps[token].remove(oracle); -+ emit OracleReportRemoved(token, oracle); -+ uint256 newMedian = rates[token].getMedianValue(); -+ if (newMedian != originalMedian) { -+ emit MedianUpdated(token, newMedian); -+ if (address(breakerBox) != address(0)) { -+ breakerBox.checkAndSetBreakers(token); -+ } ++ /// @custom:property-id 9 ++ /// @custom:property calls to relayERC20 with a value of zero dont modify accounting ++ /// @custom:property-id 7 ++ /// @custom:property calls to relayERC20 always succeed as long as the cross-domain caller is valid ++ /// @notice cant call fuzz_RelayERC20 internally since that pops a ++ /// random message, which we cannot guarantee has a value of zero ++ function fuzz_relayZeroDoesNotModifyAccounting( ++ uint256 fromIndex, ++ uint256 recipientIndex ++ ) ++ external ++ withActor(msg.sender) ++ { ++ fromIndex = bound(fromIndex, 0, allSuperTokens.length - 1); ++ address recipient = getActorByRawIndex(recipientIndex); ++ OptimismSuperchainERC20 token = OptimismSuperchainERC20(allSuperTokens[fromIndex]); ++ uint256 balanceSenderBefore = token.balanceOf(currentActor()); ++ uint256 balanceRecipientBefore = token.balanceOf(recipient); ++ uint256 supplyBefore = token.totalSupply(); ++ ++ MESSENGER.setCrossDomainMessageSender(address(token)); ++ vm.prank(address(MESSENGER)); ++ try token.relayERC20(currentActor(), recipient, 0) { ++ MESSENGER.setCrossDomainMessageSender(address(0)); ++ } catch { ++ // should not revert because of 7, and if it *does* revert, I want the test suite ++ // to discard the sequence instead of potentially getting another ++ // error due to the crossDomainMessageSender being manually set ++ compatibleAssert(false); + } ++ uint256 balanceSenderAfter = token.balanceOf(currentActor()); ++ uint256 balanceRecipeintAfter = token.balanceOf(recipient); ++ uint256 supplyAfter = token.totalSupply(); ++ compatibleAssert(balanceSenderBefore == balanceSenderAfter); ++ compatibleAssert(balanceRecipientBefore == balanceRecipeintAfter); ++ compatibleAssert(supplyBefore == supplyAfter); + } +}
@@ -33734,9 +136349,9 @@
@@ -33751,7 +136366,7 @@
@@ -33761,158 +136376,155 @@
-
+140
+
+137
-0
-
diff --git OP/packages/contracts-bedrock/src/celo/stability/interfaces/IBreakerBox.sol CELO/packages/contracts-bedrock/src/celo/stability/interfaces/IBreakerBox.sol +
diff --git OP/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/fuzz/Protocol.unguided.t.sol CELO/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/fuzz/Protocol.unguided.t.sol new file mode 100644 -index 0000000000000000000000000000000000000000..26430da7a3bea5db65b04502a7057a0606b44d7d +index 0000000000000000000000000000000000000000..90cad38baa990ef9024a56e4333eea77dda049ab --- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/stability/interfaces/IBreakerBox.sol -@@ -0,0 +1,140 @@ ++++ CELO/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/fuzz/Protocol.unguided.t.sol +@@ -0,0 +1,137 @@ +// SPDX-License-Identifier: MIT -+pragma solidity >=0.5.13 <0.9.0; -+ -+/** -+ * @title Breaker Box Interface -+ * @notice Defines the basic interface for the Breaker Box -+ */ -+interface IBreakerBox { -+ /** -+ * @dev Used to keep track of the status of a breaker for a specific rate feed. -+ * -+ * - TradingMode: Represents the trading mode the breaker is in for a rate feed. -+ * This uses a bitmask approach, meaning each bit represents a -+ * different trading mode. The final trading mode of the rate feed -+ * is obtained by applying a logical OR operation to the TradingMode -+ * of all breakers associated with that rate feed. This allows multiple -+ * breakers to contribute to the final trading mode simultaneously. -+ * Possible values: -+ * 0: bidirectional trading. -+ * 1: inflow only. -+ * 2: outflow only. -+ * 3: trading halted. -+ * -+ * - LastUpdatedTime: Records the last time the breaker status was updated. This is -+ * used to manage cooldown periods before the breaker can be reset. -+ * -+ * - Enabled: Indicates whether the breaker is enabled for the associated rate feed. -+ */ -+ struct BreakerStatus { -+ uint8 tradingMode; -+ uint64 lastUpdatedTime; -+ bool enabled; ++pragma solidity ^0.8.25; ++ ++import { ProtocolHandler } from "../handlers/Protocol.t.sol"; ++import { EnumerableMap } from "@openzeppelin/contracts/utils/structs/EnumerableMap.sol"; ++import { OptimismSuperchainERC20 } from "src/L2/OptimismSuperchainERC20.sol"; ++import { CompatibleAssert } from "../helpers/CompatibleAssert.t.sol"; ++ ++// TODO: add fuzz_sendERC20 when we implement non-atomic bridging ++contract ProtocolUnguided is ProtocolHandler, CompatibleAssert { ++ using EnumerableMap for EnumerableMap.Bytes32ToUintMap; ++ ++ /// @custom:property-id 7 ++ /// @custom:property calls to relayERC20 always succeed as long as the cross-domain caller is valid ++ /// @notice this ensures actors cant simply call relayERC20 and get tokens, no matter the system state ++ /// but there's still some possible work on how hard we can bork the system state with handlers calling ++ /// the L2ToL2CrossDomainMessenger or bridge directly (pending on non-atomic bridging) ++ function fuzz_relayERC20( ++ uint256 tokenIndex, ++ address sender, ++ address crossDomainMessageSender, ++ address recipient, ++ uint256 amount ++ ) ++ external ++ { ++ MESSENGER.setCrossDomainMessageSender(crossDomainMessageSender); ++ address token = allSuperTokens[bound(tokenIndex, 0, allSuperTokens.length)]; ++ vm.prank(sender); ++ try OptimismSuperchainERC20(token).relayERC20(sender, recipient, amount) { ++ MESSENGER.setCrossDomainMessageSender(address(0)); ++ compatibleAssert(sender == address(MESSENGER)); ++ compatibleAssert(crossDomainMessageSender == token); ++ // this increases the supply across chains without a call to ++ // `mint` by the MESSENGER, so it kind of breaks an invariant, but ++ // let's walk around that: ++ bytes32 salt = MESSENGER.superTokenInitDeploySalts(token); ++ (, uint256 currentValue) = ghost_totalSupplyAcrossChains.tryGet(salt); ++ ghost_totalSupplyAcrossChains.set(salt, currentValue + amount); ++ } catch { ++ compatibleAssert(sender != address(MESSENGER) || crossDomainMessageSender != token); ++ MESSENGER.setCrossDomainMessageSender(address(0)); ++ } + } + -+ /** -+ * @notice Emitted when a new breaker is added to the breaker box. -+ * @param breaker The address of the breaker. -+ */ -+ event BreakerAdded(address indexed breaker); -+ -+ /** -+ * @notice Emitted when a breaker is removed from the breaker box. -+ * @param breaker The address of the breaker. -+ */ -+ event BreakerRemoved(address indexed breaker); -+ -+ /** -+ * @notice Emitted when a breaker is tripped by a rate feed. -+ * @param breaker The address of the breaker. -+ * @param rateFeedID The address of the rate feed. -+ */ -+ event BreakerTripped(address indexed breaker, address indexed rateFeedID); -+ -+ /** -+ * @notice Emitted when a new rate feed is added to the breaker box. -+ * @param rateFeedID The address of the rate feed. -+ */ -+ event RateFeedAdded(address indexed rateFeedID); -+ -+ /** -+ * @notice Emitted when dependencies for a rate feed are set. -+ * @param rateFeedID The address of the rate feed. -+ * @param dependencies The addresses of the dependendent rate feeds. -+ */ -+ event RateFeedDependenciesSet(address indexed rateFeedID, address[] indexed dependencies); -+ -+ /** -+ * @notice Emitted when a rate feed is removed from the breaker box. -+ * @param rateFeedID The address of the rate feed. -+ */ -+ event RateFeedRemoved(address indexed rateFeedID); -+ -+ /** -+ * @notice Emitted when the trading mode for a rate feed is updated -+ * @param rateFeedID The address of the rate feed. -+ * @param tradingMode The new trading mode. -+ */ -+ event TradingModeUpdated(address indexed rateFeedID, uint256 tradingMode); -+ -+ /** -+ * @notice Emitted after a reset attempt is successful. -+ * @param rateFeedID The address of the rate feed. -+ * @param breaker The address of the breaker. -+ */ -+ event ResetSuccessful(address indexed rateFeedID, address indexed breaker); -+ -+ /** -+ * @notice Emitted after a reset attempt fails when the -+ * rate feed fails the breakers reset criteria. -+ * @param rateFeedID The address of the rate feed. -+ * @param breaker The address of the breaker. -+ */ -+ event ResetAttemptCriteriaFail(address indexed rateFeedID, address indexed breaker); -+ -+ /** -+ * @notice Emitted after a reset attempt fails when cooldown time has not elapsed. -+ * @param rateFeedID The address of the rate feed. -+ * @param breaker The address of the breaker. -+ */ -+ event ResetAttemptNotCool(address indexed rateFeedID, address indexed breaker); -+ -+ /** -+ * @notice Emitted when the sortedOracles address is updated. -+ * @param newSortedOracles The address of the new sortedOracles. -+ */ -+ event SortedOraclesUpdated(address indexed newSortedOracles); -+ -+ /** -+ * @notice Emitted when the breaker is enabled or disabled for a rate feed. -+ * @param breaker The address of the breaker. -+ * @param rateFeedID The address of the rate feed. -+ * @param status Indicating the status. -+ */ -+ event BreakerStatusUpdated(address breaker, address rateFeedID, bool status); -+ -+ /** -+ * @notice Checks breakers for the rateFeedID and sets correct trading mode -+ * if any breakers are tripped or need to be reset. -+ * @param rateFeedID The address of the rate feed to run checks for. -+ */ -+ function checkAndSetBreakers(address rateFeedID) external; -+ -+ /** -+ * @notice Retrives an array of all breaker addresses. -+ */ -+ function getBreakers() external view returns (address[] memory); ++ /// @custom:property-id 6 ++ /// @custom:property calls to sendERC20 succeed as long as caller has enough balance ++ /// @custom:property-id 26 ++ /// @custom:property sendERC20 decreases sender balance in source chain exactly by the input amount ++ /// @custom:property-id 10 ++ /// @custom:property sendERC20 decreases total supply in source chain exactly by the input amount ++ function fuzz_sendERC20( ++ address sender, ++ address recipient, ++ uint256 fromIndex, ++ uint256 destinationChainId, ++ uint256 amount ++ ) ++ public ++ { ++ destinationChainId = bound(destinationChainId, 0, MAX_CHAINS - 1); ++ OptimismSuperchainERC20 sourceToken = OptimismSuperchainERC20(allSuperTokens[fromIndex]); ++ OptimismSuperchainERC20 destinationToken = ++ MESSENGER.crossChainMessageReceiver(address(sourceToken), destinationChainId); ++ bytes32 deploySalt = MESSENGER.superTokenInitDeploySalts(address(sourceToken)); ++ uint256 sourceBalanceBefore = sourceToken.balanceOf(sender); ++ uint256 sourceSupplyBefore = sourceToken.totalSupply(); ++ ++ vm.prank(sender); ++ try sourceToken.sendERC20(recipient, amount, destinationChainId) { ++ (, uint256 currentlyInTransit) = ghost_tokensInTransit.tryGet(deploySalt); ++ ghost_tokensInTransit.set(deploySalt, currentlyInTransit + amount); ++ // 26 ++ uint256 sourceBalanceAfter = sourceToken.balanceOf(sender); ++ compatibleAssert(sourceBalanceBefore - amount == sourceBalanceAfter); ++ // 10 ++ uint256 sourceSupplyAfter = sourceToken.totalSupply(); ++ compatibleAssert(sourceSupplyBefore - amount == sourceSupplyAfter); ++ } catch { ++ // 6 ++ compatibleAssert(address(destinationToken) == address(sourceToken) || sourceBalanceBefore < amount); ++ } ++ } + -+ /** -+ * @notice Checks if a breaker with the specified address has been added to the breaker box. -+ * @param breaker The address of the breaker to check; -+ * @return A bool indicating whether or not the breaker has been added. -+ */ -+ function isBreaker(address breaker) external view returns (bool); ++ /// @custom:property-id 12 ++ /// @custom:property supertoken total supply only increases on calls to mint() by the L2toL2StandardBridge ++ function fuzz_mint(uint256 tokenIndex, address to, address sender, uint256 amount) external { ++ address token = allSuperTokens[bound(tokenIndex, 0, allSuperTokens.length)]; ++ bytes32 salt = MESSENGER.superTokenInitDeploySalts(token); ++ amount = bound(amount, 0, type(uint256).max - OptimismSuperchainERC20(token).totalSupply()); ++ vm.prank(sender); ++ try OptimismSuperchainERC20(token).mint(to, amount) { ++ compatibleAssert(sender == BRIDGE); ++ (, uint256 currentValue) = ghost_totalSupplyAcrossChains.tryGet(salt); ++ ghost_totalSupplyAcrossChains.set(salt, currentValue + amount); ++ } catch { ++ compatibleAssert(sender != BRIDGE || to == address(0)); ++ } ++ } + -+ /** -+ * @notice Gets the trading mode for the specified rateFeedID. -+ * @param rateFeedID The address of the rate feed to retrieve the trading mode for. -+ */ -+ function getRateFeedTradingMode(address rateFeedID) external view returns (uint8 tradingMode); ++ /// @custom:property-id 13 ++ /// @custom:property supertoken total supply only increases on calls to mint() by the L2toL2StandardBridge ++ function fuzz_burn(uint256 tokenIndex, address from, address sender, uint256 amount) external { ++ address token = allSuperTokens[bound(tokenIndex, 0, allSuperTokens.length)]; ++ bytes32 salt = MESSENGER.superTokenInitDeploySalts(token); ++ uint256 senderBalance = OptimismSuperchainERC20(token).balanceOf(sender); ++ vm.prank(sender); ++ try OptimismSuperchainERC20(token).burn(from, amount) { ++ compatibleAssert(sender == BRIDGE); ++ (, uint256 currentValue) = ghost_totalSupplyAcrossChains.tryGet(salt); ++ ghost_totalSupplyAcrossChains.set(salt, currentValue - amount); ++ } catch { ++ compatibleAssert(sender != BRIDGE || senderBalance < amount); ++ } ++ } ++ ++ /// @custom:property-id 25 ++ /// @custom:property supertokens can't be reinitialized ++ function fuzz_initialize( ++ address sender, ++ uint256 tokenIndex, ++ address remoteToken, ++ string memory name, ++ string memory symbol, ++ uint8 decimals ++ ) ++ external ++ { ++ vm.prank(sender); ++ // revert is possible in bound, but is not part of the external call ++ try OptimismSuperchainERC20(allSuperTokens[bound(tokenIndex, 0, allSuperTokens.length)]).initialize( ++ remoteToken, name, symbol, decimals ++ ) { ++ compatibleAssert(false); ++ } catch { } ++ } +}
@@ -33920,9 +136532,9 @@
@@ -33937,7 +136549,7 @@
@@ -33947,25 +136559,195 @@
-
+7
+
+177
-0
-
diff --git OP/packages/contracts-bedrock/src/celo/stability/interfaces/IOracle.sol CELO/packages/contracts-bedrock/src/celo/stability/interfaces/IOracle.sol +
diff --git OP/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/handlers/Protocol.t.sol CELO/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/handlers/Protocol.t.sol new file mode 100644 -index 0000000000000000000000000000000000000000..b3ae66a92756c915ede5a6c5b1f57387b2edc254 +index 0000000000000000000000000000000000000000..921495b467ab1c3694e6a9f8dff2c79495a33a34 --- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/stability/interfaces/IOracle.sol -@@ -0,0 +1,7 @@ ++++ CELO/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/handlers/Protocol.t.sol +@@ -0,0 +1,177 @@ +// SPDX-License-Identifier: MIT -+pragma solidity >=0.5.13 <0.9.0; ++pragma solidity ^0.8.25; ++ ++import { TestBase } from "forge-std/Base.sol"; ++import { StdUtils } from "forge-std/StdUtils.sol"; ++ ++import { ERC1967Proxy } from "@openzeppelin/contracts-v5/proxy/ERC1967/ERC1967Proxy.sol"; ++import { EnumerableMap } from "@openzeppelin/contracts/utils/structs/EnumerableMap.sol"; ++import { OptimismSuperchainERC20 } from "src/L2/OptimismSuperchainERC20.sol"; ++import { OptimismSuperchainERC20ForToBProperties } from "../helpers/OptimismSuperchainERC20ForToBProperties.t.sol"; ++import { Predeploys } from "src/libraries/Predeploys.sol"; ++import { MockL2ToL2CrossDomainMessenger } from "../helpers/MockL2ToL2CrossDomainMessenger.t.sol"; ++import { Actors } from "../helpers/Actors.t.sol"; ++ ++contract ProtocolHandler is TestBase, StdUtils, Actors { ++ using EnumerableMap for EnumerableMap.Bytes32ToUintMap; ++ ++ uint8 public constant MAX_CHAINS = 4; ++ uint8 internal constant INITIAL_TOKENS = 1; ++ uint8 internal constant INITIAL_SUPERTOKENS = 1; ++ uint8 internal constant SUPERTOKEN_INITIAL_MINT = 100; ++ address internal constant BRIDGE = Predeploys.L2_STANDARD_BRIDGE; ++ MockL2ToL2CrossDomainMessenger internal constant MESSENGER = ++ MockL2ToL2CrossDomainMessenger(Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER); ++ OptimismSuperchainERC20 internal superchainERC20Impl; ++ // NOTE: having more options for this enables the fuzzer to configure ++ // different supertokens for the same remote token ++ string[] internal WORDS = ["TOKENS"]; ++ uint8[] internal DECIMALS = [6, 18]; ++ ++ struct TokenDeployParams { ++ uint8 remoteTokenIndex; ++ uint8 nameIndex; ++ uint8 symbolIndex; ++ uint8 decimalsIndex; ++ } + -+/// Possibly not final version -+interface IOracle { -+ function getExchangeRate(address token) external view returns (uint256 numerator, uint256 denominator); ++ address[] internal remoteTokens; ++ address[] internal allSuperTokens; ++ ++ /// @notice 'real' deploy salt => total supply sum across chains ++ EnumerableMap.Bytes32ToUintMap internal ghost_totalSupplyAcrossChains; ++ /// @notice 'real' deploy salt => tokens sendERC20'd but not yet relayERC20'd ++ EnumerableMap.Bytes32ToUintMap internal ghost_tokensInTransit; ++ ++ constructor() { ++ vm.etch(address(MESSENGER), address(new MockL2ToL2CrossDomainMessenger()).code); ++ superchainERC20Impl = new OptimismSuperchainERC20ForToBProperties(); ++ for (uint256 remoteTokenIndex; remoteTokenIndex < INITIAL_TOKENS; remoteTokenIndex++) { ++ _deployRemoteToken(); ++ for (uint256 supertokenChainId; supertokenChainId < INITIAL_SUPERTOKENS; supertokenChainId++) { ++ _deploySupertoken(remoteTokens[remoteTokenIndex], WORDS[0], WORDS[0], DECIMALS[0], supertokenChainId); ++ } ++ } ++ // integrate with all ToB properties using address(this) as the sender ++ addActor(address(this)); ++ } ++ ++ /// @notice the deploy params are _indexes_ to pick from a pre-defined array of options and limit ++ /// the amount of supertokens for a given remoteAsset that are incompatible between them, as ++ /// two supertokens have to share decimals, name, symbol and remoteAsset to be considered ++ /// the same asset, and therefore bridgable. ++ modifier validateTokenDeployParams(TokenDeployParams memory params) { ++ params.remoteTokenIndex = uint8(bound(params.remoteTokenIndex, 0, remoteTokens.length - 1)); ++ params.nameIndex = uint8(bound(params.nameIndex, 0, WORDS.length - 1)); ++ params.symbolIndex = uint8(bound(params.symbolIndex, 0, WORDS.length - 1)); ++ params.decimalsIndex = uint8(bound(params.decimalsIndex, 0, DECIMALS.length - 1)); ++ _; ++ } ++ ++ function handler_mockNewRemoteToken() external { ++ _deployRemoteToken(); ++ } ++ ++ /// @notice pick one already-deployed supertoken and mint an arbitrary amount of it ++ /// necessary so there is something to be bridged :D ++ /// TODO: will be replaced when testing the factories and `convert()` ++ function handler_mintSupertoken(uint256 index, uint96 amount) external withActor(msg.sender) { ++ index = bound(index, 0, allSuperTokens.length - 1); ++ address addr = allSuperTokens[index]; ++ vm.prank(BRIDGE); ++ OptimismSuperchainERC20(addr).mint(currentActor(), amount); ++ // currentValue will be zero if key is not present ++ (, uint256 currentValue) = ghost_totalSupplyAcrossChains.tryGet(MESSENGER.superTokenInitDeploySalts(addr)); ++ ghost_totalSupplyAcrossChains.set(MESSENGER.superTokenInitDeploySalts(addr), currentValue + amount); ++ } ++ ++ /// @notice The ToB properties don't preclude the need for this since they ++ /// always use address(this) as the caller, which won't get any balance ++ /// until it's transferred to it somehow ++ function handler_supERC20Transfer( ++ uint256 tokenIndex, ++ uint256 toIndex, ++ uint256 amount ++ ) ++ external ++ withActor(msg.sender) ++ { ++ vm.prank(currentActor()); ++ OptimismSuperchainERC20(allSuperTokens[bound(tokenIndex, 0, allSuperTokens.length)]).transfer( ++ getActorByRawIndex(toIndex), amount ++ ); ++ } ++ ++ function handler_supERC20TransferFrom( ++ uint256 tokenIndex, ++ uint256 fromIndex, ++ uint256 toIndex, ++ uint256 amount ++ ) ++ external ++ withActor(msg.sender) ++ { ++ vm.prank(currentActor()); ++ OptimismSuperchainERC20(allSuperTokens[bound(tokenIndex, 0, allSuperTokens.length)]).transferFrom( ++ getActorByRawIndex(fromIndex), getActorByRawIndex(toIndex), amount ++ ); ++ } ++ ++ function handler_supERC20Approve( ++ uint256 tokenIndex, ++ uint256 spenderIndex, ++ uint256 amount ++ ) ++ external ++ withActor(msg.sender) ++ { ++ vm.prank(currentActor()); ++ OptimismSuperchainERC20(allSuperTokens[bound(tokenIndex, 0, allSuperTokens.length)]).approve( ++ getActorByRawIndex(spenderIndex), amount ++ ); ++ } ++ ++ /// @notice deploy a remote token, that supertokens will be a representation of. They are never called, so there ++ /// is no need to actually deploy a contract for them ++ function _deployRemoteToken() internal { ++ // make sure they don't conflict with predeploys/preinstalls/precompiles/other tokens ++ remoteTokens.push(address(uint160(1000 + remoteTokens.length))); ++ } ++ ++ /// @notice deploy a new supertoken representing remoteToken ++ /// remoteToken, name, symbol and decimals determine the 'real' deploy salt ++ /// and supertokens sharing it are interoperable between them ++ /// we however use the chainId as part of the deploy salt to mock the ability of ++ /// supertokens to exist on different chains on a single EVM. ++ function _deploySupertoken( ++ address remoteToken, ++ string memory name, ++ string memory symbol, ++ uint8 decimals, ++ uint256 chainId ++ ) ++ internal ++ returns (OptimismSuperchainERC20 supertoken) ++ { ++ // this salt would be used in production. Tokens sharing it will be bridgable with each other ++ bytes32 realSalt = keccak256(abi.encode(remoteToken, name, symbol, decimals)); ++ // Foundry invariant erroneously show other unrelated invariant breaking ++ // when this deployment fails due to a create2 collision, so we revert eagerly instead ++ require(MESSENGER.superTokenAddresses(chainId, realSalt) == address(0), "skip duplicate deployment"); ++ ++ // what we use in the tests to walk around two contracts needing two different addresses ++ // tbf we could be using CREATE1, but this feels more verbose ++ bytes32 hackySalt = keccak256(abi.encode(remoteToken, name, symbol, decimals, chainId)); ++ supertoken = OptimismSuperchainERC20( ++ address( ++ // TODO: Use the SuperchainERC20 Beacon Proxy ++ new ERC1967Proxy{ salt: hackySalt }( ++ address(superchainERC20Impl), ++ abi.encodeCall(OptimismSuperchainERC20.initialize, (remoteToken, name, symbol, decimals)) ++ ) ++ ) ++ ); ++ MESSENGER.registerSupertoken(realSalt, chainId, address(supertoken)); ++ allSuperTokens.push(address(supertoken)); ++ } +}
@@ -33973,9 +136755,9 @@
@@ -33990,7 +136772,7 @@
@@ -34000,32 +136782,56 @@
-
+14
+
+38
-0
-
diff --git OP/packages/contracts-bedrock/src/celo/stability/interfaces/ISortedOracles.sol CELO/packages/contracts-bedrock/src/celo/stability/interfaces/ISortedOracles.sol +
diff --git OP/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/helpers/Actors.t.sol CELO/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/helpers/Actors.t.sol new file mode 100644 -index 0000000000000000000000000000000000000000..ecea4210cd40e4fb48a7a101b74625ff9746edcc +index 0000000000000000000000000000000000000000..3a7400667518f345a9adaed4d785c45964833164 --- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/stability/interfaces/ISortedOracles.sol -@@ -0,0 +1,14 @@ ++++ CELO/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/helpers/Actors.t.sol +@@ -0,0 +1,38 @@ +// SPDX-License-Identifier: MIT -+pragma solidity ^0.8.15; ++pragma solidity ^0.8.25; ++ ++import { StdUtils } from "forge-std/StdUtils.sol"; ++ ++/// @notice helper for tracking actors, taking advantage of the fuzzer already using several `msg.sender`s ++contract Actors is StdUtils { ++ mapping(address => bool) private _isActor; ++ address[] private _actors; ++ address private _currentActor; ++ ++ /// @notice register an actor if it's not already registered ++ /// usually called with msg.sender as a parameter, to track the actors ++ /// already provided by the fuzzer ++ modifier withActor(address who) { ++ addActor(who); ++ _currentActor = who; ++ _; ++ } + -+interface ISortedOracles { -+ function addOracle(address, address) external; -+ function removeOracle(address, address, uint256) external; -+ function report(address, uint256, address, address) external; -+ function removeExpiredReports(address, uint256) external; -+ function isOldestReportExpired(address token) external view returns (bool, address); -+ function numRates(address) external view returns (uint256); -+ function medianRate(address) external view returns (uint256, uint256); -+ function numTimestamps(address) external view returns (uint256); -+ function medianTimestamp(address) external view returns (uint256); ++ function addActor(address who) internal { ++ if (!_isActor[who]) { ++ _isActor[who] = true; ++ _actors.push(who); ++ } ++ } ++ ++ /// @notice get the currently configured actor, should equal msg.sender ++ function currentActor() internal view returns (address) { ++ return _currentActor; ++ } ++ ++ /// @notice get one of the actors by index, useful to get another random ++ /// actor than the one set as currentActor, to perform operations between them ++ function getActorByRawIndex(uint256 rawIndex) internal view returns (address) { ++ return _actors[bound(rawIndex, 0, _actors.length - 1)]; ++ } +}
@@ -34033,9 +136839,9 @@
@@ -34050,7 +136856,7 @@
@@ -34060,437 +136866,45 @@
-
+420
+
+28
-0
-
diff --git OP/packages/contracts-bedrock/src/celo/testing/FeeCurrency.sol CELO/packages/contracts-bedrock/src/celo/testing/FeeCurrency.sol +
diff --git OP/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/helpers/CompatibleAssert.t.sol CELO/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/helpers/CompatibleAssert.t.sol new file mode 100644 -index 0000000000000000000000000000000000000000..fd00f42c01bbb45a455790ec9e7cd3d181742319 +index 0000000000000000000000000000000000000000..4e69c94c85852024aa5d9e48f64166c9fb6756e5 --- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/testing/FeeCurrency.sol -@@ -0,0 +1,420 @@ -+// SPDX-License-Identifier: MIT -+// Modified from OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/ERC20.sol) -+ -+pragma solidity ^0.8.0; -+ -+import "../../../lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; -+import "../../../lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol"; -+import "../../../lib/openzeppelin-contracts/contracts/utils/Context.sol"; -+ -+import "../CalledByVm.sol"; -+ -+/** -+ * @dev Implementation of the {IERC20} interface + Celo debit/creditGasFees. -+ * -+ * This implementation is agnostic to the way tokens are created. This means -+ * that a supply mechanism has to be added in a derived contract using {_mint}. -+ * For a generic mechanism see {ERC20PresetMinterPauser}. -+ * -+ * TIP: For a detailed writeup see our guide -+ * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How -+ * to implement supply mechanisms]. -+ * -+ * We have followed general OpenZeppelin Contracts guidelines: functions revert -+ * instead returning `false` on failure. This behavior is nonetheless -+ * conventional and does not conflict with the expectations of ERC20 -+ * applications. -+ * -+ * Additionally, an {Approval} event is emitted on calls to {transferFrom}. -+ * This allows applications to reconstruct the allowance for all accounts just -+ * by listening to said events. Other implementations of the EIP may not emit -+ * these events, as it isn't required by the specification. -+ * -+ * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} -+ * functions have been added to mitigate the well-known issues around setting -+ * allowances. See {IERC20-approve}. -+ */ -+contract FeeCurrency is Context, IERC20, IERC20Metadata, CalledByVm { -+ mapping(address => uint256) private _balances; -+ -+ mapping(address => mapping(address => uint256)) private _allowances; -+ -+ uint256 private _totalSupply; -+ -+ string private _name; -+ string private _symbol; -+ -+ /** -+ * @dev Sets the values for {name} and {symbol}. -+ * -+ * The default value of {decimals} is 18. To select a different value for -+ * {decimals} you should overload it. -+ * -+ * All two of these values are immutable: they can only be set once during -+ * construction. -+ */ -+ constructor(string memory name_, string memory symbol_) { -+ _name = name_; -+ _symbol = symbol_; -+ } -+ -+ /** -+ * @dev Returns the name of the token. -+ */ -+ function name() public view virtual override returns (string memory) { -+ return _name; -+ } -+ -+ /** -+ * @dev Returns the symbol of the token, usually a shorter version of the -+ * name. -+ */ -+ function symbol() public view virtual override returns (string memory) { -+ return _symbol; -+ } -+ -+ /** -+ * @dev Returns the number of decimals used to get its user representation. -+ * For example, if `decimals` equals `2`, a balance of `505` tokens should -+ * be displayed to a user as `5.05` (`505 / 10 ** 2`). -+ * -+ * Tokens usually opt for a value of 18, imitating the relationship between -+ * Ether and Wei. This is the value {ERC20} uses, unless this function is -+ * overridden; -+ * -+ * NOTE: This information is only used for _display_ purposes: it in -+ * no way affects any of the arithmetic of the contract, including -+ * {IERC20-balanceOf} and {IERC20-transfer}. -+ */ -+ function decimals() public view virtual override returns (uint8) { -+ return 18; -+ } -+ -+ /** -+ * @dev See {IERC20-totalSupply}. -+ */ -+ function totalSupply() public view virtual override returns (uint256) { -+ return _totalSupply; -+ } -+ -+ /** -+ * @dev See {IERC20-balanceOf}. -+ */ -+ function balanceOf(address account) public view virtual override returns (uint256) { -+ return _balances[account]; -+ } -+ -+ /** -+ * @dev See {IERC20-transfer}. -+ * -+ * Requirements: -+ * -+ * - `to` cannot be the zero address. -+ * - the caller must have a balance of at least `amount`. -+ */ -+ function transfer(address to, uint256 amount) public virtual override returns (bool) { -+ address owner = _msgSender(); -+ _transfer(owner, to, amount); -+ return true; -+ } -+ -+ /** -+ * @dev See {IERC20-allowance}. -+ */ -+ function allowance(address owner, address spender) public view virtual override returns (uint256) { -+ return _allowances[owner][spender]; -+ } -+ -+ /** -+ * @dev See {IERC20-approve}. -+ * -+ * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on -+ * `transferFrom`. This is semantically equivalent to an infinite approval. -+ * -+ * Requirements: -+ * -+ * - `spender` cannot be the zero address. -+ */ -+ function approve(address spender, uint256 amount) public virtual override returns (bool) { -+ address owner = _msgSender(); -+ _approve(owner, spender, amount); -+ return true; -+ } -+ -+ /** -+ * @dev See {IERC20-transferFrom}. -+ * -+ * Emits an {Approval} event indicating the updated allowance. This is not -+ * required by the EIP. See the note at the beginning of {ERC20}. -+ * -+ * NOTE: Does not update the allowance if the current allowance -+ * is the maximum `uint256`. -+ * -+ * Requirements: -+ * -+ * - `from` and `to` cannot be the zero address. -+ * - `from` must have a balance of at least `amount`. -+ * - the caller must have allowance for ``from``'s tokens of at least -+ * `amount`. -+ */ -+ function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) { -+ address spender = _msgSender(); -+ _spendAllowance(from, spender, amount); -+ _transfer(from, to, amount); -+ return true; -+ } -+ -+ /** -+ * @dev Atomically increases the allowance granted to `spender` by the caller. -+ * -+ * This is an alternative to {approve} that can be used as a mitigation for -+ * problems described in {IERC20-approve}. -+ * -+ * Emits an {Approval} event indicating the updated allowance. -+ * -+ * Requirements: -+ * -+ * - `spender` cannot be the zero address. -+ */ -+ function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { -+ address owner = _msgSender(); -+ _approve(owner, spender, allowance(owner, spender) + addedValue); -+ return true; -+ } -+ -+ /** -+ * @dev Atomically decreases the allowance granted to `spender` by the caller. -+ * -+ * This is an alternative to {approve} that can be used as a mitigation for -+ * problems described in {IERC20-approve}. -+ * -+ * Emits an {Approval} event indicating the updated allowance. -+ * -+ * Requirements: -+ * -+ * - `spender` cannot be the zero address. -+ * - `spender` must have allowance for the caller of at least -+ * `subtractedValue`. -+ */ -+ function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { -+ address owner = _msgSender(); -+ uint256 currentAllowance = allowance(owner, spender); -+ require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); -+ unchecked { -+ _approve(owner, spender, currentAllowance - subtractedValue); -+ } -+ -+ return true; -+ } -+ -+ /** -+ * @dev Moves `amount` of tokens from `from` to `to`. -+ * -+ * This internal function is equivalent to {transfer}, and can be used to -+ * e.g. implement automatic token fees, slashing mechanisms, etc. -+ * -+ * Emits a {Transfer} event. -+ * -+ * Requirements: -+ * -+ * - `from` cannot be the zero address. -+ * - `to` cannot be the zero address. -+ * - `from` must have a balance of at least `amount`. -+ */ -+ function _transfer(address from, address to, uint256 amount) internal virtual { -+ require(from != address(0), "ERC20: transfer from the zero address"); -+ require(to != address(0), "ERC20: transfer to the zero address"); -+ -+ _beforeTokenTransfer(from, to, amount); -+ -+ uint256 fromBalance = _balances[from]; -+ require(fromBalance >= amount, "ERC20: transfer amount exceeds balance"); -+ unchecked { -+ _balances[from] = fromBalance - amount; -+ } -+ _balances[to] += amount; -+ -+ emit Transfer(from, to, amount); -+ -+ _afterTokenTransfer(from, to, amount); -+ } -+ -+ /** -+ * @dev Creates `amount` tokens and assigns them to `account`, increasing -+ * the total supply. -+ * -+ * Emits a {Transfer} event with `from` set to the zero address. -+ * -+ * Requirements: -+ * -+ * - `account` cannot be the zero address. -+ */ -+ function _mint(address account, uint256 amount) internal virtual { -+ require(account != address(0), "ERC20: mint to the zero address"); -+ -+ _beforeTokenTransfer(address(0), account, amount); -+ -+ _totalSupply += amount; -+ _balances[account] += amount; -+ emit Transfer(address(0), account, amount); -+ -+ _afterTokenTransfer(address(0), account, amount); -+ } -+ -+ /** -+ * @dev Destroys `amount` tokens from `account`, reducing the -+ * total supply. -+ * -+ * Emits a {Transfer} event with `to` set to the zero address. -+ * -+ * Requirements: -+ * -+ * - `account` cannot be the zero address. -+ * - `account` must have at least `amount` tokens. -+ */ -+ function _burn(address account, uint256 amount) internal virtual { -+ require(account != address(0), "ERC20: burn from the zero address"); -+ -+ _beforeTokenTransfer(account, address(0), amount); -+ -+ uint256 accountBalance = _balances[account]; -+ require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); -+ unchecked { -+ _balances[account] = accountBalance - amount; -+ } -+ _totalSupply -= amount; -+ -+ emit Transfer(account, address(0), amount); -+ -+ _afterTokenTransfer(account, address(0), amount); -+ } -+ -+ /** -+ * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. -+ * -+ * This internal function is equivalent to `approve`, and can be used to -+ * e.g. set automatic allowances for certain subsystems, etc. -+ * -+ * Emits an {Approval} event. -+ * -+ * Requirements: -+ * -+ * - `owner` cannot be the zero address. -+ * - `spender` cannot be the zero address. -+ */ -+ function _approve(address owner, address spender, uint256 amount) internal virtual { -+ require(owner != address(0), "ERC20: approve from the zero address"); -+ require(spender != address(0), "ERC20: approve to the zero address"); -+ -+ _allowances[owner][spender] = amount; -+ emit Approval(owner, spender, amount); -+ } -+ -+ /** -+ * @dev Updates `owner` s allowance for `spender` based on spent `amount`. -+ * -+ * Does not update the allowance amount in case of infinite allowance. -+ * Revert if not enough allowance is available. -+ * -+ * Might emit an {Approval} event. -+ */ -+ function _spendAllowance(address owner, address spender, uint256 amount) internal virtual { -+ uint256 currentAllowance = allowance(owner, spender); -+ if (currentAllowance != type(uint256).max) { -+ require(currentAllowance >= amount, "ERC20: insufficient allowance"); -+ unchecked { -+ _approve(owner, spender, currentAllowance - amount); -+ } -+ } -+ } ++++ CELO/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/helpers/CompatibleAssert.t.sol +@@ -0,0 +1,28 @@ ++// SPDX-License-Identifier: GPL-3 ++pragma solidity ^0.8.24; + -+ /** -+ * @dev Hook that is called before any transfer of tokens. This includes -+ * minting and burning. -+ * -+ * Calling conditions: -+ * -+ * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens -+ * will be transferred to `to`. -+ * - when `from` is zero, `amount` tokens will be minted for `to`. -+ * - when `to` is zero, `amount` of ``from``'s tokens will be burned. -+ * - `from` and `to` are never both zero. -+ * -+ * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. -+ */ -+ function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { } ++import { console } from "forge-std/console.sol"; + -+ /** -+ * @dev Hook that is called after any transfer of tokens. This includes -+ * minting and burning. -+ * -+ * Calling conditions: -+ * -+ * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens -+ * has been transferred to `to`. -+ * - when `from` is zero, `amount` tokens have been minted for `to`. -+ * - when `to` is zero, `amount` of ``from``'s tokens have been burned. -+ * - `from` and `to` are never both zero. -+ * -+ * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. -+ */ -+ function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual { } ++/// @title CompatibleAssert ++/// @notice meant to add compatibility between medusa assertion tests and ++/// foundry invariant test's required architecture ++contract CompatibleAssert { ++ bool public failed; + -+ /** -+ * @notice Reserve balance for making payments for gas in this StableToken currency. -+ * @param from The account to reserve balance from -+ * @param value The amount of balance to reserve -+ * @dev Note that this function is called by the protocol when paying for tx fees in this -+ * currency. After the tx is executed, gas is refunded to the sender and credited to the -+ * various tx fee recipients via a call to `creditGasFees`. Note too that the events emitted -+ * by `creditGasFees` reflect the *net* gas fee payments for the transaction. -+ */ -+ function debitGasFees(address from, uint256 value) external onlyVm { -+ _balances[from] -= value; -+ _totalSupply -= value; ++ function compatibleAssert(bool condition) internal { ++ compatibleAssert(condition, ""); + } + -+ /** -+ * @notice Alternative function to credit balance after making payments -+ * for gas in this StableToken currency. -+ * @param from The account to debit balance from -+ * @param feeRecipient Coinbase address -+ * legacy param gatewayFeeRecipient Gateway address (UNUSED!) -+ * @param communityFund Community fund address -+ * @param tipTxFee Coinbase fee -+ * @param baseTxFee Community fund fee -+ * legacy param gatewayFee Gateway fee (UNUSED!) -+ * @dev Note that this function is called by the protocol when paying for tx fees in this -+ * currency. Before the tx is executed, gas is debited from the sender via a call to -+ * `debitGasFees`. Note too that the events emitted by `creditGasFees` reflect the *net* gas fee -+ * payments for the transaction. -+ */ -+ function creditGasFees( -+ address from, -+ address feeRecipient, -+ address, // gatewayFeeRecipient -+ address communityFund, -+ uint256 refund, -+ uint256 tipTxFee, -+ uint256, // gatewayFee -+ uint256 baseTxFee -+ ) -+ external -+ onlyVm -+ { -+ _balances[from] += refund; ++ function compatibleAssert(bool condition, string memory message) internal { ++ if (!condition) { ++ if (bytes(message).length != 0) console.log("Assertion failed: ", message); ++ else console.log("Assertion failed"); + -+ refund += _creditGas(from, communityFund, baseTxFee); -+ refund += _creditGas(from, feeRecipient, tipTxFee); -+ _totalSupply += refund; -+ } ++ // for foundry to call & check ++ failed = true; + -+ function _creditGas(address from, address to, uint256 value) internal returns (uint256) { -+ if (to == address(0)) { -+ return 0; ++ // for medusa ++ assert(false); + } -+ _balances[to] += value; -+ emit Transfer(from, to, value); -+ return value; + } +}
@@ -34499,9 +136913,9 @@
@@ -34516,7 +136930,7 @@
@@ -34526,69 +136940,39 @@
-
+52
+
+22
-0
-
diff --git OP/packages/contracts-bedrock/src/celo/testing/MockSortedOracles.sol CELO/packages/contracts-bedrock/src/celo/testing/MockSortedOracles.sol +
diff --git OP/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/helpers/HandlerGetters.t.sol CELO/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/helpers/HandlerGetters.t.sol new file mode 100644 -index 0000000000000000000000000000000000000000..d51fa2a7c56c47dc97af8fd34c1db22b8832e7ec +index 0000000000000000000000000000000000000000..b081aa48c6bbc2f2d9e50d539f859aa37da0b8c6 --- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/testing/MockSortedOracles.sol -@@ -0,0 +1,52 @@ -+// SPDX-License-Identifier: MIT -+pragma solidity ^0.8.15; -+ -+import { IOracle } from "../interfaces/IOracle.sol"; -+ -+/** -+ * @title A mock SortedOracles for testing. -+ */ -+contract MockSortedOracles is IOracle { -+ uint256 public constant DENOMINATOR = 1000000000000000000000000; -+ mapping(address => uint256) public numerators; -+ mapping(address => uint256) public medianTimestamp; -+ mapping(address => uint256) public numRates; -+ mapping(address => bool) public expired; -+ -+ function setMedianRate(address token, uint256 numerator) external returns (bool) { -+ numerators[token] = numerator; -+ return true; -+ } -+ -+ function setMedianTimestamp(address token, uint256 timestamp) external { -+ medianTimestamp[token] = timestamp; -+ } -+ -+ function setMedianTimestampToNow(address token) external { -+ // solhint-disable-next-line not-rely-on-time -+ medianTimestamp[token] = uint128(block.timestamp); -+ } ++++ CELO/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/helpers/HandlerGetters.t.sol +@@ -0,0 +1,22 @@ ++// SPDX-License-Identifier: GPL-3 ++pragma solidity ^0.8.24; + -+ function setNumRates(address token, uint256 rate) external { -+ numRates[token] = rate; // This change may break something, TODO -+ } ++import { ProtocolHandler } from "../handlers/Protocol.t.sol"; ++import { EnumerableMap } from "@openzeppelin/contracts/utils/structs/EnumerableMap.sol"; + -+ function getExchangeRate(address token) external view returns (uint256 numerator, uint256 denominator) { -+ return medianRate(token); -+ } ++contract HandlerGetters is ProtocolHandler { ++ using EnumerableMap for EnumerableMap.Bytes32ToUintMap; + -+ function medianRate(address token) public view returns (uint256, uint256) { -+ if (numerators[token] > 0) { -+ return (numerators[token], DENOMINATOR); -+ } -+ return (0, 0); ++ function deploySaltsLength() external view returns (uint256 length) { ++ return ghost_totalSupplyAcrossChains.length(); + } + -+ function isOldestReportExpired(address token) public view returns (bool, address) { -+ return (expired[token], token); ++ function totalSupplyAcrossChainsAtIndex(uint256 index) external view returns (bytes32 salt, uint256 supply) { ++ return ghost_totalSupplyAcrossChains.at(index); + } + -+ function setOldestReportExpired(address token) public { -+ expired[token] = true; ++ function tokensInTransitForDeploySalt(bytes32 salt) external view returns (uint256 amount) { ++ (, amount) = ghost_tokensInTransit.tryGet(salt); ++ return amount; + } +}
@@ -34597,9 +136981,9 @@
@@ -34614,7 +136998,7 @@
@@ -34624,24 +137008,136 @@
-
+6
+
+118
-0
-
diff --git OP/packages/contracts-bedrock/src/celo/uniswap/interfaces/IUniswapV2FactoryMin.sol CELO/packages/contracts-bedrock/src/celo/uniswap/interfaces/IUniswapV2FactoryMin.sol +
diff --git OP/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/helpers/MockL2ToL2CrossDomainMessenger.t.sol CELO/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/helpers/MockL2ToL2CrossDomainMessenger.t.sol new file mode 100644 -index 0000000000000000000000000000000000000000..14c6495920a1ff49978917c124c7a7fd82d7c6b6 +index 0000000000000000000000000000000000000000..6eb1c30e67994e5a2c854fd5ab33c71861f30229 --- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/uniswap/interfaces/IUniswapV2FactoryMin.sol -@@ -0,0 +1,6 @@ -+// SPDX-License-Identifier: LGPL-3.0-only -+pragma solidity ^0.8.15; ++++ CELO/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/helpers/MockL2ToL2CrossDomainMessenger.t.sol +@@ -0,0 +1,118 @@ ++// SPDX-License-Identifier: MIT ++pragma solidity ^0.8.25; ++ ++import { OptimismSuperchainERC20 } from "src/L2/OptimismSuperchainERC20.sol"; ++import { SafeCall } from "src/libraries/SafeCall.sol"; ++ ++contract MockL2ToL2CrossDomainMessenger { ++ //////////////////////// ++ // type definitions // ++ //////////////////////// ++ struct CrossChainMessage { ++ address crossDomainMessageSender; ++ address crossDomainMessageSource; ++ bytes payload; ++ address recipient; ++ uint256 amount; ++ } + -+interface IUniswapV2FactoryMin { -+ function getPair(address tokenA, address tokenB) external view returns (address pair); ++ ///////////////////////////////////////////////////////// ++ // State vars mocking the L2toL2CrossDomainMessenger // ++ ///////////////////////////////////////////////////////// ++ address public crossDomainMessageSender; ++ address public crossDomainMessageSource; ++ ++ /////////////////////////////////////////////////// ++ // Helpers for cross-chain interaction mocking // ++ /////////////////////////////////////////////////// ++ mapping(address supertoken => bytes32 deploySalt) public superTokenInitDeploySalts; ++ mapping(uint256 chainId => mapping(bytes32 deploySalt => address supertoken)) public superTokenAddresses; ++ ++ CrossChainMessage[] private _messageQueue; ++ bool private _atomic; ++ ++ function messageQueue(uint256 rawIndex) external view returns (CrossChainMessage memory) { ++ return _messageQueue[rawIndex % _messageQueue.length]; ++ } ++ ++ function crossChainMessageReceiver( ++ address sender, ++ uint256 destinationChainId ++ ) ++ external ++ view ++ returns (OptimismSuperchainERC20) ++ { ++ return OptimismSuperchainERC20(superTokenAddresses[destinationChainId][superTokenInitDeploySalts[sender]]); ++ } ++ ++ function setCrossDomainMessageSender(address sender) external { ++ crossDomainMessageSender = sender; ++ } ++ ++ function registerSupertoken(bytes32 deploySalt, uint256 chainId, address token) external { ++ superTokenAddresses[chainId][deploySalt] = token; ++ superTokenInitDeploySalts[token] = deploySalt; ++ } ++ ++ function messageQueueLength() public view returns (uint256) { ++ return _messageQueue.length; ++ } ++ ++ function setAtomic(bool atomic) public { ++ _atomic = atomic; ++ } ++ ++ function relayMessageFromQueue(uint256 rawIndex) public { ++ uint256 index = rawIndex % _messageQueue.length; ++ CrossChainMessage memory message = _messageQueue[index]; ++ _messageQueue[index] = _messageQueue[_messageQueue.length - 1]; ++ _messageQueue.pop(); ++ _relayMessage(message); ++ } ++ ++ function _relayMessage(CrossChainMessage memory message) internal { ++ crossDomainMessageSender = message.crossDomainMessageSender; ++ crossDomainMessageSource = message.crossDomainMessageSource; ++ SafeCall.call(crossDomainMessageSender, 0, message.payload); ++ crossDomainMessageSender = address(0); ++ crossDomainMessageSource = address(0); ++ } ++ ++ //////////////////////////////////////////////////////// ++ // Functions mocking the L2toL2CrossDomainMessenger // ++ //////////////////////////////////////////////////////// ++ ++ /// @notice recipient will not be used since in normal execution it's the same ++ /// address on a different chain, but here we have to compute it to mock ++ /// cross-chain messaging ++ function sendMessage(uint256 chainId, address, /*recipient*/ bytes calldata data) external { ++ address crossChainRecipient = superTokenAddresses[chainId][superTokenInitDeploySalts[msg.sender]]; ++ if (crossChainRecipient == msg.sender) { ++ require(false, "same chain"); ++ } ++ (address recipient, uint256 amount) = _decodePayload(data); ++ ++ CrossChainMessage memory message = CrossChainMessage({ ++ crossDomainMessageSender: crossChainRecipient, ++ crossDomainMessageSource: msg.sender, ++ payload: data, ++ recipient: recipient, ++ amount: amount ++ }); ++ ++ if (_atomic) { ++ _relayMessage(message); ++ } else { ++ _messageQueue.push(message); ++ } ++ } ++ ++ //////////////////////// ++ // Internal helpers // ++ //////////////////////// ++ ++ function _decodePayload(bytes calldata payload) internal pure returns (address recipient, uint256 amount) { ++ (, recipient, amount) = abi.decode(payload[4:], (address, address, uint256)); ++ } +}
@@ -34649,9 +137145,9 @@
@@ -34666,7 +137162,7 @@
@@ -34676,40 +137172,30 @@
-
+22
+
+12
-0
-
diff --git OP/packages/contracts-bedrock/src/celo/uniswap/interfaces/IUniswapV2RouterMin.sol CELO/packages/contracts-bedrock/src/celo/uniswap/interfaces/IUniswapV2RouterMin.sol +
diff --git OP/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/helpers/OptimismSuperchainERC20ForToBProperties.t.sol CELO/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/helpers/OptimismSuperchainERC20ForToBProperties.t.sol new file mode 100644 -index 0000000000000000000000000000000000000000..f1755edb137d00b91696baa96ac6d44ae601ca28 +index 0000000000000000000000000000000000000000..9f80cda92fcc412d3bbee0858ac8af9bb7cf3e73 --- /dev/null -+++ CELO/packages/contracts-bedrock/src/celo/uniswap/interfaces/IUniswapV2RouterMin.sol -@@ -0,0 +1,22 @@ -+// SPDX-License-Identifier: LGPL-3.0-only -+pragma solidity ^0.8.15; ++++ CELO/packages/contracts-bedrock/test/invariants/OptimismSuperchainERC20/helpers/OptimismSuperchainERC20ForToBProperties.t.sol +@@ -0,0 +1,12 @@ ++// SPDX-License-Identifier: AGPL-3 ++pragma solidity ^0.8.25; + -+interface IUniswapV2RouterMin { -+ function factory() external pure returns (address); -+ function swapExactTokensForTokens( -+ uint256 amountIn, -+ uint256 amountOutMin, -+ address[] calldata path, -+ address to, -+ uint256 deadline -+ ) -+ external -+ returns (uint256[] memory amounts); -+ function getAmountsOut( -+ uint256 amountIn, -+ address[] calldata path -+ ) -+ external -+ view -+ returns (uint256[] memory amounts); ++import { OptimismSuperchainERC20 } from "src/L2/OptimismSuperchainERC20.sol"; ++ ++contract OptimismSuperchainERC20ForToBProperties is OptimismSuperchainERC20 { ++ /// @notice This is used by CryticERC20ExternalBasicProperties (only used ++ /// in Medusa testing campaign)to know which properties to test, and ++ /// remains here so Medusa and Foundry test campaigns can use a single ++ /// setup ++ bool public constant isMintableOrBurnable = true; +}
@@ -34717,8 +137203,8 @@
@@ -34744,46 +137230,185 @@
-
+4
-
-4
+
+28
+
-28
-
diff --git OP/packages/contracts-bedrock/test/kontrol/proofs/utils/DeploymentSummary.sol CELO/packages/contracts-bedrock/test/kontrol/proofs/utils/DeploymentSummary.sol -index 12227a7daeddb258500c56dae8090144b46628ca..4c084cd4dde592c64001a97b1fbd5812a9d39fcb 100644 +
diff --git OP/packages/contracts-bedrock/test/kontrol/proofs/utils/DeploymentSummary.sol CELO/packages/contracts-bedrock/test/kontrol/proofs/utils/DeploymentSummary.sol +index 12227a7daeddb258500c56dae8090144b46628ca..2fa5057acbd720884798b53b5059103ec5a74a4d 100644 --- OP/packages/contracts-bedrock/test/kontrol/proofs/utils/DeploymentSummary.sol +++ CELO/packages/contracts-bedrock/test/kontrol/proofs/utils/DeploymentSummary.sol -@@ -28,9 +28,9 @@ address internal constant l1StandardBridgeProxyAddress = 0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D; - address internal constant l2OutputOracleAddress = 0x19652082F846171168Daf378C4fD3ee85a0D4A60; +@@ -13,36 +13,36 @@ address private constant VM_ADDRESS = address(uint160(uint256(keccak256("hevm cheat code")))); + Vm private constant vm = Vm(VM_ADDRESS); +  + address internal constant addressManagerAddress = 0x50EEf481cae4250d252Ae577A09bF514f224C6C4; +- address internal constant anchorStateRegistryAddress = 0x63B71B96756C693f7065345fecD9b7843b3e7C57; ++ address internal constant anchorStateRegistryAddress = 0xdEC4D949Cf1A2e824eE4F8B12064e166b96171dD; + address internal constant anchorStateRegistryProxyAddress = 0x970670459734a83899773A0fd45941B5afC1200e; +- address internal constant delayedWETHAddress = 0x2A6347EDD3C7813CDE46DD7eA61FF1Cf2290BC05; ++ address internal constant delayedWETHAddress = 0xe49cED258137CC5E18fB9ABA2Aa14069263D8f49; + address internal constant delayedWETHProxyAddress = 0xEF179756ea6525AFade217cA5aB0b1b5CfE0fd92; +- address internal constant disputeGameFactoryAddress = 0x20B168142354Cee65a32f6D8cf3033E592299765; ++ address internal constant disputeGameFactoryAddress = 0x8efDa795511CBBdfFC9eeca1a5bF30f5B1E1ef9E; + address internal constant disputeGameFactoryProxyAddress = 0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d; +- address internal constant l1CrossDomainMessengerAddress = 0x094e6508ba9d9bf1ce421fff3dE06aE56e67901b; ++ address internal constant l1CrossDomainMessengerAddress = 0x357B6CdA94109749a0dA475ac1BFd395a61eb908; + address internal constant l1CrossDomainMessengerProxyAddress = 0xDeF3bca8c80064589E6787477FFa7Dd616B5574F; +- address internal constant l1ERC721BridgeAddress = 0x5C4F5e749A61a9503c4AAE8a9393e89609a0e804; ++ address internal constant l1ERC721BridgeAddress = 0xA4BD7E58A30ED0477fe7372883d09bF86619Bb66; + address internal constant l1ERC721BridgeProxyAddress = 0xD31598c909d9C935a9e35bA70d9a3DD47d4D5865; +- address internal constant l1StandardBridgeAddress = 0xb7900B27Be8f0E0fF65d1C3A4671e1220437dd2b; ++ address internal constant l1StandardBridgeAddress = 0x6cb2c88ABCd6391F9496f44BE27d5D3b247E0159; + address internal constant l1StandardBridgeProxyAddress = 0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D; +- address internal constant l2OutputOracleAddress = 0x19652082F846171168Daf378C4fD3ee85a0D4A60; ++ address internal constant l2OutputOracleAddress = 0x60d37db59d0D14f7EA5c7425A2C03244E08B162D; address internal constant l2OutputOracleProxyAddress = 0x39Af23E00F1e662025aA01b0cEdA19542B78DF99; - address internal constant mipsAddress = 0x444e09fe6D839273316a87002aB0EFBeA6fe7806; +- address internal constant mipsAddress = 0x444e09fe6D839273316a87002aB0EFBeA6fe7806; - address internal constant optimismMintableERC20FactoryAddress = 0x7c06d3a0a2f45e39E1798afbd9C3330971332a4F; -+ address internal constant optimismMintableERC20FactoryAddress = 0x9DAaD714C8eD63f5FE60B85e3694b40899486d58; ++ address internal constant mipsAddress = 0x180CBe2EBb9F37D3a3C542DDc2546Fd160555a73; ++ address internal constant optimismMintableERC20FactoryAddress = 0x79c3114E5f89266e2C8842871Bce16D4e5076b1e; address internal constant optimismMintableERC20FactoryProxyAddress = 0xc7B87b2b892EA5C3CfF47168881FE168C00377FB; - address internal constant optimismPortalAddress = 0xbdD90485FCbcac869D5b5752179815a3103d8131; -+ address internal constant optimismPortalAddress = 0xA4c07622d72648913221A0512Bdb95D0387ebe3B; - address internal constant optimismPortal2Address = 0xae5DadFc48928543f706a9E6Ce25c682aaD2b63b; +- address internal constant optimismPortal2Address = 0xae5DadFc48928543f706a9E6Ce25c682aaD2b63b; ++ address internal constant optimismPortalAddress = 0xb5A42f01EF5068F82C11fa1c4F9bBD4c8D346961; ++ address internal constant optimismPortal2Address = 0x150581358018524994Fc29800b1783637943b103; address internal constant optimismPortalProxyAddress = 0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4; address internal constant permissionedDelayedWETHProxyAddress = 0xd6EAF4c146261653EE059077B78ED088Add54309; +- address internal constant preimageOracleAddress = 0x373d916D11cce55b548F7051002e76BCFBD7a85d; +- address internal constant protocolVersionsAddress = 0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F; ++ address internal constant preimageOracleAddress = 0x7A9Eab4CE99d157AeE7A02E95b366E972a2D5b0b; ++ address internal constant protocolVersionsAddress = 0xa99F1ab91821747b76Ec0cDFA38368DF4Ba06E84; + address internal constant protocolVersionsProxyAddress = 0x4C52a6277b1B84121b3072C0c92b6Be0b7CC10F1; + address internal constant proxyAdminAddress = 0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1; + address internal constant safeProxyFactoryAddress = 0xA8452Ec99ce0C64f20701dB7dD3abDb607c00496; + address internal constant safeSingletonAddress = 0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3; +- address internal constant superchainConfigAddress = 0x068E44eB31e111028c41598E4535be7468674D0A; ++ address internal constant superchainConfigAddress = 0xDAf629c26abd7a84B6330c369887053B75dB2AF2; + address internal constant superchainConfigProxyAddress = 0x4f559F30f5eB88D635FDe1548C4267DB8FaB0351; +- address internal constant systemConfigAddress = 0x67866A5052E5302aaD08e9f352331fd8622eB6DC; ++ address internal constant systemConfigAddress = 0xd9CEcA938f039e427Edf626FA1f377d23A6b60c9; + address internal constant systemConfigProxyAddress = 0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6; + address internal constant systemOwnerSafeAddress = 0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD; + address internal constant acc33Address = 0xb6b1579AA54e2F61e621a40d5F2704D717B3544F; +@@ -107,7 +107,7 @@ slot = hex"0000000000000000000000000000000000000000000000000000000000000005"; + value = hex"0000000000000000000000000000000000000000000000000000000000000001"; + vm.store(systemOwnerSafeAddress, slot, value); + slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; +- value = hex"000000000000000000000000068e44eb31e111028c41598e4535be7468674d0a"; ++ value = hex"000000000000000000000000daf629c26abd7a84b6330c369887053b75db2af2"; + vm.store(superchainConfigProxyAddress, slot, value); + slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; + value = hex"0000000000000000000000000000000000000000000000000000000000000001"; +@@ -145,7 +145,7 @@ slot = hex"0000000000000000000000000000000000000000000000000000000000000005"; + value = hex"0000000000000000000000000000000000000000000000000000000000000002"; + vm.store(systemOwnerSafeAddress, slot, value); + slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; +- value = hex"000000000000000000000000fbfd64a6c0257f613fefce050aa30ecc3e3d7c3f"; ++ value = hex"000000000000000000000000a99f1ab91821747b76ec0cdfa38368df4ba06e84"; + vm.store(protocolVersionsProxyAddress, slot, value); + slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; + value = hex"0000000000000000000000000000000000000000000000000000000000000001"; @@ -430,7 +430,7 @@ slot = hex"0000000000000000000000000000000000000000000000000000000000000005"; value = hex"0000000000000000000000000000000000000000000000000000000000000003"; vm.store(systemOwnerSafeAddress, slot, value); slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; - value = hex"000000000000000000000000bdd90485fcbcac869d5b5752179815a3103d8131"; -+ value = hex"000000000000000000000000a4c07622d72648913221a0512bdb95d0387ebe3b"; ++ value = hex"000000000000000000000000b5a42f01ef5068f82c11fa1c4f9bbd4c8d346961"; vm.store(optimismPortalProxyAddress, slot, value); slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; value = hex"0000000000000000000000000000000000000000000000000000000000000001"; +@@ -460,7 +460,7 @@ slot = hex"0000000000000000000000000000000000000000000000000000000000000005"; + value = hex"0000000000000000000000000000000000000000000000000000000000000004"; + vm.store(systemOwnerSafeAddress, slot, value); + slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; +- value = hex"00000000000000000000000067866a5052e5302aad08e9f352331fd8622eb6dc"; ++ value = hex"000000000000000000000000d9ceca938f039e427edf626fa1f377d23a6b60c9"; + vm.store(systemConfigProxyAddress, slot, value); + slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; + value = hex"0000000000000000000000000000000000000000000000000000000000000001"; +@@ -529,7 +529,7 @@ slot = hex"0000000000000000000000000000000000000000000000000000000000000005"; + value = hex"0000000000000000000000000000000000000000000000000000000000000006"; + vm.store(systemOwnerSafeAddress, slot, value); + slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; +- value = hex"000000000000000000000000b7900b27be8f0e0ff65d1c3a4671e1220437dd2b"; ++ value = hex"0000000000000000000000006cb2c88abcd6391f9496f44be27d5d3b247e0159"; + vm.store(l1StandardBridgeProxyAddress, slot, value); + slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; + value = hex"0000000000000000000000000000000000000000000000000000000000000001"; +@@ -556,7 +556,7 @@ slot = hex"0000000000000000000000000000000000000000000000000000000000000005"; + value = hex"0000000000000000000000000000000000000000000000000000000000000007"; + vm.store(systemOwnerSafeAddress, slot, value); + slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; +- value = hex"0000000000000000000000005c4f5e749a61a9503c4aae8a9393e89609a0e804"; ++ value = hex"000000000000000000000000a4bd7e58a30ed0477fe7372883d09bf86619bb66"; + vm.store(l1ERC721BridgeProxyAddress, slot, value); + slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; + value = hex"0000000000000000000000000000000000000000000000000000000000000001"; @@ -580,7 +580,7 @@ slot = hex"0000000000000000000000000000000000000000000000000000000000000005"; value = hex"0000000000000000000000000000000000000000000000000000000000000008"; vm.store(systemOwnerSafeAddress, slot, value); slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; - value = hex"0000000000000000000000007c06d3a0a2f45e39e1798afbd9c3330971332a4f"; -+ value = hex"0000000000000000000000009daad714c8ed63f5fe60b85e3694b40899486d58"; ++ value = hex"00000000000000000000000079c3114e5f89266e2c8842871bce16d4e5076b1e"; vm.store(optimismMintableERC20FactoryProxyAddress, slot, value); slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; + value = hex"0000000000000000000000000000000000000000000000000000000000000001"; +@@ -610,7 +610,7 @@ slot = hex"0000000000000000000000000000000000000000000000000000000000000005"; + value = hex"000000000000000000000000000000000000000000000000000000000000000b"; + vm.store(systemOwnerSafeAddress, slot, value); + slot = hex"515216935740e67dfdda5cf8e248ea32b3277787818ab59153061ac875c9385e"; +- value = hex"000000000000000000000000094e6508ba9d9bf1ce421fff3de06ae56e67901b"; ++ value = hex"000000000000000000000000357b6cda94109749a0da475ac1bfd395a61eb908"; + vm.store(addressManagerAddress, slot, value); + slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; + value = hex"0000000000000000000000010000000000000000000000000000000000000000"; +@@ -640,7 +640,7 @@ slot = hex"0000000000000000000000000000000000000000000000000000000000000005"; + value = hex"000000000000000000000000000000000000000000000000000000000000000c"; + vm.store(systemOwnerSafeAddress, slot, value); + slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; +- value = hex"00000000000000000000000019652082f846171168daf378c4fd3ee85a0d4a60"; ++ value = hex"00000000000000000000000060d37db59d0d14f7ea5c7425a2c03244e08b162d"; + vm.store(l2OutputOracleProxyAddress, slot, value); + slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; + value = hex"0000000000000000000000000000000000000000000000000000000000000001"; +@@ -676,7 +676,7 @@ slot = hex"0000000000000000000000000000000000000000000000000000000000000005"; + value = hex"000000000000000000000000000000000000000000000000000000000000000d"; + vm.store(systemOwnerSafeAddress, slot, value); + slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; +- value = hex"00000000000000000000000020b168142354cee65a32f6d8cf3033e592299765"; ++ value = hex"0000000000000000000000008efda795511cbbdffc9eeca1a5bf30f5b1e1ef9e"; + vm.store(disputeGameFactoryProxyAddress, slot, value); + slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; + value = hex"0000000000000000000000000000000000000000000000000000000000000001"; +@@ -697,7 +697,7 @@ slot = hex"0000000000000000000000000000000000000000000000000000000000000005"; + value = hex"000000000000000000000000000000000000000000000000000000000000000e"; + vm.store(systemOwnerSafeAddress, slot, value); + slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; +- value = hex"0000000000000000000000002a6347edd3c7813cde46dd7ea61ff1cf2290bc05"; ++ value = hex"000000000000000000000000e49ced258137cc5e18fb9aba2aa14069263d8f49"; + vm.store(delayedWETHProxyAddress, slot, value); + slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; + value = hex"0000000000000000000000000000000000000000000000000000000000000001"; +@@ -721,7 +721,7 @@ slot = hex"0000000000000000000000000000000000000000000000000000000000000005"; + value = hex"000000000000000000000000000000000000000000000000000000000000000f"; + vm.store(systemOwnerSafeAddress, slot, value); + slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; +- value = hex"0000000000000000000000002a6347edd3c7813cde46dd7ea61ff1cf2290bc05"; ++ value = hex"000000000000000000000000e49ced258137cc5e18fb9aba2aa14069263d8f49"; + vm.store(permissionedDelayedWETHProxyAddress, slot, value); + slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; + value = hex"0000000000000000000000000000000000000000000000000000000000000001"; +@@ -745,7 +745,7 @@ slot = hex"0000000000000000000000000000000000000000000000000000000000000005"; + value = hex"0000000000000000000000000000000000000000000000000000000000000010"; + vm.store(systemOwnerSafeAddress, slot, value); + slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; +- value = hex"00000000000000000000000063b71b96756c693f7065345fecd9b7843b3e7c57"; ++ value = hex"000000000000000000000000dec4d949cf1a2e824ee4f8b12064e166b96171dd"; + vm.store(anchorStateRegistryProxyAddress, slot, value); + slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; value = hex"0000000000000000000000000000000000000000000000000000000000000001";
@@ -34791,8 +137416,8 @@
@@ -34818,43 +137443,88 @@
-
+2
-
-2
+
+17
+
-17
-
diff --git OP/packages/contracts-bedrock/test/kontrol/proofs/utils/DeploymentSummaryCode.sol CELO/packages/contracts-bedrock/test/kontrol/proofs/utils/DeploymentSummaryCode.sol -index 025c7485cd936316bc488968ce7be20ea19467aa..b068b311e6f9d8d52b630a6d8f2c4e0ad0105cc0 100644 +
diff --git OP/packages/contracts-bedrock/test/kontrol/proofs/utils/DeploymentSummaryCode.sol CELO/packages/contracts-bedrock/test/kontrol/proofs/utils/DeploymentSummaryCode.sol +index 025c7485cd936316bc488968ce7be20ea19467aa..153fef71fb87b79ce2cda84ebf9c8cfae7e9fbd6 100644 --- OP/packages/contracts-bedrock/test/kontrol/proofs/utils/DeploymentSummaryCode.sol +++ CELO/packages/contracts-bedrock/test/kontrol/proofs/utils/DeploymentSummaryCode.sol -@@ -47,7 +47,7 @@ hex"60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a"; +@@ -17,11 +17,11 @@ hex"60806040526004361061010e5760003560e01c8063860f7cda116100a557806399a88ec411610074578063b794726211610059578063b794726214610329578063f2fde38b14610364578063f3b7dead1461038457600080fd5b806399a88ec4146102e95780639b2ea4bd1461030957600080fd5b8063860f7cda1461026b5780638d52d4a01461028b5780638da5cb5b146102ab5780639623609d146102d657600080fd5b80633ab76e9f116100e15780633ab76e9f146101cc5780636bd9f516146101f9578063715018a6146102365780637eff275e1461024b57600080fd5b80630652b57a1461011357806307c8f7b014610135578063204e1c7a14610155578063238181ae1461019f575b600080fd5b34801561011f57600080fd5b5061013361012e3660046111f9565b6103a4565b005b34801561014157600080fd5b50610133610150366004611216565b6103f3565b34801561016157600080fd5b506101756101703660046111f9565b610445565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156101ab57600080fd5b506101bf6101ba3660046111f9565b61066b565b60405161019691906112ae565b3480156101d857600080fd5b506003546101759073ffffffffffffffffffffffffffffffffffffffff1681565b34801561020557600080fd5b506102296102143660046111f9565b60016020526000908152604090205460ff1681565b60405161019691906112f0565b34801561024257600080fd5b50610133610705565b34801561025757600080fd5b50610133610266366004611331565b610719565b34801561027757600080fd5b5061013361028636600461148c565b6108cc565b34801561029757600080fd5b506101336102a63660046114dc565b610903565b3480156102b757600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff16610175565b6101336102e436600461150e565b610977565b3480156102f557600080fd5b50610133610304366004611331565b610b8e565b34801561031557600080fd5b50610133610324366004611584565b610e1e565b34801561033557600080fd5b5060035474010000000000000000000000000000000000000000900460ff166040519015158152602001610196565b34801561037057600080fd5b5061013361037f3660046111f9565b610eb4565b34801561039057600080fd5b5061017561039f3660046111f9565b610f6b565b6103ac6110e1565b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6103fb6110e1565b6003805491151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff909216919091179055565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602052604081205460ff1681816002811115610481576104816112c1565b036104fc578273ffffffffffffffffffffffffffffffffffffffff16635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104f591906115cb565b9392505050565b6001816002811115610510576105106112c1565b03610560578273ffffffffffffffffffffffffffffffffffffffff1663aaf10f426040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b6002816002811115610574576105746112c1565b036105fe5760035473ffffffffffffffffffffffffffffffffffffffff8481166000908152600260205260409081902090517fbf40fac1000000000000000000000000000000000000000000000000000000008152919092169163bf40fac1916105e19190600401611635565b602060405180830381865afa1580156104d1573d6000803e3d6000fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f50726f787941646d696e3a20756e6b6e6f776e2070726f78792074797065000060448201526064015b60405180910390fd5b50919050565b60026020526000908152604090208054610684906115e8565b80601f01602080910402602001604051908101604052809291908181526020018280546106b0906115e8565b80156106fd5780601f106106d2576101008083540402835291602001916106fd565b820191906000526020600020905b8154815290600101906020018083116106e057829003601f168201915b505050505081565b61070d6110e1565b6107176000611162565b565b6107216110e1565b73ffffffffffffffffffffffffffffffffffffffff821660009081526001602052604081205460ff169081600281111561075d5761075d6112c1565b036107e9576040517f8f28397000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152841690638f283970906024015b600060405180830381600087803b1580156107cc57600080fd5b505af11580156107e0573d6000803e3d6000fd5b50505050505050565b60018160028111156107fd576107fd6112c1565b03610856576040517f13af403500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906313af4035906024016107b2565b600281600281111561086a5761086a6112c1565b036105fe576003546040517ff2fde38b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301529091169063f2fde38b906024016107b2565b505050565b6108d46110e1565b73ffffffffffffffffffffffffffffffffffffffff821660009081526002602052604090206108c78282611724565b61090b6110e1565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600160208190526040909120805483927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009091169083600281111561096e5761096e6112c1565b02179055505050565b61097f6110e1565b73ffffffffffffffffffffffffffffffffffffffff831660009081526001602052604081205460ff16908160028111156109bb576109bb6112c1565b03610a81576040517f4f1ef28600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff851690634f1ef286903490610a16908790879060040161183e565b60006040518083038185885af1158015610a34573d6000803e3d6000fd5b50505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610a7b9190810190611875565b50610b88565b610a8b8484610b8e565b60008473ffffffffffffffffffffffffffffffffffffffff163484604051610ab391906118ec565b60006040518083038185875af1925050503d8060008114610af0576040519150601f19603f3d011682016040523d82523d6000602084013e610af5565b606091505b5050905080610b86576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f50726f787941646d696e3a2063616c6c20746f2070726f78792061667465722060448201527f75706772616465206661696c6564000000000000000000000000000000000000606482015260840161065c565b505b50505050565b610b966110e1565b73ffffffffffffffffffffffffffffffffffffffff821660009081526001602052604081205460ff1690816002811115610bd257610bd26112c1565b03610c2b576040517f3659cfe600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152841690633659cfe6906024016107b2565b6001816002811115610c3f57610c3f6112c1565b03610cbe576040517f9b0b0fda0000000000000000000000000000000000000000000000000000000081527f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc600482015273ffffffffffffffffffffffffffffffffffffffff8381166024830152841690639b0b0fda906044016107b2565b6002816002811115610cd257610cd26112c1565b03610e165773ffffffffffffffffffffffffffffffffffffffff831660009081526002602052604081208054610d07906115e8565b80601f0160208091040260200160405190810160405280929190818152602001828054610d33906115e8565b8015610d805780601f10610d5557610100808354040283529160200191610d80565b820191906000526020600020905b815481529060010190602001808311610d6357829003601f168201915b50506003546040517f9b2ea4bd00000000000000000000000000000000000000000000000000000000815294955073ffffffffffffffffffffffffffffffffffffffff1693639b2ea4bd9350610dde92508591508790600401611908565b600060405180830381600087803b158015610df857600080fd5b505af1158015610e0c573d6000803e3d6000fd5b5050505050505050565b6108c7611940565b610e266110e1565b6003546040517f9b2ea4bd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911690639b2ea4bd90610e7e9085908590600401611908565b600060405180830381600087803b158015610e9857600080fd5b505af1158015610eac573d6000803e3d6000fd5b505050505050565b610ebc6110e1565b73ffffffffffffffffffffffffffffffffffffffff8116610f5f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161065c565b610f6881611162565b50565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602052604081205460ff1681816002811115610fa757610fa76112c1565b03610ff7578273ffffffffffffffffffffffffffffffffffffffff1663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b600181600281111561100b5761100b6112c1565b0361105b578273ffffffffffffffffffffffffffffffffffffffff1663893d20e86040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b600281600281111561106f5761106f6112c1565b036105fe57600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b60005473ffffffffffffffffffffffffffffffffffffffff163314610717576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161065c565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b73ffffffffffffffffffffffffffffffffffffffff81168114610f6857600080fd5b60006020828403121561120b57600080fd5b81356104f5816111d7565b60006020828403121561122857600080fd5b813580151581146104f557600080fd5b60005b8381101561125357818101518382015260200161123b565b83811115610b885750506000910152565b6000815180845261127c816020860160208601611238565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006104f56020830184611264565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b602081016003831061132b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b6000806040838503121561134457600080fd5b823561134f816111d7565b9150602083013561135f816111d7565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156113e0576113e061136a565b604052919050565b600067ffffffffffffffff8211156114025761140261136a565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600061144161143c846113e8565b611399565b905082815283838301111561145557600080fd5b828260208301376000602084830101529392505050565b600082601f83011261147d57600080fd5b6104f58383356020850161142e565b6000806040838503121561149f57600080fd5b82356114aa816111d7565b9150602083013567ffffffffffffffff8111156114c657600080fd5b6114d28582860161146c565b9150509250929050565b600080604083850312156114ef57600080fd5b82356114fa816111d7565b915060208301356003811061135f57600080fd5b60008060006060848603121561152357600080fd5b833561152e816111d7565b9250602084013561153e816111d7565b9150604084013567ffffffffffffffff81111561155a57600080fd5b8401601f8101861361156b57600080fd5b61157a8682356020840161142e565b9150509250925092565b6000806040838503121561159757600080fd5b823567ffffffffffffffff8111156115ae57600080fd5b6115ba8582860161146c565b925050602083013561135f816111d7565b6000602082840312156115dd57600080fd5b81516104f5816111d7565b600181811c908216806115fc57607f821691505b602082108103610665577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000602080835260008454611649816115e8565b8084870152604060018084166000811461166a57600181146116a2576116d0565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008516838a01528284151560051b8a010195506116d0565b896000528660002060005b858110156116c85781548b82018601529083019088016116ad565b8a0184019650505b509398975050505050505050565b601f8211156108c757600081815260208120601f850160051c810160208610156117055750805b601f850160051c820191505b81811015610eac57828155600101611711565b815167ffffffffffffffff81111561173e5761173e61136a565b6117528161174c84546115e8565b846116de565b602080601f8311600181146117a5576000841561176f5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555610eac565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156117f2578886015182559484019460019091019084016117d3565b508582101561182e57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b73ffffffffffffffffffffffffffffffffffffffff8316815260406020820152600061186d6040830184611264565b949350505050565b60006020828403121561188757600080fd5b815167ffffffffffffffff81111561189e57600080fd5b8201601f810184136118af57600080fd5b80516118bd61143c826113e8565b8181528560208385010111156118d257600080fd5b6118e3826020830160208601611238565b95945050505050565b600082516118fe818460208701611238565b9190910192915050565b60408152600061191b6040830185611264565b905073ffffffffffffffffffffffffffffffffffffffff831660208301529392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fdfea164736f6c634300080f000a"; + bytes internal constant superchainConfigProxyCode = + hex"60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a"; + bytes internal constant superchainConfigCode = +- hex"608060405234801561001057600080fd5b50600436106100885760003560e01c80635c975abb1161005b5780635c975abb146101255780636da663551461013d5780637fbf7b6a14610150578063c23a451a1461016657600080fd5b80633f4ba83a1461008d578063400ada7514610097578063452a9320146100aa57806354fd4d50146100dc575b600080fd5b61009561016e565b005b6100956100a5366004610746565b610294565b6100b261046d565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6101186040518060400160405280600581526020017f312e312e3000000000000000000000000000000000000000000000000000000081525081565b6040516100d39190610808565b61012d6104a6565b60405190151581526020016100d3565b61009561014b366004610851565b6104d6565b6101586105a4565b6040519081526020016100d3565b6101586105d2565b61017661046d565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610235576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f5375706572636861696e436f6e6669673a206f6e6c7920677561726469616e2060448201527f63616e20756e706175736500000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61026961026360017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b60009055565b6040517fa45f47fdea8a1efdd9029a5691c7f759c32b7c698632b563573e155625d1693390600090a1565b600054610100900460ff16158080156102b45750600054600160ff909116105b806102ce5750303b1580156102ce575060005460ff166001145b61035a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161022c565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156103b857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6103c18361061d565b8115610405576104056040518060400160405280601281526020017f496e697469616c697a65722070617573656400000000000000000000000000008152506106d8565b801561046857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b60006104a161049d60017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe69610920565b5490565b905090565b60006104a161049d60017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b6104de61046d565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610598576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f5375706572636861696e436f6e6669673a206f6e6c7920677561726469616e2060448201527f63616e2070617573650000000000000000000000000000000000000000000000606482015260840161022c565b6105a1816106d8565b50565b6105cf60017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b81565b6105cf60017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe69610920565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b9055565b61065061064b60017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe69610920565b829055565b60006040805173ffffffffffffffffffffffffffffffffffffffff841660208201527f7b743789cff01dafdeae47739925425aab5dfd02d0c8229e4a508bcd2b9f42bb9101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526106cd91610808565b60405180910390a250565b61070c61070660017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b60019055565b7fc32e6d5d6d1de257f64eac19ddb1f700ba13527983849c9486b1ab007ea283818160405161073b9190610808565b60405180910390a150565b6000806040838503121561075957600080fd5b823573ffffffffffffffffffffffffffffffffffffffff8116811461077d57600080fd5b91506020830135801515811461079257600080fd5b809150509250929050565b6000815180845260005b818110156107c3576020818501810151868301820152016107a7565b818111156107d5576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061081b602083018461079d565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561086357600080fd5b813567ffffffffffffffff8082111561087b57600080fd5b818401915084601f83011261088f57600080fd5b8135818111156108a1576108a1610822565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156108e7576108e7610822565b8160405282815287602084870101111561090057600080fd5b826020860160208301376000928101602001929092525095945050505050565b600082821015610959577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50039056fea164736f6c634300080f000a"; ++ hex"608060405234801561001057600080fd5b50600436106100885760003560e01c80635c975abb1161005b5780635c975abb146101255780636da663551461013d5780637fbf7b6a14610150578063c23a451a1461016657600080fd5b80633f4ba83a1461008d578063400ada7514610097578063452a9320146100aa57806354fd4d50146100dc575b600080fd5b61009561016e565b005b6100956100a5366004610746565b610294565b6100b261046d565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6101186040518060400160405280600c81526020017f312e312e312d626574612e31000000000000000000000000000000000000000081525081565b6040516100d39190610808565b61012d6104a6565b60405190151581526020016100d3565b61009561014b366004610851565b6104d6565b6101586105a4565b6040519081526020016100d3565b6101586105d2565b61017661046d565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610235576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f5375706572636861696e436f6e6669673a206f6e6c7920677561726469616e2060448201527f63616e20756e706175736500000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61026961026360017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b60009055565b6040517fa45f47fdea8a1efdd9029a5691c7f759c32b7c698632b563573e155625d1693390600090a1565b600054610100900460ff16158080156102b45750600054600160ff909116105b806102ce5750303b1580156102ce575060005460ff166001145b61035a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161022c565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156103b857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6103c18361061d565b8115610405576104056040518060400160405280601281526020017f496e697469616c697a65722070617573656400000000000000000000000000008152506106d8565b801561046857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b60006104a161049d60017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe69610920565b5490565b905090565b60006104a161049d60017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b6104de61046d565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610598576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f5375706572636861696e436f6e6669673a206f6e6c7920677561726469616e2060448201527f63616e2070617573650000000000000000000000000000000000000000000000606482015260840161022c565b6105a1816106d8565b50565b6105cf60017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b81565b6105cf60017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe69610920565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b9055565b61065061064b60017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe69610920565b829055565b60006040805173ffffffffffffffffffffffffffffffffffffffff841660208201527f7b743789cff01dafdeae47739925425aab5dfd02d0c8229e4a508bcd2b9f42bb9101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526106cd91610808565b60405180910390a250565b61070c61070660017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b60019055565b7fc32e6d5d6d1de257f64eac19ddb1f700ba13527983849c9486b1ab007ea283818160405161073b9190610808565b60405180910390a150565b6000806040838503121561075957600080fd5b823573ffffffffffffffffffffffffffffffffffffffff8116811461077d57600080fd5b91506020830135801515811461079257600080fd5b809150509250929050565b6000815180845260005b818110156107c3576020818501810151868301820152016107a7565b818111156107d5576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061081b602083018461079d565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561086357600080fd5b813567ffffffffffffffff8082111561087b57600080fd5b818401915084601f83011261088f57600080fd5b8135818111156108a1576108a1610822565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156108e7576108e7610822565b8160405282815287602084870101111561090057600080fd5b826020860160208301376000928101602001929092525095945050505050565b600082821015610959577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50039056fea164736f6c634300080f000a"; + bytes internal constant protocolVersionsProxyCode = + hex"60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a"; + bytes internal constant protocolVersionsCode = +- hex"608060405234801561001057600080fd5b50600436106100d45760003560e01c80638da5cb5b11610081578063f2fde38b1161005b578063f2fde38b146101b8578063f7d12760146101cb578063ffa1ad74146101d357600080fd5b80638da5cb5b14610180578063d798b1ac146101a8578063dc8452cd146101b057600080fd5b80635fd579af116100b25780635fd579af14610152578063715018a6146101655780637a1ac61e1461016d57600080fd5b80630457d6f2146100d9578063206a8300146100ee57806354fd4d5014610109575b600080fd5b6100ec6100e73660046108c3565b6101db565b005b6100f66101ef565b6040519081526020015b60405180910390f35b6101456040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516101009190610947565b6100ec6101603660046108c3565b61021d565b6100ec61022e565b6100ec61017b36600461098a565b610242565b60335460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610100565b6100f66103f7565b6100f6610430565b6100ec6101c63660046109bd565b610460565b6100f6610514565b6100f6600081565b6101e361055f565b6101ec816105e0565b50565b61021a60017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16109d8565b81565b61022561055f565b6101ec81610698565b61023661055f565b6102406000610712565b565b600054610100900460ff16158080156102625750600054600160ff909116105b8061027c5750303b15801561027c575060005460ff166001145b61030d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561036b57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610373610789565b61037c84610460565b610385836105e0565b61038e82610698565b80156103f157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b600061042b61042760017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6109d8565b5490565b905090565b600061042b61042760017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16109d8565b61046861055f565b73ffffffffffffffffffffffffffffffffffffffff811661050b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610304565b6101ec81610712565b61021a60017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6109d8565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b9055565b60335473ffffffffffffffffffffffffffffffffffffffff163314610240576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610304565b61061361060e60017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16109d8565b829055565b60008160405160200161062891815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060005b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be8360405161068c9190610947565b60405180910390a35050565b6106c661060e60017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6109d8565b6000816040516020016106db91815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529050600161065b565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16610820576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610304565b610240600054610100900460ff166108ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610304565b61024033610712565b6000602082840312156108d557600080fd5b5035919050565b6000815180845260005b81811015610902576020818501810151868301820152016108e6565b81811115610914576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061095a60208301846108dc565b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461098557600080fd5b919050565b60008060006060848603121561099f57600080fd5b6109a884610961565b95602085013595506040909401359392505050565b6000602082840312156109cf57600080fd5b61095a82610961565b600082821015610a11577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50039056fea164736f6c634300080f000a"; ++ hex"608060405234801561001057600080fd5b50600436106100d45760003560e01c80638da5cb5b11610081578063f2fde38b1161005b578063f2fde38b146101b8578063f7d12760146101cb578063ffa1ad74146101d357600080fd5b80638da5cb5b14610180578063d798b1ac146101a8578063dc8452cd146101b057600080fd5b80635fd579af116100b25780635fd579af14610152578063715018a6146101655780637a1ac61e1461016d57600080fd5b80630457d6f2146100d9578063206a8300146100ee57806354fd4d5014610109575b600080fd5b6100ec6100e73660046108c3565b6101db565b005b6100f66101ef565b6040519081526020015b60405180910390f35b6101456040518060400160405280600c81526020017f312e302e312d626574612e31000000000000000000000000000000000000000081525081565b6040516101009190610947565b6100ec6101603660046108c3565b61021d565b6100ec61022e565b6100ec61017b36600461098a565b610242565b60335460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610100565b6100f66103f7565b6100f6610430565b6100ec6101c63660046109bd565b610460565b6100f6610514565b6100f6600081565b6101e361055f565b6101ec816105e0565b50565b61021a60017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16109d8565b81565b61022561055f565b6101ec81610698565b61023661055f565b6102406000610712565b565b600054610100900460ff16158080156102625750600054600160ff909116105b8061027c5750303b15801561027c575060005460ff166001145b61030d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561036b57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610373610789565b61037c84610460565b610385836105e0565b61038e82610698565b80156103f157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b600061042b61042760017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6109d8565b5490565b905090565b600061042b61042760017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16109d8565b61046861055f565b73ffffffffffffffffffffffffffffffffffffffff811661050b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610304565b6101ec81610712565b61021a60017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6109d8565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b9055565b60335473ffffffffffffffffffffffffffffffffffffffff163314610240576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610304565b61061361060e60017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16109d8565b829055565b60008160405160200161062891815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060005b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be8360405161068c9190610947565b60405180910390a35050565b6106c661060e60017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6109d8565b6000816040516020016106db91815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529050600161065b565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16610820576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610304565b610240600054610100900460ff166108ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610304565b61024033610712565b6000602082840312156108d557600080fd5b5035919050565b6000815180845260005b81811015610902576020818501810151868301820152016108e6565b81811115610914576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061095a60208301846108dc565b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461098557600080fd5b919050565b60008060006060848603121561099f57600080fd5b6109a884610961565b95602085013595506040909401359392505050565b6000602082840312156109cf57600080fd5b61095a82610961565b600082821015610a11577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50039056fea164736f6c634300080f000a"; + bytes internal constant optimismPortalProxyCode = + hex"60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a"; + bytes internal constant systemConfigProxyCode = +@@ -45,33 +45,33 @@ hex"60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a"; + bytes internal constant anchorStateRegistryProxyCode = + hex"60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a"; bytes internal constant l1CrossDomainMessengerCode = - hex"60806040526004361061018b5760003560e01c80636425666b116100d6578063b1b1b2091161007f578063d764ad0b11610059578063d764ad0b1461049b578063db505d80146104ae578063ecc70428146104db57600080fd5b8063b1b1b2091461042b578063b28ade251461045b578063c0c53b8b1461047b57600080fd5b80638cbeeef2116100b05780638cbeeef2146102d05780639fce812c146103d0578063a4e7f8bd146103fb57600080fd5b80636425666b146103775780636e296e45146103a457806383a74074146103b957600080fd5b80633dbb202b1161013857806354fd4d501161011257806354fd4d50146102e65780635644cfdf1461033c5780635c975abb1461035257600080fd5b80633dbb202b146102935780633f827a5a146102a85780634c1d6a69146102d057600080fd5b80632828d7e8116101695780632828d7e81461022457806333d7e2bd1461023957806335e80ab31461026657600080fd5b8063028f85f7146101905780630c568498146101c35780630ff754ea146101d8575b600080fd5b34801561019c57600080fd5b506101a5601081565b60405167ffffffffffffffff90911681526020015b60405180910390f35b3480156101cf57600080fd5b506101a5603f81565b3480156101e457600080fd5b5060fc5473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101ba565b34801561023057600080fd5b506101a5604081565b34801561024557600080fd5b5060fd546101ff9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561027257600080fd5b5060fb546101ff9073ffffffffffffffffffffffffffffffffffffffff1681565b6102a66102a1366004611bdd565b610540565b005b3480156102b457600080fd5b506102bd600181565b60405161ffff90911681526020016101ba565b3480156102dc57600080fd5b506101a5619c4081565b3480156102f257600080fd5b5061032f6040518060400160405280600581526020017f322e342e3000000000000000000000000000000000000000000000000000000081525081565b6040516101ba9190611caf565b34801561034857600080fd5b506101a561138881565b34801561035e57600080fd5b5061036761083d565b60405190151581526020016101ba565b34801561038357600080fd5b5060fc546101ff9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156103b057600080fd5b506101ff6108d6565b3480156103c557600080fd5b506101a562030d4081565b3480156103dc57600080fd5b5060cf5473ffffffffffffffffffffffffffffffffffffffff166101ff565b34801561040757600080fd5b50610367610416366004611cc9565b60ce6020526000908152604090205460ff1681565b34801561043757600080fd5b50610367610446366004611cc9565b60cb6020526000908152604090205460ff1681565b34801561046757600080fd5b506101a5610476366004611ce2565b6109bd565b34801561048757600080fd5b506102a6610496366004611d36565b610a2b565b6102a66104a9366004611d81565b610ca2565b3480156104ba57600080fd5b5060cf546101ff9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156104e757600080fd5b5061053260cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b6040519081526020016101ba565b6105486115d3565b156105e05734156105e0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f43726f7373446f6d61696e4d657373656e6765723a2063616e6e6f742073656e60448201527f642076616c7565207769746820637573746f6d2067617320746f6b656e00000060648201526084015b60405180910390fd5b60cf546107129073ffffffffffffffffffffffffffffffffffffffff166106088585856109bd565b347fd764ad0b0000000000000000000000000000000000000000000000000000000061067460cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b338a34898c8c6040516024016106909796959493929190611e50565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611612565b8373ffffffffffffffffffffffffffffffffffffffff167fcb0f7ffd78f9aee47a248fae8db181db6eee833039123e026dcbff529522e52a33858561079760cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b866040516107a9959493929190611eaf565b60405180910390a260405134815233907f8ebb2ec2465bdb2a06a66fc37a0963af8a2a6a1479d81d56fdb8cbb98096d5469060200160405180910390a2505060cd80547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808216600101167fffff0000000000000000000000000000000000000000000000000000000000009091161790555050565b60fb54604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa1580156108ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108d19190611efd565b905090565b60cc5460009073ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2153016109a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f43726f7373446f6d61696e4d657373656e6765723a2078446f6d61696e4d657360448201527f7361676553656e646572206973206e6f7420736574000000000000000000000060648201526084016105d7565b5060cc5473ffffffffffffffffffffffffffffffffffffffff1690565b6000611388619c4080603f6109d9604063ffffffff8816611f4e565b6109e39190611f7e565b6109ee601088611f4e565b6109fb9062030d40611fcc565b610a059190611fcc565b610a0f9190611fcc565b610a199190611fcc565b610a239190611fcc565b949350505050565b6000547501000000000000000000000000000000000000000000900460ff1615808015610a76575060005460017401000000000000000000000000000000000000000090910460ff16105b80610aa85750303b158015610aa8575060005474010000000000000000000000000000000000000000900460ff166001145b610b34576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016105d7565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790558015610bba57600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000001790555b60fb805473ffffffffffffffffffffffffffffffffffffffff8087167fffffffffffffffffffffffff00000000000000000000000000000000000000009283161790925560fc805486841690831617905560fd805492851692909116919091179055610c397342000000000000000000000000000000000000076116ab565b8015610c9c57600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b610caa61083d565b15610d11576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f43726f7373446f6d61696e4d657373656e6765723a207061757365640000000060448201526064016105d7565b60f087901c60028110610dcc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f43726f7373446f6d61696e4d657373656e6765723a206f6e6c7920766572736960448201527f6f6e2030206f722031206d657373616765732061726520737570706f7274656460648201527f20617420746869732074696d6500000000000000000000000000000000000000608482015260a4016105d7565b8061ffff16600003610ec1576000610e1d878986868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508f92506117e7915050565b600081815260cb602052604090205490915060ff1615610ebf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f43726f7373446f6d61696e4d657373656e6765723a206c65676163792077697460448201527f6864726177616c20616c72656164792072656c6179656400000000000000000060648201526084016105d7565b505b6000610f07898989898989898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061180692505050565b9050610f11611829565b15610f4957853414610f2557610f25611ff8565b600081815260ce602052604090205460ff1615610f4457610f44611ff8565b61109b565b3415610ffd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605060248201527f43726f7373446f6d61696e4d657373656e6765723a2076616c7565206d75737460448201527f206265207a65726f20756e6c657373206d6573736167652069732066726f6d2060648201527f612073797374656d206164647265737300000000000000000000000000000000608482015260a4016105d7565b600081815260ce602052604090205460ff1661109b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520636160448201527f6e6e6f74206265207265706c617965640000000000000000000000000000000060648201526084016105d7565b6110a487611905565b15611157576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f43726f7373446f6d61696e4d657373656e6765723a2063616e6e6f742073656e60448201527f64206d65737361676520746f20626c6f636b65642073797374656d206164647260648201527f6573730000000000000000000000000000000000000000000000000000000000608482015260a4016105d7565b600081815260cb602052604090205460ff16156111f6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520686160448201527f7320616c7265616479206265656e2072656c617965640000000000000000000060648201526084016105d7565b61121785611208611388619c40611fcc565b67ffffffffffffffff1661194b565b158061123d575060cc5473ffffffffffffffffffffffffffffffffffffffff1661dead14155b1561135657600081815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555182917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff320161134f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d6573736167650000000000000000000000000000000000000060648201526084016105d7565b50506115ae565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8a1617905560006113e788619c405a6113aa9190612027565b8988888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061196992505050565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790559050801561149d57600082815260cb602052604090205460ff161561143a5761143a611ff8565b600082815260cb602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f4641df4a962071e12719d8c8c8e5ac7fc4d97b927346a3d7a335b1f7517e133c91a26115aa565b600082815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff32016115aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d6573736167650000000000000000000000000000000000000060648201526084016105d7565b5050505b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6000806115de611981565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b60fc546040517fe9e05c4200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063e9e05c4290849061167390889083908990600090899060040161203e565b6000604051808303818588803b15801561168c57600080fd5b505af11580156116a0573d6000803e3d6000fd5b505050505050505050565b6000547501000000000000000000000000000000000000000000900460ff16611756576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016105d7565b60cc5473ffffffffffffffffffffffffffffffffffffffff166117a05760cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790555b60cf80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60006117f585858585611a1e565b805190602001209050949350505050565b6000611816878787878787611ab7565b8051906020012090509695505050505050565b60fc5460009073ffffffffffffffffffffffffffffffffffffffff16331480156108d1575060cf5460fc54604080517f9bf62d82000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9384169390921691639bf62d82916004808201926020929091908290030181865afa1580156118c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118e99190612096565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b600073ffffffffffffffffffffffffffffffffffffffff8216301480611945575060fc5473ffffffffffffffffffffffffffffffffffffffff8381169116145b92915050565b600080603f83619c4001026040850201603f5a021015949350505050565b6000806000835160208501868989f195945050505050565b60fd54604080517f4397dfef0000000000000000000000000000000000000000000000000000000081528151600093849373ffffffffffffffffffffffffffffffffffffffff90911692634397dfef92600480830193928290030181865afa1580156119f1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a1591906120b3565b90939092509050565b606084848484604051602401611a3794939291906120f3565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fcbd4ece9000000000000000000000000000000000000000000000000000000001790529050949350505050565b6060868686868686604051602401611ad49695949392919061213d565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd764ad0b0000000000000000000000000000000000000000000000000000000017905290509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff81168114611b7857600080fd5b50565b60008083601f840112611b8d57600080fd5b50813567ffffffffffffffff811115611ba557600080fd5b602083019150836020828501011115611bbd57600080fd5b9250929050565b803563ffffffff81168114611bd857600080fd5b919050565b60008060008060608587031215611bf357600080fd5b8435611bfe81611b56565b9350602085013567ffffffffffffffff811115611c1a57600080fd5b611c2687828801611b7b565b9094509250611c39905060408601611bc4565b905092959194509250565b6000815180845260005b81811015611c6a57602081850181015186830182015201611c4e565b81811115611c7c576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611cc26020830184611c44565b9392505050565b600060208284031215611cdb57600080fd5b5035919050565b600080600060408486031215611cf757600080fd5b833567ffffffffffffffff811115611d0e57600080fd5b611d1a86828701611b7b565b9094509250611d2d905060208501611bc4565b90509250925092565b600080600060608486031215611d4b57600080fd5b8335611d5681611b56565b92506020840135611d6681611b56565b91506040840135611d7681611b56565b809150509250925092565b600080600080600080600060c0888a031215611d9c57600080fd5b873596506020880135611dae81611b56565b95506040880135611dbe81611b56565b9450606088013593506080880135925060a088013567ffffffffffffffff811115611de857600080fd5b611df48a828b01611b7b565b989b979a50959850939692959293505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b878152600073ffffffffffffffffffffffffffffffffffffffff808916602084015280881660408401525085606083015263ffffffff8516608083015260c060a0830152611ea260c083018486611e07565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff86168152608060208201526000611edf608083018688611e07565b905083604083015263ffffffff831660608301529695505050505050565b600060208284031215611f0f57600080fd5b81518015158114611cc257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600067ffffffffffffffff80831681851681830481118215151615611f7557611f75611f1f565b02949350505050565b600067ffffffffffffffff80841680611fc0577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b92169190910492915050565b600067ffffffffffffffff808316818516808303821115611fef57611fef611f1f565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b60008282101561203957612039611f1f565b500390565b73ffffffffffffffffffffffffffffffffffffffff8616815284602082015267ffffffffffffffff84166040820152821515606082015260a06080820152600061208b60a0830184611c44565b979650505050505050565b6000602082840312156120a857600080fd5b8151611cc281611b56565b600080604083850312156120c657600080fd5b82516120d181611b56565b602084015190925060ff811681146120e857600080fd5b809150509250929050565b600073ffffffffffffffffffffffffffffffffffffffff80871683528086166020840152506080604083015261212c6080830185611c44565b905082606083015295945050505050565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a083015261218860c0830184611c44565b9897505050505050505056fea164736f6c634300080f000a"; +- hex"60806040526004361061018b5760003560e01c80636425666b116100d6578063b1b1b2091161007f578063d764ad0b11610059578063d764ad0b1461049b578063db505d80146104ae578063ecc70428146104db57600080fd5b8063b1b1b2091461042b578063b28ade251461045b578063c0c53b8b1461047b57600080fd5b80638cbeeef2116100b05780638cbeeef2146102d05780639fce812c146103d0578063a4e7f8bd146103fb57600080fd5b80636425666b146103775780636e296e45146103a457806383a74074146103b957600080fd5b80633dbb202b1161013857806354fd4d501161011257806354fd4d50146102e65780635644cfdf1461033c5780635c975abb1461035257600080fd5b80633dbb202b146102935780633f827a5a146102a85780634c1d6a69146102d057600080fd5b80632828d7e8116101695780632828d7e81461022457806333d7e2bd1461023957806335e80ab31461026657600080fd5b8063028f85f7146101905780630c568498146101c35780630ff754ea146101d8575b600080fd5b34801561019c57600080fd5b506101a5601081565b60405167ffffffffffffffff90911681526020015b60405180910390f35b3480156101cf57600080fd5b506101a5603f81565b3480156101e457600080fd5b5060fc5473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101ba565b34801561023057600080fd5b506101a5604081565b34801561024557600080fd5b5060fd546101ff9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561027257600080fd5b5060fb546101ff9073ffffffffffffffffffffffffffffffffffffffff1681565b6102a66102a1366004611bdd565b610540565b005b3480156102b457600080fd5b506102bd600181565b60405161ffff90911681526020016101ba565b3480156102dc57600080fd5b506101a5619c4081565b3480156102f257600080fd5b5061032f6040518060400160405280600581526020017f322e342e3000000000000000000000000000000000000000000000000000000081525081565b6040516101ba9190611caf565b34801561034857600080fd5b506101a561138881565b34801561035e57600080fd5b5061036761083d565b60405190151581526020016101ba565b34801561038357600080fd5b5060fc546101ff9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156103b057600080fd5b506101ff6108d6565b3480156103c557600080fd5b506101a562030d4081565b3480156103dc57600080fd5b5060cf5473ffffffffffffffffffffffffffffffffffffffff166101ff565b34801561040757600080fd5b50610367610416366004611cc9565b60ce6020526000908152604090205460ff1681565b34801561043757600080fd5b50610367610446366004611cc9565b60cb6020526000908152604090205460ff1681565b34801561046757600080fd5b506101a5610476366004611ce2565b6109bd565b34801561048757600080fd5b506102a6610496366004611d36565b610a2b565b6102a66104a9366004611d81565b610ca2565b3480156104ba57600080fd5b5060cf546101ff9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156104e757600080fd5b5061053260cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b6040519081526020016101ba565b6105486115d3565b156105e05734156105e0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f43726f7373446f6d61696e4d657373656e6765723a2063616e6e6f742073656e60448201527f642076616c7565207769746820637573746f6d2067617320746f6b656e00000060648201526084015b60405180910390fd5b60cf546107129073ffffffffffffffffffffffffffffffffffffffff166106088585856109bd565b347fd764ad0b0000000000000000000000000000000000000000000000000000000061067460cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b338a34898c8c6040516024016106909796959493929190611e50565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611612565b8373ffffffffffffffffffffffffffffffffffffffff167fcb0f7ffd78f9aee47a248fae8db181db6eee833039123e026dcbff529522e52a33858561079760cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b866040516107a9959493929190611eaf565b60405180910390a260405134815233907f8ebb2ec2465bdb2a06a66fc37a0963af8a2a6a1479d81d56fdb8cbb98096d5469060200160405180910390a2505060cd80547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808216600101167fffff0000000000000000000000000000000000000000000000000000000000009091161790555050565b60fb54604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa1580156108ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108d19190611efd565b905090565b60cc5460009073ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2153016109a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f43726f7373446f6d61696e4d657373656e6765723a2078446f6d61696e4d657360448201527f7361676553656e646572206973206e6f7420736574000000000000000000000060648201526084016105d7565b5060cc5473ffffffffffffffffffffffffffffffffffffffff1690565b6000611388619c4080603f6109d9604063ffffffff8816611f4e565b6109e39190611f7e565b6109ee601088611f4e565b6109fb9062030d40611fcc565b610a059190611fcc565b610a0f9190611fcc565b610a199190611fcc565b610a239190611fcc565b949350505050565b6000547501000000000000000000000000000000000000000000900460ff1615808015610a76575060005460017401000000000000000000000000000000000000000090910460ff16105b80610aa85750303b158015610aa8575060005474010000000000000000000000000000000000000000900460ff166001145b610b34576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016105d7565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790558015610bba57600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000001790555b60fb805473ffffffffffffffffffffffffffffffffffffffff8087167fffffffffffffffffffffffff00000000000000000000000000000000000000009283161790925560fc805486841690831617905560fd805492851692909116919091179055610c397342000000000000000000000000000000000000076116ab565b8015610c9c57600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b610caa61083d565b15610d11576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f43726f7373446f6d61696e4d657373656e6765723a207061757365640000000060448201526064016105d7565b60f087901c60028110610dcc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f43726f7373446f6d61696e4d657373656e6765723a206f6e6c7920766572736960448201527f6f6e2030206f722031206d657373616765732061726520737570706f7274656460648201527f20617420746869732074696d6500000000000000000000000000000000000000608482015260a4016105d7565b8061ffff16600003610ec1576000610e1d878986868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508f92506117e7915050565b600081815260cb602052604090205490915060ff1615610ebf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f43726f7373446f6d61696e4d657373656e6765723a206c65676163792077697460448201527f6864726177616c20616c72656164792072656c6179656400000000000000000060648201526084016105d7565b505b6000610f07898989898989898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061180692505050565b9050610f11611829565b15610f4957853414610f2557610f25611ff8565b600081815260ce602052604090205460ff1615610f4457610f44611ff8565b61109b565b3415610ffd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605060248201527f43726f7373446f6d61696e4d657373656e6765723a2076616c7565206d75737460448201527f206265207a65726f20756e6c657373206d6573736167652069732066726f6d2060648201527f612073797374656d206164647265737300000000000000000000000000000000608482015260a4016105d7565b600081815260ce602052604090205460ff1661109b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520636160448201527f6e6e6f74206265207265706c617965640000000000000000000000000000000060648201526084016105d7565b6110a487611905565b15611157576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f43726f7373446f6d61696e4d657373656e6765723a2063616e6e6f742073656e60448201527f64206d65737361676520746f20626c6f636b65642073797374656d206164647260648201527f6573730000000000000000000000000000000000000000000000000000000000608482015260a4016105d7565b600081815260cb602052604090205460ff16156111f6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520686160448201527f7320616c7265616479206265656e2072656c617965640000000000000000000060648201526084016105d7565b61121785611208611388619c40611fcc565b67ffffffffffffffff1661194b565b158061123d575060cc5473ffffffffffffffffffffffffffffffffffffffff1661dead14155b1561135657600081815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555182917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff320161134f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d6573736167650000000000000000000000000000000000000060648201526084016105d7565b50506115ae565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8a1617905560006113e788619c405a6113aa9190612027565b8988888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061196992505050565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790559050801561149d57600082815260cb602052604090205460ff161561143a5761143a611ff8565b600082815260cb602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f4641df4a962071e12719d8c8c8e5ac7fc4d97b927346a3d7a335b1f7517e133c91a26115aa565b600082815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff32016115aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d6573736167650000000000000000000000000000000000000060648201526084016105d7565b5050505b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6000806115de611981565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b60fc546040517fe9e05c4200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063e9e05c4290849061167390889083908990600090899060040161203e565b6000604051808303818588803b15801561168c57600080fd5b505af11580156116a0573d6000803e3d6000fd5b505050505050505050565b6000547501000000000000000000000000000000000000000000900460ff16611756576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016105d7565b60cc5473ffffffffffffffffffffffffffffffffffffffff166117a05760cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790555b60cf80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60006117f585858585611a1e565b805190602001209050949350505050565b6000611816878787878787611ab7565b8051906020012090509695505050505050565b60fc5460009073ffffffffffffffffffffffffffffffffffffffff16331480156108d1575060cf5460fc54604080517f9bf62d82000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9384169390921691639bf62d82916004808201926020929091908290030181865afa1580156118c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118e99190612096565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b600073ffffffffffffffffffffffffffffffffffffffff8216301480611945575060fc5473ffffffffffffffffffffffffffffffffffffffff8381169116145b92915050565b600080603f83619c4001026040850201603f5a021015949350505050565b6000806000835160208501868989f195945050505050565b60fd54604080517f4397dfef0000000000000000000000000000000000000000000000000000000081528151600093849373ffffffffffffffffffffffffffffffffffffffff90911692634397dfef92600480830193928290030181865afa1580156119f1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a1591906120b3565b90939092509050565b606084848484604051602401611a3794939291906120f3565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fcbd4ece9000000000000000000000000000000000000000000000000000000001790529050949350505050565b6060868686868686604051602401611ad49695949392919061213d565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd764ad0b0000000000000000000000000000000000000000000000000000000017905290509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff81168114611b7857600080fd5b50565b60008083601f840112611b8d57600080fd5b50813567ffffffffffffffff811115611ba557600080fd5b602083019150836020828501011115611bbd57600080fd5b9250929050565b803563ffffffff81168114611bd857600080fd5b919050565b60008060008060608587031215611bf357600080fd5b8435611bfe81611b56565b9350602085013567ffffffffffffffff811115611c1a57600080fd5b611c2687828801611b7b565b9094509250611c39905060408601611bc4565b905092959194509250565b6000815180845260005b81811015611c6a57602081850181015186830182015201611c4e565b81811115611c7c576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611cc26020830184611c44565b9392505050565b600060208284031215611cdb57600080fd5b5035919050565b600080600060408486031215611cf757600080fd5b833567ffffffffffffffff811115611d0e57600080fd5b611d1a86828701611b7b565b9094509250611d2d905060208501611bc4565b90509250925092565b600080600060608486031215611d4b57600080fd5b8335611d5681611b56565b92506020840135611d6681611b56565b91506040840135611d7681611b56565b809150509250925092565b600080600080600080600060c0888a031215611d9c57600080fd5b873596506020880135611dae81611b56565b95506040880135611dbe81611b56565b9450606088013593506080880135925060a088013567ffffffffffffffff811115611de857600080fd5b611df48a828b01611b7b565b989b979a50959850939692959293505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b878152600073ffffffffffffffffffffffffffffffffffffffff808916602084015280881660408401525085606083015263ffffffff8516608083015260c060a0830152611ea260c083018486611e07565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff86168152608060208201526000611edf608083018688611e07565b905083604083015263ffffffff831660608301529695505050505050565b600060208284031215611f0f57600080fd5b81518015158114611cc257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600067ffffffffffffffff80831681851681830481118215151615611f7557611f75611f1f565b02949350505050565b600067ffffffffffffffff80841680611fc0577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b92169190910492915050565b600067ffffffffffffffff808316818516808303821115611fef57611fef611f1f565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b60008282101561203957612039611f1f565b500390565b73ffffffffffffffffffffffffffffffffffffffff8616815284602082015267ffffffffffffffff84166040820152821515606082015260a06080820152600061208b60a0830184611c44565b979650505050505050565b6000602082840312156120a857600080fd5b8151611cc281611b56565b600080604083850312156120c657600080fd5b82516120d181611b56565b602084015190925060ff811681146120e857600080fd5b809150509250929050565b600073ffffffffffffffffffffffffffffffffffffffff80871683528086166020840152506080604083015261212c6080830185611c44565b905082606083015295945050505050565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a083015261218860c0830184611c44565b9897505050505050505056fea164736f6c634300080f000a"; ++ hex"60806040526004361061018b5760003560e01c80636425666b116100d6578063b1b1b2091161007f578063d764ad0b11610059578063d764ad0b1461049b578063db505d80146104ae578063ecc70428146104db57600080fd5b8063b1b1b2091461042b578063b28ade251461045b578063c0c53b8b1461047b57600080fd5b80638cbeeef2116100b05780638cbeeef2146102d05780639fce812c146103d0578063a4e7f8bd146103fb57600080fd5b80636425666b146103775780636e296e45146103a457806383a74074146103b957600080fd5b80633dbb202b1161013857806354fd4d501161011257806354fd4d50146102e65780635644cfdf1461033c5780635c975abb1461035257600080fd5b80633dbb202b146102935780633f827a5a146102a85780634c1d6a69146102d057600080fd5b80632828d7e8116101695780632828d7e81461022457806333d7e2bd1461023957806335e80ab31461026657600080fd5b8063028f85f7146101905780630c568498146101c35780630ff754ea146101d8575b600080fd5b34801561019c57600080fd5b506101a5601081565b60405167ffffffffffffffff90911681526020015b60405180910390f35b3480156101cf57600080fd5b506101a5603f81565b3480156101e457600080fd5b5060fc5473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101ba565b34801561023057600080fd5b506101a5604081565b34801561024557600080fd5b5060fd546101ff9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561027257600080fd5b5060fb546101ff9073ffffffffffffffffffffffffffffffffffffffff1681565b6102a66102a1366004611bdd565b610540565b005b3480156102b457600080fd5b506102bd600181565b60405161ffff90911681526020016101ba565b3480156102dc57600080fd5b506101a5619c4081565b3480156102f257600080fd5b5061032f6040518060400160405280600c81526020017f322e342e312d626574612e31000000000000000000000000000000000000000081525081565b6040516101ba9190611caf565b34801561034857600080fd5b506101a561138881565b34801561035e57600080fd5b5061036761083d565b60405190151581526020016101ba565b34801561038357600080fd5b5060fc546101ff9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156103b057600080fd5b506101ff6108d6565b3480156103c557600080fd5b506101a562030d4081565b3480156103dc57600080fd5b5060cf5473ffffffffffffffffffffffffffffffffffffffff166101ff565b34801561040757600080fd5b50610367610416366004611cc9565b60ce6020526000908152604090205460ff1681565b34801561043757600080fd5b50610367610446366004611cc9565b60cb6020526000908152604090205460ff1681565b34801561046757600080fd5b506101a5610476366004611ce2565b6109bd565b34801561048757600080fd5b506102a6610496366004611d36565b610a2b565b6102a66104a9366004611d81565b610ca2565b3480156104ba57600080fd5b5060cf546101ff9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156104e757600080fd5b5061053260cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b6040519081526020016101ba565b6105486115d3565b156105e05734156105e0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f43726f7373446f6d61696e4d657373656e6765723a2063616e6e6f742073656e60448201527f642076616c7565207769746820637573746f6d2067617320746f6b656e00000060648201526084015b60405180910390fd5b60cf546107129073ffffffffffffffffffffffffffffffffffffffff166106088585856109bd565b347fd764ad0b0000000000000000000000000000000000000000000000000000000061067460cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b338a34898c8c6040516024016106909796959493929190611e50565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611612565b8373ffffffffffffffffffffffffffffffffffffffff167fcb0f7ffd78f9aee47a248fae8db181db6eee833039123e026dcbff529522e52a33858561079760cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b866040516107a9959493929190611eaf565b60405180910390a260405134815233907f8ebb2ec2465bdb2a06a66fc37a0963af8a2a6a1479d81d56fdb8cbb98096d5469060200160405180910390a2505060cd80547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808216600101167fffff0000000000000000000000000000000000000000000000000000000000009091161790555050565b60fb54604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa1580156108ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108d19190611efd565b905090565b60cc5460009073ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2153016109a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f43726f7373446f6d61696e4d657373656e6765723a2078446f6d61696e4d657360448201527f7361676553656e646572206973206e6f7420736574000000000000000000000060648201526084016105d7565b5060cc5473ffffffffffffffffffffffffffffffffffffffff1690565b6000611388619c4080603f6109d9604063ffffffff8816611f4e565b6109e39190611f7e565b6109ee601088611f4e565b6109fb9062030d40611fcc565b610a059190611fcc565b610a0f9190611fcc565b610a199190611fcc565b610a239190611fcc565b949350505050565b6000547501000000000000000000000000000000000000000000900460ff1615808015610a76575060005460017401000000000000000000000000000000000000000090910460ff16105b80610aa85750303b158015610aa8575060005474010000000000000000000000000000000000000000900460ff166001145b610b34576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016105d7565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790558015610bba57600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000001790555b60fb805473ffffffffffffffffffffffffffffffffffffffff8087167fffffffffffffffffffffffff00000000000000000000000000000000000000009283161790925560fc805486841690831617905560fd805492851692909116919091179055610c397342000000000000000000000000000000000000076116ab565b8015610c9c57600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b610caa61083d565b15610d11576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f43726f7373446f6d61696e4d657373656e6765723a207061757365640000000060448201526064016105d7565b60f087901c60028110610dcc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f43726f7373446f6d61696e4d657373656e6765723a206f6e6c7920766572736960448201527f6f6e2030206f722031206d657373616765732061726520737570706f7274656460648201527f20617420746869732074696d6500000000000000000000000000000000000000608482015260a4016105d7565b8061ffff16600003610ec1576000610e1d878986868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508f92506117e7915050565b600081815260cb602052604090205490915060ff1615610ebf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f43726f7373446f6d61696e4d657373656e6765723a206c65676163792077697460448201527f6864726177616c20616c72656164792072656c6179656400000000000000000060648201526084016105d7565b505b6000610f07898989898989898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061180692505050565b9050610f11611829565b15610f4957853414610f2557610f25611ff8565b600081815260ce602052604090205460ff1615610f4457610f44611ff8565b61109b565b3415610ffd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605060248201527f43726f7373446f6d61696e4d657373656e6765723a2076616c7565206d75737460448201527f206265207a65726f20756e6c657373206d6573736167652069732066726f6d2060648201527f612073797374656d206164647265737300000000000000000000000000000000608482015260a4016105d7565b600081815260ce602052604090205460ff1661109b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520636160448201527f6e6e6f74206265207265706c617965640000000000000000000000000000000060648201526084016105d7565b6110a487611905565b15611157576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f43726f7373446f6d61696e4d657373656e6765723a2063616e6e6f742073656e60448201527f64206d65737361676520746f20626c6f636b65642073797374656d206164647260648201527f6573730000000000000000000000000000000000000000000000000000000000608482015260a4016105d7565b600081815260cb602052604090205460ff16156111f6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520686160448201527f7320616c7265616479206265656e2072656c617965640000000000000000000060648201526084016105d7565b61121785611208611388619c40611fcc565b67ffffffffffffffff1661194b565b158061123d575060cc5473ffffffffffffffffffffffffffffffffffffffff1661dead14155b1561135657600081815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555182917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff320161134f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d6573736167650000000000000000000000000000000000000060648201526084016105d7565b50506115ae565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8a1617905560006113e788619c405a6113aa9190612027565b8988888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061196992505050565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790559050801561149d57600082815260cb602052604090205460ff161561143a5761143a611ff8565b600082815260cb602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f4641df4a962071e12719d8c8c8e5ac7fc4d97b927346a3d7a335b1f7517e133c91a26115aa565b600082815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff32016115aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d6573736167650000000000000000000000000000000000000060648201526084016105d7565b5050505b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6000806115de611981565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b60fc546040517fe9e05c4200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063e9e05c4290849061167390889083908990600090899060040161203e565b6000604051808303818588803b15801561168c57600080fd5b505af11580156116a0573d6000803e3d6000fd5b505050505050505050565b6000547501000000000000000000000000000000000000000000900460ff16611756576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016105d7565b60cc5473ffffffffffffffffffffffffffffffffffffffff166117a05760cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790555b60cf80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60006117f585858585611a1e565b805190602001209050949350505050565b6000611816878787878787611ab7565b8051906020012090509695505050505050565b60fc5460009073ffffffffffffffffffffffffffffffffffffffff16331480156108d1575060cf5460fc54604080517f9bf62d82000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9384169390921691639bf62d82916004808201926020929091908290030181865afa1580156118c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118e99190612096565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b600073ffffffffffffffffffffffffffffffffffffffff8216301480611945575060fc5473ffffffffffffffffffffffffffffffffffffffff8381169116145b92915050565b600080603f83619c4001026040850201603f5a021015949350505050565b6000806000835160208501868989f195945050505050565b60fd54604080517f4397dfef0000000000000000000000000000000000000000000000000000000081528151600093849373ffffffffffffffffffffffffffffffffffffffff90911692634397dfef92600480830193928290030181865afa1580156119f1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a1591906120b3565b90939092509050565b606084848484604051602401611a3794939291906120f3565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fcbd4ece9000000000000000000000000000000000000000000000000000000001790529050949350505050565b6060868686868686604051602401611ad49695949392919061213d565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd764ad0b0000000000000000000000000000000000000000000000000000000017905290509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff81168114611b7857600080fd5b50565b60008083601f840112611b8d57600080fd5b50813567ffffffffffffffff811115611ba557600080fd5b602083019150836020828501011115611bbd57600080fd5b9250929050565b803563ffffffff81168114611bd857600080fd5b919050565b60008060008060608587031215611bf357600080fd5b8435611bfe81611b56565b9350602085013567ffffffffffffffff811115611c1a57600080fd5b611c2687828801611b7b565b9094509250611c39905060408601611bc4565b905092959194509250565b6000815180845260005b81811015611c6a57602081850181015186830182015201611c4e565b81811115611c7c576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611cc26020830184611c44565b9392505050565b600060208284031215611cdb57600080fd5b5035919050565b600080600060408486031215611cf757600080fd5b833567ffffffffffffffff811115611d0e57600080fd5b611d1a86828701611b7b565b9094509250611d2d905060208501611bc4565b90509250925092565b600080600060608486031215611d4b57600080fd5b8335611d5681611b56565b92506020840135611d6681611b56565b91506040840135611d7681611b56565b809150509250925092565b600080600080600080600060c0888a031215611d9c57600080fd5b873596506020880135611dae81611b56565b95506040880135611dbe81611b56565b9450606088013593506080880135925060a088013567ffffffffffffffff811115611de857600080fd5b611df48a828b01611b7b565b989b979a50959850939692959293505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b878152600073ffffffffffffffffffffffffffffffffffffffff808916602084015280881660408401525085606083015263ffffffff8516608083015260c060a0830152611ea260c083018486611e07565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff86168152608060208201526000611edf608083018688611e07565b905083604083015263ffffffff831660608301529695505050505050565b600060208284031215611f0f57600080fd5b81518015158114611cc257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600067ffffffffffffffff80831681851681830481118215151615611f7557611f75611f1f565b02949350505050565b600067ffffffffffffffff80841680611fc0577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b92169190910492915050565b600067ffffffffffffffff808316818516808303821115611fef57611fef611f1f565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b60008282101561203957612039611f1f565b500390565b73ffffffffffffffffffffffffffffffffffffffff8616815284602082015267ffffffffffffffff84166040820152821515606082015260a06080820152600061208b60a0830184611c44565b979650505050505050565b6000602082840312156120a857600080fd5b8151611cc281611b56565b600080604083850312156120c657600080fd5b82516120d181611b56565b602084015190925060ff811681146120e857600080fd5b809150509250929050565b600073ffffffffffffffffffffffffffffffffffffffff80871683528086166020840152506080604083015261212c6080830185611c44565b905082606083015295945050505050565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a083015261218860c0830184611c44565b9897505050505050505056fea164736f6c634300080f000a"; bytes internal constant optimismMintableERC20FactoryCode = - hex"60806040523480156200001157600080fd5b5060043610620000935760003560e01c8063c4d66de81162000062578063c4d66de81462000175578063ce5ac90f146200018e578063e78cea9214620001a5578063ee9a31a214620001c657600080fd5b8063316b3739146200009857806354fd4d5014620000fb578063896f93d114620001475780638cf0629c146200015e575b600080fd5b620000d1620000a936600462000652565b60026020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b620001386040518060400160405280600681526020017f312e31302e30000000000000000000000000000000000000000000000000000081525081565b604051620000f29190620006e5565b620000d162000158366004620007dc565b620001e5565b620000d16200016f36600462000859565b620001fc565b6200018c6200018636600462000652565b6200041b565b005b620000d16200019f366004620007dc565b620005ed565b600154620000d19073ffffffffffffffffffffffffffffffffffffffff1681565b60015473ffffffffffffffffffffffffffffffffffffffff16620000d1565b6000620001f4848484620005ed565b949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8516620002a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d4d696e7461626c654552433230466163746f72793a206d7560448201527f73742070726f766964652072656d6f746520746f6b656e20616464726573730060648201526084015b60405180910390fd5b600085858585604051602001620002c29493929190620008f0565b604051602081830303815290604052805190602001209050600081600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168888888860405162000312906200061a565b620003229594939291906200094a565b8190604051809103906000f590508015801562000343573d6000803e3d6000fd5b5073ffffffffffffffffffffffffffffffffffffffff81811660008181526002602052604080822080547fffffffffffffffffffffffff000000000000000000000000000000000000000016948d1694851790555193945090927fceeb8e7d520d7f3b65fc11a262b91066940193b05d4f93df07cfdced0eb551cf9190a360405133815273ffffffffffffffffffffffffffffffffffffffff80891691908316907f52fe89dd5930f343d25650b62fd367bae47088bcddffd2a88350a6ecdd620cdb9060200160405180910390a39695505050505050565b600054610100900460ff16158080156200043c5750600054600160ff909116105b80620004585750303b15801562000458575060005460ff166001145b620004e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016200029e565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156200054557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84161790558015620005e957600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6000620001f48484846012620001fc565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b61178a80620009b083390190565b803573ffffffffffffffffffffffffffffffffffffffff811681146200064d57600080fd5b919050565b6000602082840312156200066557600080fd5b620006708262000628565b9392505050565b6000815180845260005b818110156200069f5760208185018101518683018201520162000681565b81811115620006b2576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600062000670602083018462000677565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126200073b57600080fd5b813567ffffffffffffffff80821115620007595762000759620006fa565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715620007a257620007a2620006fa565b81604052838152866020858801011115620007bc57600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600060608486031215620007f257600080fd5b620007fd8462000628565b9250602084013567ffffffffffffffff808211156200081b57600080fd5b620008298783880162000729565b935060408601359150808211156200084057600080fd5b506200084f8682870162000729565b9150509250925092565b600080600080608085870312156200087057600080fd5b6200087b8562000628565b9350602085013567ffffffffffffffff808211156200089957600080fd5b620008a78883890162000729565b94506040870135915080821115620008be57600080fd5b50620008cd8782880162000729565b925050606085013560ff81168114620008e557600080fd5b939692955090935050565b73ffffffffffffffffffffffffffffffffffffffff8516815260806020820152600062000921608083018662000677565b828103604084015262000935818662000677565b91505060ff8316606083015295945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808816835280871660208401525060a060408301526200098560a083018662000677565b828103606084015262000999818662000677565b91505060ff83166080830152969550505050505056fe60e06040523480156200001157600080fd5b506040516200178a3803806200178a833981016040819052620000349162000163565b828260036200004483826200029e565b5060046200005382826200029e565b5050506001600160a01b039384166080529390921660a052505060ff1660c0526200036a565b80516001600160a01b03811681146200009157600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620000be57600080fd5b81516001600160401b0380821115620000db57620000db62000096565b604051601f8301601f19908116603f0116810190828211818310171562000106576200010662000096565b816040528381526020925086838588010111156200012357600080fd5b600091505b8382101562000147578582018301518183018401529082019062000128565b83821115620001595760008385830101525b9695505050505050565b600080600080600060a086880312156200017c57600080fd5b620001878662000079565b9450620001976020870162000079565b60408701519094506001600160401b0380821115620001b557600080fd5b620001c389838a01620000ac565b94506060880151915080821115620001da57600080fd5b50620001e988828901620000ac565b925050608086015160ff811681146200020157600080fd5b809150509295509295909350565b600181811c908216806200022457607f821691505b6020821081036200024557634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200029957600081815260208120601f850160051c81016020861015620002745750805b601f850160051c820191505b81811015620002955782815560010162000280565b5050505b505050565b81516001600160401b03811115620002ba57620002ba62000096565b620002d281620002cb84546200020f565b846200024b565b602080601f8311600181146200030a5760008415620002f15750858301515b600019600386901b1c1916600185901b17855562000295565b600085815260208120601f198616915b828110156200033b578886015182559484019460019091019084016200031a565b50858210156200035a5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c0516113d4620003b6600039600061024401526000818161034b015281816103e001528181610625015261075c0152600081816101a9015261037101526113d46000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063ae1f6aaf1161008c578063dd62ed3e11610066578063dd62ed3e14610395578063e78cea9214610349578063ee9a31a2146103db57600080fd5b8063ae1f6aaf14610349578063c01e1bd61461036f578063d6c0b2c41461036f57600080fd5b80639dc29fac116100bd5780639dc29fac14610310578063a457c2d714610323578063a9059cbb1461033657600080fd5b806370a08231146102d257806395d89b411461030857600080fd5b806323b872dd1161012f5780633950935111610114578063395093511461026e57806340c10f191461028157806354fd4d501461029657600080fd5b806323b872dd1461022a578063313ce5671461023d57600080fd5b806306fdde031161016057806306fdde03146101f0578063095ea7b31461020557806318160ddd1461021857600080fd5b806301ffc9a71461017c578063033964be146101a4575b600080fd5b61018f61018a36600461117d565b610402565b60405190151581526020015b60405180910390f35b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b6101f86104f3565b60405161019b91906111c6565b61018f610213366004611262565b610585565b6002545b60405190815260200161019b565b61018f61023836600461128c565b61059d565b60405160ff7f000000000000000000000000000000000000000000000000000000000000000016815260200161019b565b61018f61027c366004611262565b6105c1565b61029461028f366004611262565b61060d565b005b6101f86040518060400160405280600581526020017f312e332e3000000000000000000000000000000000000000000000000000000081525081565b61021c6102e03660046112c8565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101f8610735565b61029461031e366004611262565b610744565b61018f610331366004611262565b61085b565b61018f610344366004611262565b61092c565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b61021c6103a33660046112e3565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007f1d1d8b63000000000000000000000000000000000000000000000000000000007fec4fc8e3000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000085168314806104bb57507fffffffff00000000000000000000000000000000000000000000000000000000858116908316145b806104ea57507fffffffff00000000000000000000000000000000000000000000000000000000858116908216145b95945050505050565b60606003805461050290611316565b80601f016020809104026020016040519081016040528092919081815260200182805461052e90611316565b801561057b5780601f106105505761010080835404028352916020019161057b565b820191906000526020600020905b81548152906001019060200180831161055e57829003601f168201915b5050505050905090565b60003361059381858561093a565b5060019392505050565b6000336105ab858285610aee565b6105b6858585610bc5565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906105939082908690610608908790611398565b61093a565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146106d7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084015b60405180910390fd5b6106e18282610e78565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d41213968858260405161072991815260200190565b60405180910390a25050565b60606004805461050290611316565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610809576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084016106ce565b6108138282610f98565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca58260405161072991815260200190565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091908381101561091f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084016106ce565b6105b6828686840361093a565b600033610593818585610bc5565b73ffffffffffffffffffffffffffffffffffffffff83166109dc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f726573730000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216610a7f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f737300000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610bbf5781811015610bb2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016106ce565b610bbf848484840361093a565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610c68576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216610d0b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f657373000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610dc1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e6365000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260208190526040808220858503905591851681529081208054849290610e05908490611398565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610e6b91815260200190565b60405180910390a3610bbf565b73ffffffffffffffffffffffffffffffffffffffff8216610ef5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016106ce565b8060026000828254610f079190611398565b909155505073ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604081208054839290610f41908490611398565b909155505060405181815273ffffffffffffffffffffffffffffffffffffffff8316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff821661103b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f730000000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260208190526040902054818110156110f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f636500000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260208190526040812083830390556002805484929061112d9084906113b0565b909155505060405182815260009073ffffffffffffffffffffffffffffffffffffffff8516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610ae1565b60006020828403121561118f57600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146111bf57600080fd5b9392505050565b600060208083528351808285015260005b818110156111f3578581018301518582016040015282016111d7565b81811115611205576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461125d57600080fd5b919050565b6000806040838503121561127557600080fd5b61127e83611239565b946020939093013593505050565b6000806000606084860312156112a157600080fd5b6112aa84611239565b92506112b860208501611239565b9150604084013590509250925092565b6000602082840312156112da57600080fd5b6111bf82611239565b600080604083850312156112f657600080fd5b6112ff83611239565b915061130d60208401611239565b90509250929050565b600181811c9082168061132a57607f821691505b602082108103611363577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156113ab576113ab611369565b500190565b6000828210156113c2576113c2611369565b50039056fea164736f6c634300080f000aa164736f6c634300080f000a"; -+ hex"60806040523480156200001157600080fd5b5060043610620000935760003560e01c8063c4d66de81162000062578063c4d66de81462000175578063ce5ac90f146200018e578063e78cea9214620001a5578063ee9a31a214620001c657600080fd5b8063316b3739146200009857806354fd4d5014620000fb578063896f93d114620001475780638cf0629c146200015e575b600080fd5b620000d1620000a936600462000652565b60026020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b620001386040518060400160405280600681526020017f312e31302e30000000000000000000000000000000000000000000000000000081525081565b604051620000f29190620006e5565b620000d162000158366004620007dc565b620001e5565b620000d16200016f36600462000859565b620001fc565b6200018c6200018636600462000652565b6200041b565b005b620000d16200019f366004620007dc565b620005ed565b600154620000d19073ffffffffffffffffffffffffffffffffffffffff1681565b60015473ffffffffffffffffffffffffffffffffffffffff16620000d1565b6000620001f4848484620005ed565b949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8516620002a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d4d696e7461626c654552433230466163746f72793a206d7560448201527f73742070726f766964652072656d6f746520746f6b656e20616464726573730060648201526084015b60405180910390fd5b600085858585604051602001620002c29493929190620008f0565b604051602081830303815290604052805190602001209050600081600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168888888860405162000312906200061a565b620003229594939291906200094a565b8190604051809103906000f590508015801562000343573d6000803e3d6000fd5b5073ffffffffffffffffffffffffffffffffffffffff81811660008181526002602052604080822080547fffffffffffffffffffffffff000000000000000000000000000000000000000016948d1694851790555193945090927fceeb8e7d520d7f3b65fc11a262b91066940193b05d4f93df07cfdced0eb551cf9190a360405133815273ffffffffffffffffffffffffffffffffffffffff80891691908316907f52fe89dd5930f343d25650b62fd367bae47088bcddffd2a88350a6ecdd620cdb9060200160405180910390a39695505050505050565b600054610100900460ff16158080156200043c5750600054600160ff909116105b80620004585750303b15801562000458575060005460ff166001145b620004e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016200029e565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156200054557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84161790558015620005e957600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6000620001f48484846012620001fc565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b611be480620009b083390190565b803573ffffffffffffffffffffffffffffffffffffffff811681146200064d57600080fd5b919050565b6000602082840312156200066557600080fd5b620006708262000628565b9392505050565b6000815180845260005b818110156200069f5760208185018101518683018201520162000681565b81811115620006b2576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600062000670602083018462000677565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126200073b57600080fd5b813567ffffffffffffffff80821115620007595762000759620006fa565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715620007a257620007a2620006fa565b81604052838152866020858801011115620007bc57600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600060608486031215620007f257600080fd5b620007fd8462000628565b9250602084013567ffffffffffffffff808211156200081b57600080fd5b620008298783880162000729565b935060408601359150808211156200084057600080fd5b506200084f8682870162000729565b9150509250925092565b600080600080608085870312156200087057600080fd5b6200087b8562000628565b9350602085013567ffffffffffffffff808211156200089957600080fd5b620008a78883890162000729565b94506040870135915080821115620008be57600080fd5b50620008cd8782880162000729565b925050606085013560ff81168114620008e557600080fd5b939692955090935050565b73ffffffffffffffffffffffffffffffffffffffff8516815260806020820152600062000921608083018662000677565b828103604084015262000935818662000677565b91505060ff8316606083015295945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808816835280871660208401525060a060408301526200098560a083018662000677565b828103606084015262000999818662000677565b91505060ff83166080830152969550505050505056fe60e06040523480156200001157600080fd5b5060405162001be438038062001be4833981016040819052620000349162000163565b828260036200004483826200029e565b5060046200005382826200029e565b5050506001600160a01b039384166080529390921660a052505060ff1660c0526200036a565b80516001600160a01b03811681146200009157600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620000be57600080fd5b81516001600160401b0380821115620000db57620000db62000096565b604051601f8301601f19908116603f0116810190828211818310171562000106576200010662000096565b816040528381526020925086838588010111156200012357600080fd5b600091505b8382101562000147578582018301518183018401529082019062000128565b83821115620001595760008385830101525b9695505050505050565b600080600080600060a086880312156200017c57600080fd5b620001878662000079565b9450620001976020870162000079565b60408701519094506001600160401b0380821115620001b557600080fd5b620001c389838a01620000ac565b94506060880151915080821115620001da57600080fd5b50620001e988828901620000ac565b925050608086015160ff811681146200020157600080fd5b809150509295509295909350565b600181811c908216806200022457607f821691505b6020821081036200024557634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200029957600081815260208120601f850160051c81016020861015620002745750805b601f850160051c820191505b81811015620002955782815560010162000280565b5050505b505050565b81516001600160401b03811115620002ba57620002ba62000096565b620002d281620002cb84546200020f565b846200024b565b602080601f8311600181146200030a5760008415620002f15750858301515b600019600386901b1c1916600185901b17855562000295565b600085815260208120601f198616915b828110156200033b578886015182559484019460019091019084016200031a565b50858210156200035a5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05161182e620003b6600039600061027a0152600081816103a50152818161043a015281816107e70152610a1f0152600081816101ca01526103cb015261182e6000f3fe608060405234801561001057600080fd5b50600436106101985760003560e01c80636a30b253116100e3578063ae1f6aaf1161008c578063dd62ed3e11610066578063dd62ed3e146103ef578063e78cea92146103a3578063ee9a31a21461043557600080fd5b8063ae1f6aaf146103a3578063c01e1bd6146103c9578063d6c0b2c4146103c957600080fd5b80639dc29fac116100bd5780639dc29fac1461036a578063a457c2d71461037d578063a9059cbb1461039057600080fd5b80636a30b2531461031957806370a082311461032c57806395d89b411461036257600080fd5b80632e0f98ad1161014557806340c10f191161011f57806340c10f19146102b757806354fd4d50146102ca57806358cf96721461030657600080fd5b80632e0f98ad1461025e578063313ce5671461027357806339509351146102a457600080fd5b8063095ea7b311610176578063095ea7b31461022657806318160ddd1461023957806323b872dd1461024b57600080fd5b806301ffc9a71461019d578063033964be146101c557806306fdde0314610211575b600080fd5b6101b06101ab366004611440565b61045c565b60405190151581526020015b60405180910390f35b6101ec7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101bc565b61021961054d565b6040516101bc9190611489565b6101b0610234366004611525565b6105df565b6002545b6040519081526020016101bc565b6101b061025936600461154f565b6105f7565b61027161026c3660046115d7565b61061b565b005b60405160ff7f00000000000000000000000000000000000000000000000000000000000000001681526020016101bc565b6101b06102b2366004611525565b610783565b6102716102c5366004611525565b6107cf565b6102196040518060400160405280600581526020017f312e332e3000000000000000000000000000000000000000000000000000000081525081565b610271610314366004611525565b6108f2565b610271610327366004611643565b610968565b61023d61033a3660046116bb565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6102196109f8565b610271610378366004611525565b610a07565b6101b061038b366004611525565b610b1e565b6101b061039e366004611525565b610bef565b7f00000000000000000000000000000000000000000000000000000000000000006101ec565b7f00000000000000000000000000000000000000000000000000000000000000006101ec565b61023d6103fd3660046116d6565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101ec7f000000000000000000000000000000000000000000000000000000000000000081565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007f1d1d8b63000000000000000000000000000000000000000000000000000000007fec4fc8e3000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000851683148061051557507fffffffff00000000000000000000000000000000000000000000000000000000858116908316145b8061054457507fffffffff00000000000000000000000000000000000000000000000000000000858116908216145b95945050505050565b60606003805461055c90611709565b80601f016020809104026020016040519081016040528092919081815260200182805461058890611709565b80156105d55780601f106105aa576101008083540402835291602001916105d5565b820191906000526020600020905b8154815290600101906020018083116105b857829003601f168201915b5050505050905090565b6000336105ed818585610bfd565b5060019392505050565b600033610605858285610db1565b610610858585610e88565b506001949350505050565b3315610688576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f4f6e6c7920564d2063616e2063616c6c0000000000000000000000000000000060448201526064015b60405180910390fd5b828114610717576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526563697069656e747320616e6420616d6f756e7473206d757374206265207460448201527f68652073616d65206c656e6774682e0000000000000000000000000000000000606482015260840161067f565b60005b8381101561077c5761076a8585838181106107375761073761175c565b905060200201602081019061074c91906116bb565b84848481811061075e5761075e61175c565b9050602002013561113b565b80610774816117ba565b91505061071a565b5050505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906105ed90829086906107ca9087906117f2565b610bfd565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610894576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e000000000000000000000000606482015260840161067f565b61089e828261113b565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885826040516108e691815260200190565b60405180910390a25050565b331561095a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f4f6e6c7920564d2063616e2063616c6c00000000000000000000000000000000604482015260640161067f565b610964828261125b565b5050565b33156109d0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f4f6e6c7920564d2063616e2063616c6c00000000000000000000000000000000604482015260640161067f565b6109da888561113b565b6109e4878461113b565b6109ee858261113b565b5050505050505050565b60606004805461055c90611709565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610acc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e000000000000000000000000606482015260840161067f565b610ad6828261125b565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5826040516108e691815260200190565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919083811015610be2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f000000000000000000000000000000000000000000000000000000606482015260840161067f565b6106108286868403610bfd565b6000336105ed818585610e88565b73ffffffffffffffffffffffffffffffffffffffff8316610c9f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f7265737300000000000000000000000000000000000000000000000000000000606482015260840161067f565b73ffffffffffffffffffffffffffffffffffffffff8216610d42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f7373000000000000000000000000000000000000000000000000000000000000606482015260840161067f565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610e825781811015610e75576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e6365000000604482015260640161067f565b610e828484848403610bfd565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610f2b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f6472657373000000000000000000000000000000000000000000000000000000606482015260840161067f565b73ffffffffffffffffffffffffffffffffffffffff8216610fce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f6573730000000000000000000000000000000000000000000000000000000000606482015260840161067f565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015611084576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e63650000000000000000000000000000000000000000000000000000606482015260840161067f565b73ffffffffffffffffffffffffffffffffffffffff8085166000908152602081905260408082208585039055918516815290812080548492906110c89084906117f2565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161112e91815260200190565b60405180910390a3610e82565b73ffffffffffffffffffffffffffffffffffffffff82166111b8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640161067f565b80600260008282546111ca91906117f2565b909155505073ffffffffffffffffffffffffffffffffffffffff8216600090815260208190526040812080548392906112049084906117f2565b909155505060405181815273ffffffffffffffffffffffffffffffffffffffff8316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff82166112fe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f7300000000000000000000000000000000000000000000000000000000000000606482015260840161067f565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260208190526040902054818110156113b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f6365000000000000000000000000000000000000000000000000000000000000606482015260840161067f565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604081208383039055600280548492906113f090849061180a565b909155505060405182815260009073ffffffffffffffffffffffffffffffffffffffff8516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610da4565b60006020828403121561145257600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461148257600080fd5b9392505050565b600060208083528351808285015260005b818110156114b65785810183015185820160400152820161149a565b818111156114c8576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461152057600080fd5b919050565b6000806040838503121561153857600080fd5b611541836114fc565b946020939093013593505050565b60008060006060848603121561156457600080fd5b61156d846114fc565b925061157b602085016114fc565b9150604084013590509250925092565b60008083601f84011261159d57600080fd5b50813567ffffffffffffffff8111156115b557600080fd5b6020830191508360208260051b85010111156115d057600080fd5b9250929050565b600080600080604085870312156115ed57600080fd5b843567ffffffffffffffff8082111561160557600080fd5b6116118883890161158b565b9096509450602087013591508082111561162a57600080fd5b506116378782880161158b565b95989497509550505050565b600080600080600080600080610100898b03121561166057600080fd5b611669896114fc565b975061167760208a016114fc565b965061168560408a016114fc565b955061169360608a016114fc565b979a969950949760808101359660a0820135965060c0820135955060e0909101359350915050565b6000602082840312156116cd57600080fd5b611482826114fc565b600080604083850312156116e957600080fd5b6116f2836114fc565b9150611700602084016114fc565b90509250929050565b600181811c9082168061171d57607f821691505b602082108103611756577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036117eb576117eb61178b565b5060010190565b600082198211156118055761180561178b565b500190565b60008282101561181c5761181c61178b565b50039056fea164736f6c634300080f000aa164736f6c634300080f000a"; ++ hex"60806040523480156200001157600080fd5b5060043610620000935760003560e01c8063c4d66de81162000062578063c4d66de81462000175578063ce5ac90f146200018e578063e78cea9214620001a5578063ee9a31a214620001c657600080fd5b8063316b3739146200009857806354fd4d5014620000fb578063896f93d114620001475780638cf0629c146200015e575b600080fd5b620000d1620000a936600462000652565b60026020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b620001386040518060400160405280600d81526020017f312e31302e312d626574612e310000000000000000000000000000000000000081525081565b604051620000f29190620006e5565b620000d162000158366004620007dc565b620001e5565b620000d16200016f36600462000859565b620001fc565b6200018c6200018636600462000652565b6200041b565b005b620000d16200019f366004620007dc565b620005ed565b600154620000d19073ffffffffffffffffffffffffffffffffffffffff1681565b60015473ffffffffffffffffffffffffffffffffffffffff16620000d1565b6000620001f4848484620005ed565b949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8516620002a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d4d696e7461626c654552433230466163746f72793a206d7560448201527f73742070726f766964652072656d6f746520746f6b656e20616464726573730060648201526084015b60405180910390fd5b600085858585604051602001620002c29493929190620008f0565b604051602081830303815290604052805190602001209050600081600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168888888860405162000312906200061a565b620003229594939291906200094a565b8190604051809103906000f590508015801562000343573d6000803e3d6000fd5b5073ffffffffffffffffffffffffffffffffffffffff81811660008181526002602052604080822080547fffffffffffffffffffffffff000000000000000000000000000000000000000016948d1694851790555193945090927fceeb8e7d520d7f3b65fc11a262b91066940193b05d4f93df07cfdced0eb551cf9190a360405133815273ffffffffffffffffffffffffffffffffffffffff80891691908316907f52fe89dd5930f343d25650b62fd367bae47088bcddffd2a88350a6ecdd620cdb9060200160405180910390a39695505050505050565b600054610100900460ff16158080156200043c5750600054600160ff909116105b80620004585750303b15801562000458575060005460ff166001145b620004e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016200029e565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156200054557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84161790558015620005e957600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6000620001f48484846012620001fc565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b61178a80620009b083390190565b803573ffffffffffffffffffffffffffffffffffffffff811681146200064d57600080fd5b919050565b6000602082840312156200066557600080fd5b620006708262000628565b9392505050565b6000815180845260005b818110156200069f5760208185018101518683018201520162000681565b81811115620006b2576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600062000670602083018462000677565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126200073b57600080fd5b813567ffffffffffffffff80821115620007595762000759620006fa565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715620007a257620007a2620006fa565b81604052838152866020858801011115620007bc57600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600060608486031215620007f257600080fd5b620007fd8462000628565b9250602084013567ffffffffffffffff808211156200081b57600080fd5b620008298783880162000729565b935060408601359150808211156200084057600080fd5b506200084f8682870162000729565b9150509250925092565b600080600080608085870312156200087057600080fd5b6200087b8562000628565b9350602085013567ffffffffffffffff808211156200089957600080fd5b620008a78883890162000729565b94506040870135915080821115620008be57600080fd5b50620008cd8782880162000729565b925050606085013560ff81168114620008e557600080fd5b939692955090935050565b73ffffffffffffffffffffffffffffffffffffffff8516815260806020820152600062000921608083018662000677565b828103604084015262000935818662000677565b91505060ff8316606083015295945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808816835280871660208401525060a060408301526200098560a083018662000677565b828103606084015262000999818662000677565b91505060ff83166080830152969550505050505056fe60e06040523480156200001157600080fd5b506040516200178a3803806200178a833981016040819052620000349162000163565b828260036200004483826200029e565b5060046200005382826200029e565b5050506001600160a01b039384166080529390921660a052505060ff1660c0526200036a565b80516001600160a01b03811681146200009157600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620000be57600080fd5b81516001600160401b0380821115620000db57620000db62000096565b604051601f8301601f19908116603f0116810190828211818310171562000106576200010662000096565b816040528381526020925086838588010111156200012357600080fd5b600091505b8382101562000147578582018301518183018401529082019062000128565b83821115620001595760008385830101525b9695505050505050565b600080600080600060a086880312156200017c57600080fd5b620001878662000079565b9450620001976020870162000079565b60408701519094506001600160401b0380821115620001b557600080fd5b620001c389838a01620000ac565b94506060880151915080821115620001da57600080fd5b50620001e988828901620000ac565b925050608086015160ff811681146200020157600080fd5b809150509295509295909350565b600181811c908216806200022457607f821691505b6020821081036200024557634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200029957600081815260208120601f850160051c81016020861015620002745750805b601f850160051c820191505b81811015620002955782815560010162000280565b5050505b505050565b81516001600160401b03811115620002ba57620002ba62000096565b620002d281620002cb84546200020f565b846200024b565b602080601f8311600181146200030a5760008415620002f15750858301515b600019600386901b1c1916600185901b17855562000295565b600085815260208120601f198616915b828110156200033b578886015182559484019460019091019084016200031a565b50858210156200035a5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c0516113d4620003b6600039600061024401526000818161034b015281816103e001528181610625015261075c0152600081816101a9015261037101526113d46000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063ae1f6aaf1161008c578063dd62ed3e11610066578063dd62ed3e14610395578063e78cea9214610349578063ee9a31a2146103db57600080fd5b8063ae1f6aaf14610349578063c01e1bd61461036f578063d6c0b2c41461036f57600080fd5b80639dc29fac116100bd5780639dc29fac14610310578063a457c2d714610323578063a9059cbb1461033657600080fd5b806370a08231146102d257806395d89b411461030857600080fd5b806323b872dd1161012f5780633950935111610114578063395093511461026e57806340c10f191461028157806354fd4d501461029657600080fd5b806323b872dd1461022a578063313ce5671461023d57600080fd5b806306fdde031161016057806306fdde03146101f0578063095ea7b31461020557806318160ddd1461021857600080fd5b806301ffc9a71461017c578063033964be146101a4575b600080fd5b61018f61018a36600461117d565b610402565b60405190151581526020015b60405180910390f35b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b6101f86104f3565b60405161019b91906111c6565b61018f610213366004611262565b610585565b6002545b60405190815260200161019b565b61018f61023836600461128c565b61059d565b60405160ff7f000000000000000000000000000000000000000000000000000000000000000016815260200161019b565b61018f61027c366004611262565b6105c1565b61029461028f366004611262565b61060d565b005b6101f86040518060400160405280600c81526020017f312e332e312d626574612e31000000000000000000000000000000000000000081525081565b61021c6102e03660046112c8565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101f8610735565b61029461031e366004611262565b610744565b61018f610331366004611262565b61085b565b61018f610344366004611262565b61092c565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b61021c6103a33660046112e3565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007f1d1d8b63000000000000000000000000000000000000000000000000000000007fec4fc8e3000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000085168314806104bb57507fffffffff00000000000000000000000000000000000000000000000000000000858116908316145b806104ea57507fffffffff00000000000000000000000000000000000000000000000000000000858116908216145b95945050505050565b60606003805461050290611316565b80601f016020809104026020016040519081016040528092919081815260200182805461052e90611316565b801561057b5780601f106105505761010080835404028352916020019161057b565b820191906000526020600020905b81548152906001019060200180831161055e57829003601f168201915b5050505050905090565b60003361059381858561093a565b5060019392505050565b6000336105ab858285610aee565b6105b6858585610bc5565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906105939082908690610608908790611398565b61093a565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146106d7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084015b60405180910390fd5b6106e18282610e78565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d41213968858260405161072991815260200190565b60405180910390a25050565b60606004805461050290611316565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610809576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084016106ce565b6108138282610f98565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca58260405161072991815260200190565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091908381101561091f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084016106ce565b6105b6828686840361093a565b600033610593818585610bc5565b73ffffffffffffffffffffffffffffffffffffffff83166109dc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f726573730000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216610a7f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f737300000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610bbf5781811015610bb2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016106ce565b610bbf848484840361093a565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610c68576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216610d0b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f657373000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610dc1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e6365000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260208190526040808220858503905591851681529081208054849290610e05908490611398565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610e6b91815260200190565b60405180910390a3610bbf565b73ffffffffffffffffffffffffffffffffffffffff8216610ef5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016106ce565b8060026000828254610f079190611398565b909155505073ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604081208054839290610f41908490611398565b909155505060405181815273ffffffffffffffffffffffffffffffffffffffff8316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff821661103b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f730000000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260208190526040902054818110156110f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f636500000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260208190526040812083830390556002805484929061112d9084906113b0565b909155505060405182815260009073ffffffffffffffffffffffffffffffffffffffff8516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610ae1565b60006020828403121561118f57600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146111bf57600080fd5b9392505050565b600060208083528351808285015260005b818110156111f3578581018301518582016040015282016111d7565b81811115611205576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461125d57600080fd5b919050565b6000806040838503121561127557600080fd5b61127e83611239565b946020939093013593505050565b6000806000606084860312156112a157600080fd5b6112aa84611239565b92506112b860208501611239565b9150604084013590509250925092565b6000602082840312156112da57600080fd5b6111bf82611239565b600080604083850312156112f657600080fd5b6112ff83611239565b915061130d60208401611239565b90509250929050565b600181811c9082168061132a57607f821691505b602082108103611363577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156113ab576113ab611369565b500190565b6000828210156113c2576113c2611369565b50039056fea164736f6c634300080f000aa164736f6c634300080f000a"; bytes internal constant systemConfigCode = - hex"608060405234801561001057600080fd5b50600436106102de5760003560e01c8063a711986911610186578063e0e2016d116100e3578063f2fde38b11610097578063f8c68de011610071578063f8c68de0146106e2578063fd32aa0f146106ea578063ffa1ad74146106f257600080fd5b8063f2fde38b146106b2578063f45e65d8146106c5578063f68016b7146106ce57600080fd5b8063e81b2c6d116100c8578063e81b2c6d14610681578063ec7075171461068a578063f2b4e617146106aa57600080fd5b8063e0e2016d14610671578063e2a3285c1461067957600080fd5b8063c9b26f611161013a578063d84447151161011f578063d84447151461064e578063dac6e63a14610656578063db9040fa1461065e57600080fd5b8063c9b26f6114610507578063cc731b021461051a57600080fd5b8063bc49ce5f1161016b578063bc49ce5f146104c6578063bfb14fb7146104ce578063c4e8ddfa146104ff57600080fd5b8063a7119869146104ab578063b40a817c146104b357600080fd5b80634397dfef1161023f578063550fcdc9116101f35780638da5cb5b116101cd5780638da5cb5b14610472578063935f029e146104905780639b7d7f0a146104a357600080fd5b8063550fcdc91461045a5780635d73369c14610462578063715018a61461046a57600080fd5b80634add321d116102245780634add321d146103e95780634f16540b146103f157806354fd4d501461041857600080fd5b80634397dfef146103ab57806348cd4cb1146103e157600080fd5b806318d13918116102965780631fd19ee11161027b5780631fd19ee114610378578063213268491461038057806321d7fde51461039857600080fd5b806318d139181461035b57806319f5cea81461037057600080fd5b80630a49cb03116102c75780630a49cb031461032b5780630ae14b1b146103335780630c18c1621461035257600080fd5b806306c92657146102e3578063078f29cf146102fe575b600080fd5b6102eb6106fa565b6040519081526020015b60405180910390f35b610306610728565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016102f5565b610306610761565b630bebc2005b60405167ffffffffffffffff90911681526020016102f5565b6102eb60655481565b61036e610369366004612241565b610791565b005b6102eb6107a5565b6103066107d0565b6103886107fa565b60405190151581526020016102f5565b61036e6103a6366004612277565b610839565b6103b361084f565b6040805173ffffffffffffffffffffffffffffffffffffffff909316835260ff9091166020830152016102f5565b6102eb610863565b610339610893565b6102eb7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c0881565b60408051808201909152600c81527f322e332e302d626574612e32000000000000000000000000000000000000000060208201525b6040516102f59190612320565b61044d6108b9565b6102eb6108c3565b61036e6108ee565b60335473ffffffffffffffffffffffffffffffffffffffff16610306565b61036e61049e366004612333565b610902565b610306610914565b610306610944565b61036e6104c136600461236d565b610974565b6102eb610985565b6068546104ea9068010000000000000000900463ffffffff1681565b60405163ffffffff90911681526020016102f5565b6103066109b0565b61036e610515366004612388565b6109e0565b6105de6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152506040805160c08101825260695463ffffffff8082168352640100000000820460ff9081166020850152650100000000008304169383019390935266010000000000008104831660608301526a0100000000000000000000810490921660808201526e0100000000000000000000000000009091046fffffffffffffffffffffffffffffffff1660a082015290565b6040516102f59190600060c08201905063ffffffff80845116835260ff602085015116602084015260ff6040850151166040840152806060850151166060840152806080850151166080840152506fffffffffffffffffffffffffffffffff60a08401511660a083015292915050565b61044d6109f1565b6103066109fb565b61036e61066c3660046124bb565b610a2b565b6102eb610e36565b6102eb610e61565b6102eb60675481565b6068546104ea906c01000000000000000000000000900463ffffffff1681565b610306610e8c565b61036e6106c0366004612241565b610ebc565b6102eb60665481565b6068546103399067ffffffffffffffff1681565b6102eb610f70565b6102eb610f9b565b6102eb600081565b61072560017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d61263d565b81565b600061075c61075860017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad637761263d565b5490565b905090565b600061075c61075860017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad61263d565b610799611201565b6107a281611282565b50565b61072560017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a861263d565b600061075c7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c085490565b60008061080561084f565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b610841611201565b61084b828261133f565b5050565b60008061085a611184565b90939092509050565b600061075c61075860017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a061263d565b60695460009061075c9063ffffffff6a0100000000000000000000820481169116612654565b606061075c61147d565b61072560017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce958063761263d565b6108f6611201565b610900600061153e565b565b61090a611201565b61084b82826115b5565b600061075c61075860017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d61263d565b600061075c61075860017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce958063761263d565b61097c611201565b6107a28161168b565b61072560017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc59861263d565b600061075c61075860017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a861263d565b6109e8611201565b6107a2816117e1565b606061075c611809565b600061075c61075860017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc59861263d565b600054610100900460ff1615808015610a4b5750600054600160ff909116105b80610a655750303b158015610a65575060005460ff166001145b610af6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610b5457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610b5c6118bf565b610b658a610ebc565b610b6e876117e1565b610b78898961133f565b610b818661168b565b610baa7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08869055565b610bdd610bd860017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc59861263d565b849055565b610c11610c0b60017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce958063761263d565b83519055565b610c48610c3f60017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a861263d565b60208401519055565b610c7f610c7660017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad637761263d565b60408401519055565b610cb6610cad60017f52322a25d9f59ea17656545543306b7aef62bc0cc53a0e65ccfa0c75b97aa90761263d565b60608401519055565b610ced610ce460017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad61263d565b60808401519055565b610d24610d1b60017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d61263d565b60a08401519055565b610d2c61195e565b610d398260c001516119c6565b610d4284611cd0565b610d4a610893565b67ffffffffffffffff168667ffffffffffffffff161015610dc7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77006044820152606401610aed565b8015610e2a57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050505050565b61072560017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a061263d565b61072560017f52322a25d9f59ea17656545543306b7aef62bc0cc53a0e65ccfa0c75b97aa90761263d565b600061075c61075860017f52322a25d9f59ea17656545543306b7aef62bc0cc53a0e65ccfa0c75b97aa90761263d565b610ec4611201565b73ffffffffffffffffffffffffffffffffffffffff8116610f67576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610aed565b6107a28161153e565b61072560017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad637761263d565b61072560017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad61263d565b9055565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b600060208251111561107a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f476173506179696e67546f6b656e3a20737472696e672063616e6e6f7420626560448201527f2067726561746572207468616e203332206279746573000000000000000000006064820152608401610aed565b6110838261115b565b92915050565b6110ef6110b760017f04adb1412b2ddc16fcc0d4538d5c8f07cf9c83abecc6b41f6f69037b708fbcec61263d565b74ff000000000000000000000000000000000000000060a086901b1673ffffffffffffffffffffffffffffffffffffffff8716179055565b61112261111d60017f657c3582c29b3176614e3a33ddd1ec48352696a04e92b3c0566d72010fa8863d61263d565b839055565b61115561115060017fa48b38a4b44951360fbdcbfaaeae5ed6ae92585412e9841b70ec72ed8cd0576461263d565b829055565b50505050565b8051602181106111735763ec92f9a36000526004601cfd5b9081015160209190910360031b1b90565b600080806111b661075860017f04adb1412b2ddc16fcc0d4538d5c8f07cf9c83abecc6b41f6f69037b708fbcec61263d565b73ffffffffffffffffffffffffffffffffffffffff811693509050826111f5575073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee92601292509050565b60a081901c9150509091565b60335473ffffffffffffffffffffffffffffffffffffffff163314610900576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610aed565b6112ab7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08829055565b6040805173ffffffffffffffffffffffffffffffffffffffff8316602082015260009101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060035b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be836040516113339190612320565b60405180910390a35050565b606880547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff166801000000000000000063ffffffff8581169182027fffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffff16929092176c0100000000000000000000000092851692909202919091179091557f0100000000000000000000000000000000000000000000000000000000000000602083811b67ffffffff000000001690921717606681905560655460408051938401919091528201526000906060015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529050600160007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be836040516114709190612320565b60405180910390a3505050565b60606000611489611184565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff82160161150257505060408051808201909152600381527f4554480000000000000000000000000000000000000000000000000000000000602082015290565b61153861153361075860017fa48b38a4b44951360fbdcbfaaeae5ed6ae92585412e9841b70ec72ed8cd0576461263d565b612144565b91505090565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b7fff00000000000000000000000000000000000000000000000000000000000000811615611665576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f53797374656d436f6e6669673a207363616c61722065786365656473206d617860448201527f2e000000000000000000000000000000000000000000000000000000000000006064820152608401610aed565b60658290556066819055604080516020810184905290810182905260009060600161140d565b611693610893565b67ffffffffffffffff168167ffffffffffffffff161015611710576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77006044820152606401610aed565b630bebc20067ffffffffffffffff82161115611788576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f20686967686044820152606401610aed565b606880547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff83169081179091556040805160208082019390935281518082039093018352810190526002611302565b6067819055604080516020808201849052825180830390910181529082019091526000611302565b60606000611815611184565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff82160161188e57505060408051808201909152600581527f4574686572000000000000000000000000000000000000000000000000000000602082015290565b61153861153361075860017f657c3582c29b3176614e3a33ddd1ec48352696a04e92b3c0566d72010fa8863d61263d565b600054610100900460ff16611956576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610aed565b610900612178565b61198c61075860017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a061263d565b600003610900576109006119c160017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a061263d565b439055565b73ffffffffffffffffffffffffffffffffffffffff811615801590611a15575073ffffffffffffffffffffffffffffffffffffffff811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14155b8015611a265750611a246107fa565b155b156107a257601260ff168173ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a9f9190612680565b60ff1614611b2f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f53797374656d436f6e6669673a2062616420646563696d616c73206f6620676160448201527f7320706179696e6720746f6b656e0000000000000000000000000000000000006064820152608401610aed565b6000611bca8273ffffffffffffffffffffffffffffffffffffffff166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa158015611b7f573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611bc5919081019061269d565b610fe6565b90506000611c1c8373ffffffffffffffffffffffffffffffffffffffff166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015611b7f573d6000803e3d6000fd5b9050611c2b8360128484611089565b611c33610761565b6040517f71cfaa3f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015260126024830152604482018590526064820184905291909116906371cfaa3f90608401600060405180830381600087803b158015611cb357600080fd5b505af1158015611cc7573d6000803e3d6000fd5b50505050505050565b8060a001516fffffffffffffffffffffffffffffffff16816060015163ffffffff161115611d80576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f53797374656d436f6e6669673a206d696e206261736520666565206d7573742060448201527f6265206c657373207468616e206d6178206261736500000000000000000000006064820152608401610aed565b6001816040015160ff1611611e17576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f53797374656d436f6e6669673a2064656e6f6d696e61746f72206d757374206260448201527f65206c6172676572207468616e203100000000000000000000000000000000006064820152608401610aed565b6068546080820151825167ffffffffffffffff90921691611e389190612768565b63ffffffff161115611ea6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77006044820152606401610aed565b6000816020015160ff1611611f3d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f53797374656d436f6e6669673a20656c6173746963697479206d756c7469706c60448201527f6965722063616e6e6f74206265203000000000000000000000000000000000006064820152608401610aed565b8051602082015163ffffffff82169160ff90911690611f5d908290612787565b611f6791906127d1565b63ffffffff1614611ffa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f53797374656d436f6e6669673a20707265636973696f6e206c6f73732077697460448201527f6820746172676574207265736f75726365206c696d69740000000000000000006064820152608401610aed565b805160698054602084015160408501516060860151608087015160a09097015163ffffffff9687167fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009095169490941764010000000060ff94851602177fffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffff166501000000000093909216929092027fffffffffffffffffffffffffffffffffffffffffffff00000000ffffffffffff1617660100000000000091851691909102177fffff0000000000000000000000000000000000000000ffffffffffffffffffff166a010000000000000000000093909416929092027fffff00000000000000000000000000000000ffffffffffffffffffffffffffff16929092176e0100000000000000000000000000006fffffffffffffffffffffffffffffffff90921691909102179055565b60405160005b82811a1561215a5760010161214a565b80825260208201838152600082820152505060408101604052919050565b600054610100900460ff1661220f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610aed565b6109003361153e565b803573ffffffffffffffffffffffffffffffffffffffff8116811461223c57600080fd5b919050565b60006020828403121561225357600080fd5b61225c82612218565b9392505050565b803563ffffffff8116811461223c57600080fd5b6000806040838503121561228a57600080fd5b61229383612263565b91506122a160208401612263565b90509250929050565b60005b838110156122c55781810151838201526020016122ad565b838111156111555750506000910152565b600081518084526122ee8160208601602086016122aa565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061225c60208301846122d6565b6000806040838503121561234657600080fd5b50508035926020909101359150565b803567ffffffffffffffff8116811461223c57600080fd5b60006020828403121561237f57600080fd5b61225c82612355565b60006020828403121561239a57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160c0810167ffffffffffffffff811182821017156123f3576123f36123a1565b60405290565b60ff811681146107a257600080fd5b600060e0828403121561241a57600080fd5b60405160e0810181811067ffffffffffffffff8211171561243d5761243d6123a1565b60405290508061244c83612218565b815261245a60208401612218565b602082015261246b60408401612218565b604082015261247c60608401612218565b606082015261248d60808401612218565b608082015261249e60a08401612218565b60a08201526124af60c08401612218565b60c08201525092915050565b6000806000806000806000806000898b036102808112156124db57600080fd5b6124e48b612218565b99506124f260208c01612263565b985061250060408c01612263565b975060608b0135965061251560808c01612355565b955061252360a08c01612218565b945060c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff408201121561255557600080fd5b5061255e6123d0565b61256a60c08c01612263565b815260e08b013561257a816123f9565b60208201526101008b013561258e816123f9565b60408201526125a06101208c01612263565b60608201526125b26101408c01612263565b60808201526101608b01356fffffffffffffffffffffffffffffffff811681146125db57600080fd5b60a082015292506125ef6101808b01612218565b91506125ff8b6101a08c01612408565b90509295985092959850929598565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008282101561264f5761264f61260e565b500390565b600067ffffffffffffffff8083168185168083038211156126775761267761260e565b01949350505050565b60006020828403121561269257600080fd5b815161225c816123f9565b6000602082840312156126af57600080fd5b815167ffffffffffffffff808211156126c757600080fd5b818401915084601f8301126126db57600080fd5b8151818111156126ed576126ed6123a1565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715612733576127336123a1565b8160405282815287602084870101111561274c57600080fd5b61275d8360208301602088016122aa565b979650505050505050565b600063ffffffff8083168185168083038211156126775761267761260e565b600063ffffffff808416806127c5577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b92169190910492915050565b600063ffffffff808316818516818304811182151516156127f4576127f461260e565b0294935050505056fea164736f6c634300080f000a"; +- hex"608060405234801561001057600080fd5b50600436106102de5760003560e01c8063a711986911610186578063e0e2016d116100e3578063f2fde38b11610097578063f8c68de011610071578063f8c68de0146106e2578063fd32aa0f146106ea578063ffa1ad74146106f257600080fd5b8063f2fde38b146106b2578063f45e65d8146106c5578063f68016b7146106ce57600080fd5b8063e81b2c6d116100c8578063e81b2c6d14610681578063ec7075171461068a578063f2b4e617146106aa57600080fd5b8063e0e2016d14610671578063e2a3285c1461067957600080fd5b8063c9b26f611161013a578063d84447151161011f578063d84447151461064e578063dac6e63a14610656578063db9040fa1461065e57600080fd5b8063c9b26f6114610507578063cc731b021461051a57600080fd5b8063bc49ce5f1161016b578063bc49ce5f146104c6578063bfb14fb7146104ce578063c4e8ddfa146104ff57600080fd5b8063a7119869146104ab578063b40a817c146104b357600080fd5b80634397dfef1161023f578063550fcdc9116101f35780638da5cb5b116101cd5780638da5cb5b14610472578063935f029e146104905780639b7d7f0a146104a357600080fd5b8063550fcdc91461045a5780635d73369c14610462578063715018a61461046a57600080fd5b80634add321d116102245780634add321d146103e95780634f16540b146103f157806354fd4d501461041857600080fd5b80634397dfef146103ab57806348cd4cb1146103e157600080fd5b806318d13918116102965780631fd19ee11161027b5780631fd19ee114610378578063213268491461038057806321d7fde51461039857600080fd5b806318d139181461035b57806319f5cea81461037057600080fd5b80630a49cb03116102c75780630a49cb031461032b5780630ae14b1b146103335780630c18c1621461035257600080fd5b806306c92657146102e3578063078f29cf146102fe575b600080fd5b6102eb6106fa565b6040519081526020015b60405180910390f35b610306610728565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016102f5565b610306610761565b630bebc2005b60405167ffffffffffffffff90911681526020016102f5565b6102eb60655481565b61036e610369366004612241565b610791565b005b6102eb6107a5565b6103066107d0565b6103886107fa565b60405190151581526020016102f5565b61036e6103a6366004612277565b610839565b6103b361084f565b6040805173ffffffffffffffffffffffffffffffffffffffff909316835260ff9091166020830152016102f5565b6102eb610863565b610339610893565b6102eb7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c0881565b60408051808201909152600c81527f322e332e302d626574612e32000000000000000000000000000000000000000060208201525b6040516102f59190612320565b61044d6108b9565b6102eb6108c3565b61036e6108ee565b60335473ffffffffffffffffffffffffffffffffffffffff16610306565b61036e61049e366004612333565b610902565b610306610914565b610306610944565b61036e6104c136600461236d565b610974565b6102eb610985565b6068546104ea9068010000000000000000900463ffffffff1681565b60405163ffffffff90911681526020016102f5565b6103066109b0565b61036e610515366004612388565b6109e0565b6105de6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152506040805160c08101825260695463ffffffff8082168352640100000000820460ff9081166020850152650100000000008304169383019390935266010000000000008104831660608301526a0100000000000000000000810490921660808201526e0100000000000000000000000000009091046fffffffffffffffffffffffffffffffff1660a082015290565b6040516102f59190600060c08201905063ffffffff80845116835260ff602085015116602084015260ff6040850151166040840152806060850151166060840152806080850151166080840152506fffffffffffffffffffffffffffffffff60a08401511660a083015292915050565b61044d6109f1565b6103066109fb565b61036e61066c3660046124bb565b610a2b565b6102eb610e36565b6102eb610e61565b6102eb60675481565b6068546104ea906c01000000000000000000000000900463ffffffff1681565b610306610e8c565b61036e6106c0366004612241565b610ebc565b6102eb60665481565b6068546103399067ffffffffffffffff1681565b6102eb610f70565b6102eb610f9b565b6102eb600081565b61072560017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d61263d565b81565b600061075c61075860017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad637761263d565b5490565b905090565b600061075c61075860017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad61263d565b610799611201565b6107a281611282565b50565b61072560017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a861263d565b600061075c7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c085490565b60008061080561084f565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b610841611201565b61084b828261133f565b5050565b60008061085a611184565b90939092509050565b600061075c61075860017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a061263d565b60695460009061075c9063ffffffff6a0100000000000000000000820481169116612654565b606061075c61147d565b61072560017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce958063761263d565b6108f6611201565b610900600061153e565b565b61090a611201565b61084b82826115b5565b600061075c61075860017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d61263d565b600061075c61075860017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce958063761263d565b61097c611201565b6107a28161168b565b61072560017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc59861263d565b600061075c61075860017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a861263d565b6109e8611201565b6107a2816117e1565b606061075c611809565b600061075c61075860017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc59861263d565b600054610100900460ff1615808015610a4b5750600054600160ff909116105b80610a655750303b158015610a65575060005460ff166001145b610af6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610b5457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610b5c6118bf565b610b658a610ebc565b610b6e876117e1565b610b78898961133f565b610b818661168b565b610baa7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08869055565b610bdd610bd860017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc59861263d565b849055565b610c11610c0b60017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce958063761263d565b83519055565b610c48610c3f60017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a861263d565b60208401519055565b610c7f610c7660017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad637761263d565b60408401519055565b610cb6610cad60017f52322a25d9f59ea17656545543306b7aef62bc0cc53a0e65ccfa0c75b97aa90761263d565b60608401519055565b610ced610ce460017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad61263d565b60808401519055565b610d24610d1b60017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d61263d565b60a08401519055565b610d2c61195e565b610d398260c001516119c6565b610d4284611cd0565b610d4a610893565b67ffffffffffffffff168667ffffffffffffffff161015610dc7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77006044820152606401610aed565b8015610e2a57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050505050565b61072560017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a061263d565b61072560017f52322a25d9f59ea17656545543306b7aef62bc0cc53a0e65ccfa0c75b97aa90761263d565b600061075c61075860017f52322a25d9f59ea17656545543306b7aef62bc0cc53a0e65ccfa0c75b97aa90761263d565b610ec4611201565b73ffffffffffffffffffffffffffffffffffffffff8116610f67576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610aed565b6107a28161153e565b61072560017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad637761263d565b61072560017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad61263d565b9055565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b600060208251111561107a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f476173506179696e67546f6b656e3a20737472696e672063616e6e6f7420626560448201527f2067726561746572207468616e203332206279746573000000000000000000006064820152608401610aed565b6110838261115b565b92915050565b6110ef6110b760017f04adb1412b2ddc16fcc0d4538d5c8f07cf9c83abecc6b41f6f69037b708fbcec61263d565b74ff000000000000000000000000000000000000000060a086901b1673ffffffffffffffffffffffffffffffffffffffff8716179055565b61112261111d60017f657c3582c29b3176614e3a33ddd1ec48352696a04e92b3c0566d72010fa8863d61263d565b839055565b61115561115060017fa48b38a4b44951360fbdcbfaaeae5ed6ae92585412e9841b70ec72ed8cd0576461263d565b829055565b50505050565b8051602181106111735763ec92f9a36000526004601cfd5b9081015160209190910360031b1b90565b600080806111b661075860017f04adb1412b2ddc16fcc0d4538d5c8f07cf9c83abecc6b41f6f69037b708fbcec61263d565b73ffffffffffffffffffffffffffffffffffffffff811693509050826111f5575073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee92601292509050565b60a081901c9150509091565b60335473ffffffffffffffffffffffffffffffffffffffff163314610900576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610aed565b6112ab7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08829055565b6040805173ffffffffffffffffffffffffffffffffffffffff8316602082015260009101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060035b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be836040516113339190612320565b60405180910390a35050565b606880547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff166801000000000000000063ffffffff8581169182027fffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffff16929092176c0100000000000000000000000092851692909202919091179091557f0100000000000000000000000000000000000000000000000000000000000000602083811b67ffffffff000000001690921717606681905560655460408051938401919091528201526000906060015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529050600160007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be836040516114709190612320565b60405180910390a3505050565b60606000611489611184565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff82160161150257505060408051808201909152600381527f4554480000000000000000000000000000000000000000000000000000000000602082015290565b61153861153361075860017fa48b38a4b44951360fbdcbfaaeae5ed6ae92585412e9841b70ec72ed8cd0576461263d565b612144565b91505090565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b7fff00000000000000000000000000000000000000000000000000000000000000811615611665576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f53797374656d436f6e6669673a207363616c61722065786365656473206d617860448201527f2e000000000000000000000000000000000000000000000000000000000000006064820152608401610aed565b60658290556066819055604080516020810184905290810182905260009060600161140d565b611693610893565b67ffffffffffffffff168167ffffffffffffffff161015611710576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77006044820152606401610aed565b630bebc20067ffffffffffffffff82161115611788576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f20686967686044820152606401610aed565b606880547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff83169081179091556040805160208082019390935281518082039093018352810190526002611302565b6067819055604080516020808201849052825180830390910181529082019091526000611302565b60606000611815611184565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff82160161188e57505060408051808201909152600581527f4574686572000000000000000000000000000000000000000000000000000000602082015290565b61153861153361075860017f657c3582c29b3176614e3a33ddd1ec48352696a04e92b3c0566d72010fa8863d61263d565b600054610100900460ff16611956576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610aed565b610900612178565b61198c61075860017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a061263d565b600003610900576109006119c160017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a061263d565b439055565b73ffffffffffffffffffffffffffffffffffffffff811615801590611a15575073ffffffffffffffffffffffffffffffffffffffff811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14155b8015611a265750611a246107fa565b155b156107a257601260ff168173ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a9f9190612680565b60ff1614611b2f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f53797374656d436f6e6669673a2062616420646563696d616c73206f6620676160448201527f7320706179696e6720746f6b656e0000000000000000000000000000000000006064820152608401610aed565b6000611bca8273ffffffffffffffffffffffffffffffffffffffff166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa158015611b7f573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611bc5919081019061269d565b610fe6565b90506000611c1c8373ffffffffffffffffffffffffffffffffffffffff166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015611b7f573d6000803e3d6000fd5b9050611c2b8360128484611089565b611c33610761565b6040517f71cfaa3f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015260126024830152604482018590526064820184905291909116906371cfaa3f90608401600060405180830381600087803b158015611cb357600080fd5b505af1158015611cc7573d6000803e3d6000fd5b50505050505050565b8060a001516fffffffffffffffffffffffffffffffff16816060015163ffffffff161115611d80576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f53797374656d436f6e6669673a206d696e206261736520666565206d7573742060448201527f6265206c657373207468616e206d6178206261736500000000000000000000006064820152608401610aed565b6001816040015160ff1611611e17576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f53797374656d436f6e6669673a2064656e6f6d696e61746f72206d757374206260448201527f65206c6172676572207468616e203100000000000000000000000000000000006064820152608401610aed565b6068546080820151825167ffffffffffffffff90921691611e389190612768565b63ffffffff161115611ea6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77006044820152606401610aed565b6000816020015160ff1611611f3d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f53797374656d436f6e6669673a20656c6173746963697479206d756c7469706c60448201527f6965722063616e6e6f74206265203000000000000000000000000000000000006064820152608401610aed565b8051602082015163ffffffff82169160ff90911690611f5d908290612787565b611f6791906127d1565b63ffffffff1614611ffa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f53797374656d436f6e6669673a20707265636973696f6e206c6f73732077697460448201527f6820746172676574207265736f75726365206c696d69740000000000000000006064820152608401610aed565b805160698054602084015160408501516060860151608087015160a09097015163ffffffff9687167fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009095169490941764010000000060ff94851602177fffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffff166501000000000093909216929092027fffffffffffffffffffffffffffffffffffffffffffff00000000ffffffffffff1617660100000000000091851691909102177fffff0000000000000000000000000000000000000000ffffffffffffffffffff166a010000000000000000000093909416929092027fffff00000000000000000000000000000000ffffffffffffffffffffffffffff16929092176e0100000000000000000000000000006fffffffffffffffffffffffffffffffff90921691909102179055565b60405160005b82811a1561215a5760010161214a565b80825260208201838152600082820152505060408101604052919050565b600054610100900460ff1661220f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610aed565b6109003361153e565b803573ffffffffffffffffffffffffffffffffffffffff8116811461223c57600080fd5b919050565b60006020828403121561225357600080fd5b61225c82612218565b9392505050565b803563ffffffff8116811461223c57600080fd5b6000806040838503121561228a57600080fd5b61229383612263565b91506122a160208401612263565b90509250929050565b60005b838110156122c55781810151838201526020016122ad565b838111156111555750506000910152565b600081518084526122ee8160208601602086016122aa565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061225c60208301846122d6565b6000806040838503121561234657600080fd5b50508035926020909101359150565b803567ffffffffffffffff8116811461223c57600080fd5b60006020828403121561237f57600080fd5b61225c82612355565b60006020828403121561239a57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160c0810167ffffffffffffffff811182821017156123f3576123f36123a1565b60405290565b60ff811681146107a257600080fd5b600060e0828403121561241a57600080fd5b60405160e0810181811067ffffffffffffffff8211171561243d5761243d6123a1565b60405290508061244c83612218565b815261245a60208401612218565b602082015261246b60408401612218565b604082015261247c60608401612218565b606082015261248d60808401612218565b608082015261249e60a08401612218565b60a08201526124af60c08401612218565b60c08201525092915050565b6000806000806000806000806000898b036102808112156124db57600080fd5b6124e48b612218565b99506124f260208c01612263565b985061250060408c01612263565b975060608b0135965061251560808c01612355565b955061252360a08c01612218565b945060c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff408201121561255557600080fd5b5061255e6123d0565b61256a60c08c01612263565b815260e08b013561257a816123f9565b60208201526101008b013561258e816123f9565b60408201526125a06101208c01612263565b60608201526125b26101408c01612263565b60808201526101608b01356fffffffffffffffffffffffffffffffff811681146125db57600080fd5b60a082015292506125ef6101808b01612218565b91506125ff8b6101a08c01612408565b90509295985092959850929598565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008282101561264f5761264f61260e565b500390565b600067ffffffffffffffff8083168185168083038211156126775761267761260e565b01949350505050565b60006020828403121561269257600080fd5b815161225c816123f9565b6000602082840312156126af57600080fd5b815167ffffffffffffffff808211156126c757600080fd5b818401915084601f8301126126db57600080fd5b8151818111156126ed576126ed6123a1565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715612733576127336123a1565b8160405282815287602084870101111561274c57600080fd5b61275d8360208301602088016122aa565b979650505050505050565b600063ffffffff8083168185168083038211156126775761267761260e565b600063ffffffff808416806127c5577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b92169190910492915050565b600063ffffffff808316818516818304811182151516156127f4576127f461260e565b0294935050505056fea164736f6c634300080f000a"; ++ hex"608060405234801561001057600080fd5b50600436106102de5760003560e01c8063a711986911610186578063e0e2016d116100e3578063f2fde38b11610097578063f8c68de011610071578063f8c68de0146106e2578063fd32aa0f146106ea578063ffa1ad74146106f257600080fd5b8063f2fde38b146106b2578063f45e65d8146106c5578063f68016b7146106ce57600080fd5b8063e81b2c6d116100c8578063e81b2c6d14610681578063ec7075171461068a578063f2b4e617146106aa57600080fd5b8063e0e2016d14610671578063e2a3285c1461067957600080fd5b8063c9b26f611161013a578063d84447151161011f578063d84447151461064e578063dac6e63a14610656578063db9040fa1461065e57600080fd5b8063c9b26f6114610507578063cc731b021461051a57600080fd5b8063bc49ce5f1161016b578063bc49ce5f146104c6578063bfb14fb7146104ce578063c4e8ddfa146104ff57600080fd5b8063a7119869146104ab578063b40a817c146104b357600080fd5b80634397dfef1161023f578063550fcdc9116101f35780638da5cb5b116101cd5780638da5cb5b14610472578063935f029e146104905780639b7d7f0a146104a357600080fd5b8063550fcdc91461045a5780635d73369c14610462578063715018a61461046a57600080fd5b80634add321d116102245780634add321d146103e95780634f16540b146103f157806354fd4d501461041857600080fd5b80634397dfef146103ab57806348cd4cb1146103e157600080fd5b806318d13918116102965780631fd19ee11161027b5780631fd19ee114610378578063213268491461038057806321d7fde51461039857600080fd5b806318d139181461035b57806319f5cea81461037057600080fd5b80630a49cb03116102c75780630a49cb031461032b5780630ae14b1b146103335780630c18c1621461035257600080fd5b806306c92657146102e3578063078f29cf146102fe575b600080fd5b6102eb6106fa565b6040519081526020015b60405180910390f35b610306610728565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016102f5565b610306610761565b630bebc2005b60405167ffffffffffffffff90911681526020016102f5565b6102eb60655481565b61036e610369366004612241565b610791565b005b6102eb6107a5565b6103066107d0565b6103886107fa565b60405190151581526020016102f5565b61036e6103a6366004612277565b610839565b6103b361084f565b6040805173ffffffffffffffffffffffffffffffffffffffff909316835260ff9091166020830152016102f5565b6102eb610863565b610339610893565b6102eb7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c0881565b60408051808201909152600c81527f322e332e302d626574612e33000000000000000000000000000000000000000060208201525b6040516102f59190612320565b61044d6108b9565b6102eb6108c3565b61036e6108ee565b60335473ffffffffffffffffffffffffffffffffffffffff16610306565b61036e61049e366004612333565b610902565b610306610914565b610306610944565b61036e6104c136600461236d565b610974565b6102eb610985565b6068546104ea9068010000000000000000900463ffffffff1681565b60405163ffffffff90911681526020016102f5565b6103066109b0565b61036e610515366004612388565b6109e0565b6105de6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152506040805160c08101825260695463ffffffff8082168352640100000000820460ff9081166020850152650100000000008304169383019390935266010000000000008104831660608301526a0100000000000000000000810490921660808201526e0100000000000000000000000000009091046fffffffffffffffffffffffffffffffff1660a082015290565b6040516102f59190600060c08201905063ffffffff80845116835260ff602085015116602084015260ff6040850151166040840152806060850151166060840152806080850151166080840152506fffffffffffffffffffffffffffffffff60a08401511660a083015292915050565b61044d6109f1565b6103066109fb565b61036e61066c3660046124bb565b610a2b565b6102eb610e36565b6102eb610e61565b6102eb60675481565b6068546104ea906c01000000000000000000000000900463ffffffff1681565b610306610e8c565b61036e6106c0366004612241565b610ebc565b6102eb60665481565b6068546103399067ffffffffffffffff1681565b6102eb610f70565b6102eb610f9b565b6102eb600081565b61072560017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d61263d565b81565b600061075c61075860017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad637761263d565b5490565b905090565b600061075c61075860017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad61263d565b610799611201565b6107a281611282565b50565b61072560017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a861263d565b600061075c7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c085490565b60008061080561084f565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b610841611201565b61084b828261133f565b5050565b60008061085a611184565b90939092509050565b600061075c61075860017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a061263d565b60695460009061075c9063ffffffff6a0100000000000000000000820481169116612654565b606061075c61147d565b61072560017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce958063761263d565b6108f6611201565b610900600061153e565b565b61090a611201565b61084b82826115b5565b600061075c61075860017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d61263d565b600061075c61075860017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce958063761263d565b61097c611201565b6107a28161168b565b61072560017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc59861263d565b600061075c61075860017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a861263d565b6109e8611201565b6107a2816117e1565b606061075c611809565b600061075c61075860017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc59861263d565b600054610100900460ff1615808015610a4b5750600054600160ff909116105b80610a655750303b158015610a65575060005460ff166001145b610af6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610b5457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610b5c6118bf565b610b658a610ebc565b610b6e876117e1565b610b78898961133f565b610b818661168b565b610baa7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08869055565b610bdd610bd860017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc59861263d565b849055565b610c11610c0b60017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce958063761263d565b83519055565b610c48610c3f60017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a861263d565b60208401519055565b610c7f610c7660017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad637761263d565b60408401519055565b610cb6610cad60017f52322a25d9f59ea17656545543306b7aef62bc0cc53a0e65ccfa0c75b97aa90761263d565b60608401519055565b610ced610ce460017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad61263d565b60808401519055565b610d24610d1b60017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d61263d565b60a08401519055565b610d2c61195e565b610d398260c001516119c6565b610d4284611cd0565b610d4a610893565b67ffffffffffffffff168667ffffffffffffffff161015610dc7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77006044820152606401610aed565b8015610e2a57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050505050565b61072560017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a061263d565b61072560017f52322a25d9f59ea17656545543306b7aef62bc0cc53a0e65ccfa0c75b97aa90761263d565b600061075c61075860017f52322a25d9f59ea17656545543306b7aef62bc0cc53a0e65ccfa0c75b97aa90761263d565b610ec4611201565b73ffffffffffffffffffffffffffffffffffffffff8116610f67576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610aed565b6107a28161153e565b61072560017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad637761263d565b61072560017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad61263d565b9055565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b600060208251111561107a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f476173506179696e67546f6b656e3a20737472696e672063616e6e6f7420626560448201527f2067726561746572207468616e203332206279746573000000000000000000006064820152608401610aed565b6110838261115b565b92915050565b6110ef6110b760017f04adb1412b2ddc16fcc0d4538d5c8f07cf9c83abecc6b41f6f69037b708fbcec61263d565b74ff000000000000000000000000000000000000000060a086901b1673ffffffffffffffffffffffffffffffffffffffff8716179055565b61112261111d60017f657c3582c29b3176614e3a33ddd1ec48352696a04e92b3c0566d72010fa8863d61263d565b839055565b61115561115060017fa48b38a4b44951360fbdcbfaaeae5ed6ae92585412e9841b70ec72ed8cd0576461263d565b829055565b50505050565b8051602181106111735763ec92f9a36000526004601cfd5b9081015160209190910360031b1b90565b600080806111b661075860017f04adb1412b2ddc16fcc0d4538d5c8f07cf9c83abecc6b41f6f69037b708fbcec61263d565b73ffffffffffffffffffffffffffffffffffffffff811693509050826111f5575073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee92601292509050565b60a081901c9150509091565b60335473ffffffffffffffffffffffffffffffffffffffff163314610900576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610aed565b6112ab7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08829055565b6040805173ffffffffffffffffffffffffffffffffffffffff8316602082015260009101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060035b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be836040516113339190612320565b60405180910390a35050565b606880547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff166801000000000000000063ffffffff8581169182027fffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffff16929092176c0100000000000000000000000092851692909202919091179091557f0100000000000000000000000000000000000000000000000000000000000000602083811b67ffffffff000000001690921717606681905560655460408051938401919091528201526000906060015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529050600160007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be836040516114709190612320565b60405180910390a3505050565b60606000611489611184565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff82160161150257505060408051808201909152600381527f4554480000000000000000000000000000000000000000000000000000000000602082015290565b61153861153361075860017fa48b38a4b44951360fbdcbfaaeae5ed6ae92585412e9841b70ec72ed8cd0576461263d565b612144565b91505090565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b7fff00000000000000000000000000000000000000000000000000000000000000811615611665576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f53797374656d436f6e6669673a207363616c61722065786365656473206d617860448201527f2e000000000000000000000000000000000000000000000000000000000000006064820152608401610aed565b60658290556066819055604080516020810184905290810182905260009060600161140d565b611693610893565b67ffffffffffffffff168167ffffffffffffffff161015611710576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77006044820152606401610aed565b630bebc20067ffffffffffffffff82161115611788576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f20686967686044820152606401610aed565b606880547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff83169081179091556040805160208082019390935281518082039093018352810190526002611302565b6067819055604080516020808201849052825180830390910181529082019091526000611302565b60606000611815611184565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff82160161188e57505060408051808201909152600581527f4574686572000000000000000000000000000000000000000000000000000000602082015290565b61153861153361075860017f657c3582c29b3176614e3a33ddd1ec48352696a04e92b3c0566d72010fa8863d61263d565b600054610100900460ff16611956576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610aed565b610900612178565b61198c61075860017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a061263d565b600003610900576109006119c160017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a061263d565b439055565b73ffffffffffffffffffffffffffffffffffffffff811615801590611a15575073ffffffffffffffffffffffffffffffffffffffff811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14155b8015611a265750611a246107fa565b155b156107a257601260ff168173ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a9f9190612680565b60ff1614611b2f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f53797374656d436f6e6669673a2062616420646563696d616c73206f6620676160448201527f7320706179696e6720746f6b656e0000000000000000000000000000000000006064820152608401610aed565b6000611bca8273ffffffffffffffffffffffffffffffffffffffff166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa158015611b7f573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611bc5919081019061269d565b610fe6565b90506000611c1c8373ffffffffffffffffffffffffffffffffffffffff166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015611b7f573d6000803e3d6000fd5b9050611c2b8360128484611089565b611c33610761565b6040517f71cfaa3f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015260126024830152604482018590526064820184905291909116906371cfaa3f90608401600060405180830381600087803b158015611cb357600080fd5b505af1158015611cc7573d6000803e3d6000fd5b50505050505050565b8060a001516fffffffffffffffffffffffffffffffff16816060015163ffffffff161115611d80576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f53797374656d436f6e6669673a206d696e206261736520666565206d7573742060448201527f6265206c657373207468616e206d6178206261736500000000000000000000006064820152608401610aed565b6001816040015160ff1611611e17576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f53797374656d436f6e6669673a2064656e6f6d696e61746f72206d757374206260448201527f65206c6172676572207468616e203100000000000000000000000000000000006064820152608401610aed565b6068546080820151825167ffffffffffffffff90921691611e389190612768565b63ffffffff161115611ea6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77006044820152606401610aed565b6000816020015160ff1611611f3d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f53797374656d436f6e6669673a20656c6173746963697479206d756c7469706c60448201527f6965722063616e6e6f74206265203000000000000000000000000000000000006064820152608401610aed565b8051602082015163ffffffff82169160ff90911690611f5d908290612787565b611f6791906127d1565b63ffffffff1614611ffa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f53797374656d436f6e6669673a20707265636973696f6e206c6f73732077697460448201527f6820746172676574207265736f75726365206c696d69740000000000000000006064820152608401610aed565b805160698054602084015160408501516060860151608087015160a09097015163ffffffff9687167fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009095169490941764010000000060ff94851602177fffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffff166501000000000093909216929092027fffffffffffffffffffffffffffffffffffffffffffff00000000ffffffffffff1617660100000000000091851691909102177fffff0000000000000000000000000000000000000000ffffffffffffffffffff166a010000000000000000000093909416929092027fffff00000000000000000000000000000000ffffffffffffffffffffffffffff16929092176e0100000000000000000000000000006fffffffffffffffffffffffffffffffff90921691909102179055565b60405160005b82811a1561215a5760010161214a565b80825260208201838152600082820152505060408101604052919050565b600054610100900460ff1661220f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610aed565b6109003361153e565b803573ffffffffffffffffffffffffffffffffffffffff8116811461223c57600080fd5b919050565b60006020828403121561225357600080fd5b61225c82612218565b9392505050565b803563ffffffff8116811461223c57600080fd5b6000806040838503121561228a57600080fd5b61229383612263565b91506122a160208401612263565b90509250929050565b60005b838110156122c55781810151838201526020016122ad565b838111156111555750506000910152565b600081518084526122ee8160208601602086016122aa565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061225c60208301846122d6565b6000806040838503121561234657600080fd5b50508035926020909101359150565b803567ffffffffffffffff8116811461223c57600080fd5b60006020828403121561237f57600080fd5b61225c82612355565b60006020828403121561239a57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160c0810167ffffffffffffffff811182821017156123f3576123f36123a1565b60405290565b60ff811681146107a257600080fd5b600060e0828403121561241a57600080fd5b60405160e0810181811067ffffffffffffffff8211171561243d5761243d6123a1565b60405290508061244c83612218565b815261245a60208401612218565b602082015261246b60408401612218565b604082015261247c60608401612218565b606082015261248d60808401612218565b608082015261249e60a08401612218565b60a08201526124af60c08401612218565b60c08201525092915050565b6000806000806000806000806000898b036102808112156124db57600080fd5b6124e48b612218565b99506124f260208c01612263565b985061250060408c01612263565b975060608b0135965061251560808c01612355565b955061252360a08c01612218565b945060c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff408201121561255557600080fd5b5061255e6123d0565b61256a60c08c01612263565b815260e08b013561257a816123f9565b60208201526101008b013561258e816123f9565b60408201526125a06101208c01612263565b60608201526125b26101408c01612263565b60808201526101608b01356fffffffffffffffffffffffffffffffff811681146125db57600080fd5b60a082015292506125ef6101808b01612218565b91506125ff8b6101a08c01612408565b90509295985092959850929598565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008282101561264f5761264f61260e565b500390565b600067ffffffffffffffff8083168185168083038211156126775761267761260e565b01949350505050565b60006020828403121561269257600080fd5b815161225c816123f9565b6000602082840312156126af57600080fd5b815167ffffffffffffffff808211156126c757600080fd5b818401915084601f8301126126db57600080fd5b8151818111156126ed576126ed6123a1565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715612733576127336123a1565b8160405282815287602084870101111561274c57600080fd5b61275d8360208301602088016122aa565b979650505050505050565b600063ffffffff8083168185168083038211156126775761267761260e565b600063ffffffff808416806127c5577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b92169190910492915050565b600063ffffffff808316818516818304811182151516156127f4576127f461260e565b0294935050505056fea164736f6c634300080f000a"; bytes internal constant l1StandardBridgeCode = -@@ -55,7 +55,7 @@ hex"6080604052600436106101845760003560e01c80637f46ddb2116100d65780639a2ac6d51161007f578063c0c53b8b11610059578063c0c53b8b14610529578063c89701a214610549578063e11013dd1461057657600080fd5b80639a2ac6d5146104e3578063a9f9e675146104f6578063b1a1a8821461051657600080fd5b80638f601f66116100b05780638f601f661461047257806391c49bf814610407578063927ede2d146104b857600080fd5b80637f46ddb214610407578063838b252014610432578063870876231461045257600080fd5b806335e80ab31161013857806354fd4d501161011257806354fd4d501461036c57806358a997f6146103c25780635c975abb146103e257600080fd5b806335e80ab3146102f25780633cb747bf1461031f578063540abf731461034c57600080fd5b80631532ec34116101695780631532ec34146102755780631635f5fd1461028857806333d7e2bd1461029b57600080fd5b80630166a07a1461024257806309fc88431461026257600080fd5b3661023d57333b1561021d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084015b60405180910390fd5b61023b333362030d40604051806020016040528060008152506105a5565b005b600080fd5b34801561024e57600080fd5b5061023b61025d366004612991565b6105b8565b61023b610270366004612a42565b6109d2565b61023b610283366004612a95565b610aa9565b61023b610296366004612a95565b610abd565b3480156102a757600080fd5b506033546102c89073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156102fe57600080fd5b506032546102c89073ffffffffffffffffffffffffffffffffffffffff1681565b34801561032b57600080fd5b506003546102c89073ffffffffffffffffffffffffffffffffffffffff1681565b34801561035857600080fd5b5061023b610367366004612b08565b61101b565b34801561037857600080fd5b506103b56040518060400160405280600581526020017f322e322e3000000000000000000000000000000000000000000000000000000081525081565b6040516102e99190612bf5565b3480156103ce57600080fd5b5061023b6103dd366004612c08565b611060565b3480156103ee57600080fd5b506103f7611134565b60405190151581526020016102e9565b34801561041357600080fd5b5060045473ffffffffffffffffffffffffffffffffffffffff166102c8565b34801561043e57600080fd5b5061023b61044d366004612b08565b6111cd565b34801561045e57600080fd5b5061023b61046d366004612c08565b611212565b34801561047e57600080fd5b506104aa61048d366004612c8b565b600260209081526000928352604080842090915290825290205481565b6040519081526020016102e9565b3480156104c457600080fd5b5060035473ffffffffffffffffffffffffffffffffffffffff166102c8565b61023b6104f1366004612cc4565b6112e6565b34801561050257600080fd5b5061023b610511366004612991565b611328565b61023b610524366004612a42565b611337565b34801561053557600080fd5b5061023b610544366004612d27565b611408565b34801561055557600080fd5b506004546102c89073ffffffffffffffffffffffffffffffffffffffff1681565b61023b610584366004612cc4565b611607565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6105b2848434858561164a565b50505050565b60035473ffffffffffffffffffffffffffffffffffffffff163314801561068b575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa15801561064f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106739190612d72565b73ffffffffffffffffffffffffffffffffffffffff16145b61073d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a401610214565b610745611134565b156107ac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616e646172644272696467653a20706175736564000000000000000000006044820152606401610214565b6107b5876118a9565b15610903576107c4878761190b565b610876576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a401610214565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590528816906340c10f1990604401600060405180830381600087803b1580156108e657600080fd5b505af11580156108fa573d6000803e3d6000fd5b50505050610985565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054610941908490612dbe565b73ffffffffffffffffffffffffffffffffffffffff8089166000818152600260209081526040808320948c1683529390529190912091909155610985908585611a2b565b6109c9878787878787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611aff92505050565b50505050505050565b333b15610a61576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610214565b610aa43333348686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061164a92505050565b505050565b610ab68585858585610abd565b5050505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610b90575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa158015610b54573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b789190612d72565b73ffffffffffffffffffffffffffffffffffffffff16145b610c42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a401610214565b610c4a611134565b15610cb1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616e646172644272696467653a20706175736564000000000000000000006044820152606401610214565b610cb9611b8d565b15610d46576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e0000000000000000006064820152608401610214565b823414610dd5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5374616e646172644272696467653a20616d6f756e742073656e7420646f657360448201527f206e6f74206d6174636820616d6f756e742072657175697265640000000000006064820152608401610214565b3073ffffffffffffffffffffffffffffffffffffffff851603610e7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f207360448201527f656c6600000000000000000000000000000000000000000000000000000000006064820152608401610214565b60035473ffffffffffffffffffffffffffffffffffffffff90811690851603610f25576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f206d60448201527f657373656e6765720000000000000000000000000000000000000000000000006064820152608401610214565b610f6785858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611bcc92505050565b6000610f84855a8660405180602001604052806000815250611c3f565b905080611013576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a20455448207472616e736665722066616960448201527f6c656400000000000000000000000000000000000000000000000000000000006064820152608401610214565b505050505050565b6109c987873388888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611c5792505050565b333b156110ef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610214565b61101386863333888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061201092505050565b603254604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa1580156111a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111c89190612dd5565b905090565b6109c987873388888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061201092505050565b333b156112a1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610214565b61101386863333888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611c5792505050565b6105b233858585858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506105a592505050565b6109c9878787878787876105b8565b333b156113c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610214565b610aa433338585858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506105a592505050565b600054610100900460ff16158080156114285750600054600160ff909116105b806114425750303b158015611442575060005460ff166001145b6114ce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610214565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561152c57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6032805473ffffffffffffffffffffffffffffffffffffffff8086167fffffffffffffffffffffffff000000000000000000000000000000000000000092831617909255603380549285169290911691909117905561159f8473420000000000000000000000000000000000001061201f565b80156105b257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150505050565b6105b23385348686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061164a92505050565b611652611b8d565b156116df576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e0000000000000000006064820152608401610214565b82341461176e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5374616e646172644272696467653a206272696467696e6720455448206d757360448201527f7420696e636c7564652073756666696369656e74204554482076616c756500006064820152608401610214565b61177a85858584612109565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9287929116907f1635f5fd00000000000000000000000000000000000000000000000000000000906117dd908b908b9086908a90602401612df7565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b909216825261187092918890600401612e40565b6000604051808303818588803b15801561188957600080fd5b505af115801561189d573d6000803e3d6000fd5b50505050505050505050565b60006118d5827f1d1d8b630000000000000000000000000000000000000000000000000000000061217c565b806119055750611905827fec4fc8e30000000000000000000000000000000000000000000000000000000061217c565b92915050565b6000611937837f1d1d8b630000000000000000000000000000000000000000000000000000000061217c565b156119e0578273ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015611987573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ab9190612d72565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050611905565b8273ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611987573d6000803e3d6000fd5b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052610aa49084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915261219f565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f3ceee06c1e37648fcbb6ed52e17b3e1f275a1f8c7b22a84b2b84732431e046b3868686604051611b7793929190612e85565b60405180910390a46110138686868686866122ab565b600080611b98612333565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2ac69ee804d9a7a0984249f508dfab7cb2534b465b6ce1580f99a38ba9c5e6318484604051611c2b929190612ec3565b60405180910390a36105b2848484846123d0565b6000806000835160208501868989f195945050505050565b3415611ce5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5374616e646172644272696467653a2063616e6e6f742073656e642076616c7560448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610214565b611cee876118a9565b15611e3c57611cfd878761190b565b611daf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a401610214565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015260248201859052881690639dc29fac90604401600060405180830381600087803b158015611e1f57600080fd5b505af1158015611e33573d6000803e3d6000fd5b50505050611ed0565b611e5e73ffffffffffffffffffffffffffffffffffffffff881686308661243d565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054611e9c908490612edc565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152600260209081526040808320938b16835292905220555b611ede87878787878661249b565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9216907f0166a07a0000000000000000000000000000000000000000000000000000000090611f42908b908d908c908c908c908b90602401612ef4565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e085901b9092168252611fd592918790600401612e40565b600060405180830381600087803b158015611fef57600080fd5b505af1158015612003573d6000803e3d6000fd5b5050505050505050505050565b6109c987878787878787611c57565b600054610100900460ff166120b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610214565b6003805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560048054929093169116179055565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f35d79ab81f2b2017e19afb5c5571778877782d7a8786f5907f93b0f4702f4f238484604051612168929190612ec3565b60405180910390a36105b284848484612529565b600061218783612588565b8015612198575061219883836125ec565b9392505050565b6000612201826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166126bb9092919063ffffffff16565b805190915015610aa4578080602001905181019061221f9190612dd5565b610aa4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610214565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fd59c65b35445225835c83f50b6ede06a7be047d22e357073e250d9af537518cd86868660405161232393929190612e85565b60405180910390a4505050505050565b603354604080517f4397dfef0000000000000000000000000000000000000000000000000000000081528151600093849373ffffffffffffffffffffffffffffffffffffffff90911692634397dfef92600480830193928290030181865afa1580156123a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123c79190612f4f565b90939092509050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f31b2166ff604fc5672ea5df08a78081d2bc6d746cadce880747f3643d819e83d848460405161242f929190612ec3565b60405180910390a350505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526105b29085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611a7d565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f718594027abd4eaed59f95162563e0cc6d0e8d5b86b1c7be8b1b0ac3343d039686868660405161251393929190612e85565b60405180910390a46110138686868686866126d2565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2849b43074093a05396b6f2a937dee8565b15a48a7b3d4bffb732a5017380af5848460405161242f929190612ec3565b60006125b4827f01ffc9a7000000000000000000000000000000000000000000000000000000006125ec565b801561190557506125e5827fffffffff000000000000000000000000000000000000000000000000000000006125ec565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d915060005190508280156126a4575060208210155b80156126b05750600081115b979650505050505050565b60606126ca848460008561274a565b949350505050565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f7ff126db8024424bbfd9826e8ab82ff59136289ea440b04b39a0df1b03b9cabf86868660405161232393929190612e85565b6060824710156127dc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610214565b73ffffffffffffffffffffffffffffffffffffffff85163b61285a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610214565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516128839190612f84565b60006040518083038185875af1925050503d80600081146128c0576040519150601f19603f3d011682016040523d82523d6000602084013e6128c5565b606091505b50915091506126b0828286606083156128df575081612198565b8251156128ef5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102149190612bf5565b73ffffffffffffffffffffffffffffffffffffffff8116811461294557600080fd5b50565b60008083601f84011261295a57600080fd5b50813567ffffffffffffffff81111561297257600080fd5b60208301915083602082850101111561298a57600080fd5b9250929050565b600080600080600080600060c0888a0312156129ac57600080fd5b87356129b781612923565b965060208801356129c781612923565b955060408801356129d781612923565b945060608801356129e781612923565b93506080880135925060a088013567ffffffffffffffff811115612a0a57600080fd5b612a168a828b01612948565b989b979a50959850939692959293505050565b803563ffffffff81168114612a3d57600080fd5b919050565b600080600060408486031215612a5757600080fd5b612a6084612a29565b9250602084013567ffffffffffffffff811115612a7c57600080fd5b612a8886828701612948565b9497909650939450505050565b600080600080600060808688031215612aad57600080fd5b8535612ab881612923565b94506020860135612ac881612923565b935060408601359250606086013567ffffffffffffffff811115612aeb57600080fd5b612af788828901612948565b969995985093965092949392505050565b600080600080600080600060c0888a031215612b2357600080fd5b8735612b2e81612923565b96506020880135612b3e81612923565b95506040880135612b4e81612923565b945060608801359350612b6360808901612a29565b925060a088013567ffffffffffffffff811115612a0a57600080fd5b60005b83811015612b9a578181015183820152602001612b82565b838111156105b25750506000910152565b60008151808452612bc3816020860160208601612b7f565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006121986020830184612bab565b60008060008060008060a08789031215612c2157600080fd5b8635612c2c81612923565b95506020870135612c3c81612923565b945060408701359350612c5160608801612a29565b9250608087013567ffffffffffffffff811115612c6d57600080fd5b612c7989828a01612948565b979a9699509497509295939492505050565b60008060408385031215612c9e57600080fd5b8235612ca981612923565b91506020830135612cb981612923565b809150509250929050565b60008060008060608587031215612cda57600080fd5b8435612ce581612923565b9350612cf360208601612a29565b9250604085013567ffffffffffffffff811115612d0f57600080fd5b612d1b87828801612948565b95989497509550505050565b600080600060608486031215612d3c57600080fd5b8335612d4781612923565b92506020840135612d5781612923565b91506040840135612d6781612923565b809150509250925092565b600060208284031215612d8457600080fd5b815161219881612923565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015612dd057612dd0612d8f565b500390565b600060208284031215612de757600080fd5b8151801515811461219857600080fd5b600073ffffffffffffffffffffffffffffffffffffffff808716835280861660208401525083604083015260806060830152612e366080830184612bab565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff84168152606060208201526000612e6f6060830185612bab565b905063ffffffff83166040830152949350505050565b73ffffffffffffffffffffffffffffffffffffffff84168152826020820152606060408201526000612eba6060830184612bab565b95945050505050565b8281526040602082015260006126ca6040830184612bab565b60008219821115612eef57612eef612d8f565b500190565b600073ffffffffffffffffffffffffffffffffffffffff80891683528088166020840152808716604084015280861660608401525083608083015260c060a0830152612f4360c0830184612bab565b98975050505050505050565b60008060408385031215612f6257600080fd5b8251612f6d81612923565b602084015190925060ff81168114612cb957600080fd5b60008251612f96818460208701612b7f565b919091019291505056fea164736f6c634300080f000a"; +- hex"6080604052600436106101845760003560e01c80637f46ddb2116100d65780639a2ac6d51161007f578063c0c53b8b11610059578063c0c53b8b14610529578063c89701a214610549578063e11013dd1461057657600080fd5b80639a2ac6d5146104e3578063a9f9e675146104f6578063b1a1a8821461051657600080fd5b80638f601f66116100b05780638f601f661461047257806391c49bf814610407578063927ede2d146104b857600080fd5b80637f46ddb214610407578063838b252014610432578063870876231461045257600080fd5b806335e80ab31161013857806354fd4d501161011257806354fd4d501461036c57806358a997f6146103c25780635c975abb146103e257600080fd5b806335e80ab3146102f25780633cb747bf1461031f578063540abf731461034c57600080fd5b80631532ec34116101695780631532ec34146102755780631635f5fd1461028857806333d7e2bd1461029b57600080fd5b80630166a07a1461024257806309fc88431461026257600080fd5b3661023d57333b1561021d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084015b60405180910390fd5b61023b333362030d40604051806020016040528060008152506105a5565b005b600080fd5b34801561024e57600080fd5b5061023b61025d366004612991565b6105b8565b61023b610270366004612a42565b6109d2565b61023b610283366004612a95565b610aa9565b61023b610296366004612a95565b610abd565b3480156102a757600080fd5b506033546102c89073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156102fe57600080fd5b506032546102c89073ffffffffffffffffffffffffffffffffffffffff1681565b34801561032b57600080fd5b506003546102c89073ffffffffffffffffffffffffffffffffffffffff1681565b34801561035857600080fd5b5061023b610367366004612b08565b61101b565b34801561037857600080fd5b506103b56040518060400160405280600581526020017f322e322e3000000000000000000000000000000000000000000000000000000081525081565b6040516102e99190612bf5565b3480156103ce57600080fd5b5061023b6103dd366004612c08565b611060565b3480156103ee57600080fd5b506103f7611134565b60405190151581526020016102e9565b34801561041357600080fd5b5060045473ffffffffffffffffffffffffffffffffffffffff166102c8565b34801561043e57600080fd5b5061023b61044d366004612b08565b6111cd565b34801561045e57600080fd5b5061023b61046d366004612c08565b611212565b34801561047e57600080fd5b506104aa61048d366004612c8b565b600260209081526000928352604080842090915290825290205481565b6040519081526020016102e9565b3480156104c457600080fd5b5060035473ffffffffffffffffffffffffffffffffffffffff166102c8565b61023b6104f1366004612cc4565b6112e6565b34801561050257600080fd5b5061023b610511366004612991565b611328565b61023b610524366004612a42565b611337565b34801561053557600080fd5b5061023b610544366004612d27565b611408565b34801561055557600080fd5b506004546102c89073ffffffffffffffffffffffffffffffffffffffff1681565b61023b610584366004612cc4565b611607565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6105b2848434858561164a565b50505050565b60035473ffffffffffffffffffffffffffffffffffffffff163314801561068b575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa15801561064f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106739190612d72565b73ffffffffffffffffffffffffffffffffffffffff16145b61073d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a401610214565b610745611134565b156107ac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616e646172644272696467653a20706175736564000000000000000000006044820152606401610214565b6107b5876118a9565b15610903576107c4878761190b565b610876576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a401610214565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590528816906340c10f1990604401600060405180830381600087803b1580156108e657600080fd5b505af11580156108fa573d6000803e3d6000fd5b50505050610985565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054610941908490612dbe565b73ffffffffffffffffffffffffffffffffffffffff8089166000818152600260209081526040808320948c1683529390529190912091909155610985908585611a2b565b6109c9878787878787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611aff92505050565b50505050505050565b333b15610a61576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610214565b610aa43333348686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061164a92505050565b505050565b610ab68585858585610abd565b5050505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610b90575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa158015610b54573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b789190612d72565b73ffffffffffffffffffffffffffffffffffffffff16145b610c42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a401610214565b610c4a611134565b15610cb1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616e646172644272696467653a20706175736564000000000000000000006044820152606401610214565b610cb9611b8d565b15610d46576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e0000000000000000006064820152608401610214565b823414610dd5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5374616e646172644272696467653a20616d6f756e742073656e7420646f657360448201527f206e6f74206d6174636820616d6f756e742072657175697265640000000000006064820152608401610214565b3073ffffffffffffffffffffffffffffffffffffffff851603610e7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f207360448201527f656c6600000000000000000000000000000000000000000000000000000000006064820152608401610214565b60035473ffffffffffffffffffffffffffffffffffffffff90811690851603610f25576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f206d60448201527f657373656e6765720000000000000000000000000000000000000000000000006064820152608401610214565b610f6785858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611bcc92505050565b6000610f84855a8660405180602001604052806000815250611c3f565b905080611013576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a20455448207472616e736665722066616960448201527f6c656400000000000000000000000000000000000000000000000000000000006064820152608401610214565b505050505050565b6109c987873388888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611c5792505050565b333b156110ef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610214565b61101386863333888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061201092505050565b603254604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa1580156111a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111c89190612dd5565b905090565b6109c987873388888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061201092505050565b333b156112a1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610214565b61101386863333888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611c5792505050565b6105b233858585858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506105a592505050565b6109c9878787878787876105b8565b333b156113c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610214565b610aa433338585858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506105a592505050565b600054610100900460ff16158080156114285750600054600160ff909116105b806114425750303b158015611442575060005460ff166001145b6114ce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610214565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561152c57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6032805473ffffffffffffffffffffffffffffffffffffffff8086167fffffffffffffffffffffffff000000000000000000000000000000000000000092831617909255603380549285169290911691909117905561159f8473420000000000000000000000000000000000001061201f565b80156105b257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150505050565b6105b23385348686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061164a92505050565b611652611b8d565b156116df576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e0000000000000000006064820152608401610214565b82341461176e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5374616e646172644272696467653a206272696467696e6720455448206d757360448201527f7420696e636c7564652073756666696369656e74204554482076616c756500006064820152608401610214565b61177a85858584612109565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9287929116907f1635f5fd00000000000000000000000000000000000000000000000000000000906117dd908b908b9086908a90602401612df7565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b909216825261187092918890600401612e40565b6000604051808303818588803b15801561188957600080fd5b505af115801561189d573d6000803e3d6000fd5b50505050505050505050565b60006118d5827f1d1d8b630000000000000000000000000000000000000000000000000000000061217c565b806119055750611905827fec4fc8e30000000000000000000000000000000000000000000000000000000061217c565b92915050565b6000611937837f1d1d8b630000000000000000000000000000000000000000000000000000000061217c565b156119e0578273ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015611987573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ab9190612d72565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050611905565b8273ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611987573d6000803e3d6000fd5b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052610aa49084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915261219f565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f3ceee06c1e37648fcbb6ed52e17b3e1f275a1f8c7b22a84b2b84732431e046b3868686604051611b7793929190612e85565b60405180910390a46110138686868686866122ab565b600080611b98612333565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2ac69ee804d9a7a0984249f508dfab7cb2534b465b6ce1580f99a38ba9c5e6318484604051611c2b929190612ec3565b60405180910390a36105b2848484846123d0565b6000806000835160208501868989f195945050505050565b3415611ce5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5374616e646172644272696467653a2063616e6e6f742073656e642076616c7560448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610214565b611cee876118a9565b15611e3c57611cfd878761190b565b611daf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a401610214565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015260248201859052881690639dc29fac90604401600060405180830381600087803b158015611e1f57600080fd5b505af1158015611e33573d6000803e3d6000fd5b50505050611ed0565b611e5e73ffffffffffffffffffffffffffffffffffffffff881686308661243d565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054611e9c908490612edc565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152600260209081526040808320938b16835292905220555b611ede87878787878661249b565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9216907f0166a07a0000000000000000000000000000000000000000000000000000000090611f42908b908d908c908c908c908b90602401612ef4565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e085901b9092168252611fd592918790600401612e40565b600060405180830381600087803b158015611fef57600080fd5b505af1158015612003573d6000803e3d6000fd5b5050505050505050505050565b6109c987878787878787611c57565b600054610100900460ff166120b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610214565b6003805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560048054929093169116179055565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f35d79ab81f2b2017e19afb5c5571778877782d7a8786f5907f93b0f4702f4f238484604051612168929190612ec3565b60405180910390a36105b284848484612529565b600061218783612588565b8015612198575061219883836125ec565b9392505050565b6000612201826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166126bb9092919063ffffffff16565b805190915015610aa4578080602001905181019061221f9190612dd5565b610aa4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610214565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fd59c65b35445225835c83f50b6ede06a7be047d22e357073e250d9af537518cd86868660405161232393929190612e85565b60405180910390a4505050505050565b603354604080517f4397dfef0000000000000000000000000000000000000000000000000000000081528151600093849373ffffffffffffffffffffffffffffffffffffffff90911692634397dfef92600480830193928290030181865afa1580156123a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123c79190612f4f565b90939092509050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f31b2166ff604fc5672ea5df08a78081d2bc6d746cadce880747f3643d819e83d848460405161242f929190612ec3565b60405180910390a350505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526105b29085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611a7d565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f718594027abd4eaed59f95162563e0cc6d0e8d5b86b1c7be8b1b0ac3343d039686868660405161251393929190612e85565b60405180910390a46110138686868686866126d2565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2849b43074093a05396b6f2a937dee8565b15a48a7b3d4bffb732a5017380af5848460405161242f929190612ec3565b60006125b4827f01ffc9a7000000000000000000000000000000000000000000000000000000006125ec565b801561190557506125e5827fffffffff000000000000000000000000000000000000000000000000000000006125ec565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d915060005190508280156126a4575060208210155b80156126b05750600081115b979650505050505050565b60606126ca848460008561274a565b949350505050565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f7ff126db8024424bbfd9826e8ab82ff59136289ea440b04b39a0df1b03b9cabf86868660405161232393929190612e85565b6060824710156127dc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610214565b73ffffffffffffffffffffffffffffffffffffffff85163b61285a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610214565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516128839190612f84565b60006040518083038185875af1925050503d80600081146128c0576040519150601f19603f3d011682016040523d82523d6000602084013e6128c5565b606091505b50915091506126b0828286606083156128df575081612198565b8251156128ef5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102149190612bf5565b73ffffffffffffffffffffffffffffffffffffffff8116811461294557600080fd5b50565b60008083601f84011261295a57600080fd5b50813567ffffffffffffffff81111561297257600080fd5b60208301915083602082850101111561298a57600080fd5b9250929050565b600080600080600080600060c0888a0312156129ac57600080fd5b87356129b781612923565b965060208801356129c781612923565b955060408801356129d781612923565b945060608801356129e781612923565b93506080880135925060a088013567ffffffffffffffff811115612a0a57600080fd5b612a168a828b01612948565b989b979a50959850939692959293505050565b803563ffffffff81168114612a3d57600080fd5b919050565b600080600060408486031215612a5757600080fd5b612a6084612a29565b9250602084013567ffffffffffffffff811115612a7c57600080fd5b612a8886828701612948565b9497909650939450505050565b600080600080600060808688031215612aad57600080fd5b8535612ab881612923565b94506020860135612ac881612923565b935060408601359250606086013567ffffffffffffffff811115612aeb57600080fd5b612af788828901612948565b969995985093965092949392505050565b600080600080600080600060c0888a031215612b2357600080fd5b8735612b2e81612923565b96506020880135612b3e81612923565b95506040880135612b4e81612923565b945060608801359350612b6360808901612a29565b925060a088013567ffffffffffffffff811115612a0a57600080fd5b60005b83811015612b9a578181015183820152602001612b82565b838111156105b25750506000910152565b60008151808452612bc3816020860160208601612b7f565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006121986020830184612bab565b60008060008060008060a08789031215612c2157600080fd5b8635612c2c81612923565b95506020870135612c3c81612923565b945060408701359350612c5160608801612a29565b9250608087013567ffffffffffffffff811115612c6d57600080fd5b612c7989828a01612948565b979a9699509497509295939492505050565b60008060408385031215612c9e57600080fd5b8235612ca981612923565b91506020830135612cb981612923565b809150509250929050565b60008060008060608587031215612cda57600080fd5b8435612ce581612923565b9350612cf360208601612a29565b9250604085013567ffffffffffffffff811115612d0f57600080fd5b612d1b87828801612948565b95989497509550505050565b600080600060608486031215612d3c57600080fd5b8335612d4781612923565b92506020840135612d5781612923565b91506040840135612d6781612923565b809150509250925092565b600060208284031215612d8457600080fd5b815161219881612923565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015612dd057612dd0612d8f565b500390565b600060208284031215612de757600080fd5b8151801515811461219857600080fd5b600073ffffffffffffffffffffffffffffffffffffffff808716835280861660208401525083604083015260806060830152612e366080830184612bab565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff84168152606060208201526000612e6f6060830185612bab565b905063ffffffff83166040830152949350505050565b73ffffffffffffffffffffffffffffffffffffffff84168152826020820152606060408201526000612eba6060830184612bab565b95945050505050565b8281526040602082015260006126ca6040830184612bab565b60008219821115612eef57612eef612d8f565b500190565b600073ffffffffffffffffffffffffffffffffffffffff80891683528088166020840152808716604084015280861660608401525083608083015260c060a0830152612f4360c0830184612bab565b98975050505050505050565b60008060408385031215612f6257600080fd5b8251612f6d81612923565b602084015190925060ff81168114612cb957600080fd5b60008251612f96818460208701612b7f565b919091019291505056fea164736f6c634300080f000a"; ++ hex"6080604052600436106101845760003560e01c80637f46ddb2116100d65780639a2ac6d51161007f578063c0c53b8b11610059578063c0c53b8b14610529578063c89701a214610549578063e11013dd1461057657600080fd5b80639a2ac6d5146104e3578063a9f9e675146104f6578063b1a1a8821461051657600080fd5b80638f601f66116100b05780638f601f661461047257806391c49bf814610407578063927ede2d146104b857600080fd5b80637f46ddb214610407578063838b252014610432578063870876231461045257600080fd5b806335e80ab31161013857806354fd4d501161011257806354fd4d501461036c57806358a997f6146103c25780635c975abb146103e257600080fd5b806335e80ab3146102f25780633cb747bf1461031f578063540abf731461034c57600080fd5b80631532ec34116101695780631532ec34146102755780631635f5fd1461028857806333d7e2bd1461029b57600080fd5b80630166a07a1461024257806309fc88431461026257600080fd5b3661023d57333b1561021d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084015b60405180910390fd5b61023b333362030d40604051806020016040528060008152506105a5565b005b600080fd5b34801561024e57600080fd5b5061023b61025d366004612991565b6105b8565b61023b610270366004612a42565b6109d2565b61023b610283366004612a95565b610aa9565b61023b610296366004612a95565b610abd565b3480156102a757600080fd5b506033546102c89073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156102fe57600080fd5b506032546102c89073ffffffffffffffffffffffffffffffffffffffff1681565b34801561032b57600080fd5b506003546102c89073ffffffffffffffffffffffffffffffffffffffff1681565b34801561035857600080fd5b5061023b610367366004612b08565b61101b565b34801561037857600080fd5b506103b56040518060400160405280600c81526020017f322e322e312d626574612e31000000000000000000000000000000000000000081525081565b6040516102e99190612bf5565b3480156103ce57600080fd5b5061023b6103dd366004612c08565b611060565b3480156103ee57600080fd5b506103f7611134565b60405190151581526020016102e9565b34801561041357600080fd5b5060045473ffffffffffffffffffffffffffffffffffffffff166102c8565b34801561043e57600080fd5b5061023b61044d366004612b08565b6111cd565b34801561045e57600080fd5b5061023b61046d366004612c08565b611212565b34801561047e57600080fd5b506104aa61048d366004612c8b565b600260209081526000928352604080842090915290825290205481565b6040519081526020016102e9565b3480156104c457600080fd5b5060035473ffffffffffffffffffffffffffffffffffffffff166102c8565b61023b6104f1366004612cc4565b6112e6565b34801561050257600080fd5b5061023b610511366004612991565b611328565b61023b610524366004612a42565b611337565b34801561053557600080fd5b5061023b610544366004612d27565b611408565b34801561055557600080fd5b506004546102c89073ffffffffffffffffffffffffffffffffffffffff1681565b61023b610584366004612cc4565b611607565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6105b2848434858561164a565b50505050565b60035473ffffffffffffffffffffffffffffffffffffffff163314801561068b575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa15801561064f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106739190612d72565b73ffffffffffffffffffffffffffffffffffffffff16145b61073d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a401610214565b610745611134565b156107ac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616e646172644272696467653a20706175736564000000000000000000006044820152606401610214565b6107b5876118a9565b15610903576107c4878761190b565b610876576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a401610214565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590528816906340c10f1990604401600060405180830381600087803b1580156108e657600080fd5b505af11580156108fa573d6000803e3d6000fd5b50505050610985565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054610941908490612dbe565b73ffffffffffffffffffffffffffffffffffffffff8089166000818152600260209081526040808320948c1683529390529190912091909155610985908585611a2b565b6109c9878787878787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611aff92505050565b50505050505050565b333b15610a61576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610214565b610aa43333348686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061164a92505050565b505050565b610ab68585858585610abd565b5050505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610b90575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa158015610b54573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b789190612d72565b73ffffffffffffffffffffffffffffffffffffffff16145b610c42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a401610214565b610c4a611134565b15610cb1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616e646172644272696467653a20706175736564000000000000000000006044820152606401610214565b610cb9611b8d565b15610d46576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e0000000000000000006064820152608401610214565b823414610dd5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5374616e646172644272696467653a20616d6f756e742073656e7420646f657360448201527f206e6f74206d6174636820616d6f756e742072657175697265640000000000006064820152608401610214565b3073ffffffffffffffffffffffffffffffffffffffff851603610e7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f207360448201527f656c6600000000000000000000000000000000000000000000000000000000006064820152608401610214565b60035473ffffffffffffffffffffffffffffffffffffffff90811690851603610f25576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f206d60448201527f657373656e6765720000000000000000000000000000000000000000000000006064820152608401610214565b610f6785858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611bcc92505050565b6000610f84855a8660405180602001604052806000815250611c3f565b905080611013576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a20455448207472616e736665722066616960448201527f6c656400000000000000000000000000000000000000000000000000000000006064820152608401610214565b505050505050565b6109c987873388888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611c5792505050565b333b156110ef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610214565b61101386863333888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061201092505050565b603254604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa1580156111a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111c89190612dd5565b905090565b6109c987873388888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061201092505050565b333b156112a1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610214565b61101386863333888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611c5792505050565b6105b233858585858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506105a592505050565b6109c9878787878787876105b8565b333b156113c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610214565b610aa433338585858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506105a592505050565b600054610100900460ff16158080156114285750600054600160ff909116105b806114425750303b158015611442575060005460ff166001145b6114ce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610214565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561152c57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6032805473ffffffffffffffffffffffffffffffffffffffff8086167fffffffffffffffffffffffff000000000000000000000000000000000000000092831617909255603380549285169290911691909117905561159f8473420000000000000000000000000000000000001061201f565b80156105b257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150505050565b6105b23385348686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061164a92505050565b611652611b8d565b156116df576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e0000000000000000006064820152608401610214565b82341461176e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5374616e646172644272696467653a206272696467696e6720455448206d757360448201527f7420696e636c7564652073756666696369656e74204554482076616c756500006064820152608401610214565b61177a85858584612109565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9287929116907f1635f5fd00000000000000000000000000000000000000000000000000000000906117dd908b908b9086908a90602401612df7565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b909216825261187092918890600401612e40565b6000604051808303818588803b15801561188957600080fd5b505af115801561189d573d6000803e3d6000fd5b50505050505050505050565b60006118d5827f1d1d8b630000000000000000000000000000000000000000000000000000000061217c565b806119055750611905827fec4fc8e30000000000000000000000000000000000000000000000000000000061217c565b92915050565b6000611937837f1d1d8b630000000000000000000000000000000000000000000000000000000061217c565b156119e0578273ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015611987573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ab9190612d72565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050611905565b8273ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611987573d6000803e3d6000fd5b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052610aa49084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915261219f565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f3ceee06c1e37648fcbb6ed52e17b3e1f275a1f8c7b22a84b2b84732431e046b3868686604051611b7793929190612e85565b60405180910390a46110138686868686866122ab565b600080611b98612333565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2ac69ee804d9a7a0984249f508dfab7cb2534b465b6ce1580f99a38ba9c5e6318484604051611c2b929190612ec3565b60405180910390a36105b2848484846123d0565b6000806000835160208501868989f195945050505050565b3415611ce5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5374616e646172644272696467653a2063616e6e6f742073656e642076616c7560448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610214565b611cee876118a9565b15611e3c57611cfd878761190b565b611daf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a401610214565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015260248201859052881690639dc29fac90604401600060405180830381600087803b158015611e1f57600080fd5b505af1158015611e33573d6000803e3d6000fd5b50505050611ed0565b611e5e73ffffffffffffffffffffffffffffffffffffffff881686308661243d565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054611e9c908490612edc565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152600260209081526040808320938b16835292905220555b611ede87878787878661249b565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9216907f0166a07a0000000000000000000000000000000000000000000000000000000090611f42908b908d908c908c908c908b90602401612ef4565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e085901b9092168252611fd592918790600401612e40565b600060405180830381600087803b158015611fef57600080fd5b505af1158015612003573d6000803e3d6000fd5b5050505050505050505050565b6109c987878787878787611c57565b600054610100900460ff166120b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610214565b6003805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560048054929093169116179055565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f35d79ab81f2b2017e19afb5c5571778877782d7a8786f5907f93b0f4702f4f238484604051612168929190612ec3565b60405180910390a36105b284848484612529565b600061218783612588565b8015612198575061219883836125ec565b9392505050565b6000612201826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166126bb9092919063ffffffff16565b805190915015610aa4578080602001905181019061221f9190612dd5565b610aa4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610214565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fd59c65b35445225835c83f50b6ede06a7be047d22e357073e250d9af537518cd86868660405161232393929190612e85565b60405180910390a4505050505050565b603354604080517f4397dfef0000000000000000000000000000000000000000000000000000000081528151600093849373ffffffffffffffffffffffffffffffffffffffff90911692634397dfef92600480830193928290030181865afa1580156123a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123c79190612f4f565b90939092509050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f31b2166ff604fc5672ea5df08a78081d2bc6d746cadce880747f3643d819e83d848460405161242f929190612ec3565b60405180910390a350505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526105b29085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611a7d565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f718594027abd4eaed59f95162563e0cc6d0e8d5b86b1c7be8b1b0ac3343d039686868660405161251393929190612e85565b60405180910390a46110138686868686866126d2565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2849b43074093a05396b6f2a937dee8565b15a48a7b3d4bffb732a5017380af5848460405161242f929190612ec3565b60006125b4827f01ffc9a7000000000000000000000000000000000000000000000000000000006125ec565b801561190557506125e5827fffffffff000000000000000000000000000000000000000000000000000000006125ec565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d915060005190508280156126a4575060208210155b80156126b05750600081115b979650505050505050565b60606126ca848460008561274a565b949350505050565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f7ff126db8024424bbfd9826e8ab82ff59136289ea440b04b39a0df1b03b9cabf86868660405161232393929190612e85565b6060824710156127dc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610214565b73ffffffffffffffffffffffffffffffffffffffff85163b61285a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610214565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516128839190612f84565b60006040518083038185875af1925050503d80600081146128c0576040519150601f19603f3d011682016040523d82523d6000602084013e6128c5565b606091505b50915091506126b0828286606083156128df575081612198565b8251156128ef5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102149190612bf5565b73ffffffffffffffffffffffffffffffffffffffff8116811461294557600080fd5b50565b60008083601f84011261295a57600080fd5b50813567ffffffffffffffff81111561297257600080fd5b60208301915083602082850101111561298a57600080fd5b9250929050565b600080600080600080600060c0888a0312156129ac57600080fd5b87356129b781612923565b965060208801356129c781612923565b955060408801356129d781612923565b945060608801356129e781612923565b93506080880135925060a088013567ffffffffffffffff811115612a0a57600080fd5b612a168a828b01612948565b989b979a50959850939692959293505050565b803563ffffffff81168114612a3d57600080fd5b919050565b600080600060408486031215612a5757600080fd5b612a6084612a29565b9250602084013567ffffffffffffffff811115612a7c57600080fd5b612a8886828701612948565b9497909650939450505050565b600080600080600060808688031215612aad57600080fd5b8535612ab881612923565b94506020860135612ac881612923565b935060408601359250606086013567ffffffffffffffff811115612aeb57600080fd5b612af788828901612948565b969995985093965092949392505050565b600080600080600080600060c0888a031215612b2357600080fd5b8735612b2e81612923565b96506020880135612b3e81612923565b95506040880135612b4e81612923565b945060608801359350612b6360808901612a29565b925060a088013567ffffffffffffffff811115612a0a57600080fd5b60005b83811015612b9a578181015183820152602001612b82565b838111156105b25750506000910152565b60008151808452612bc3816020860160208601612b7f565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006121986020830184612bab565b60008060008060008060a08789031215612c2157600080fd5b8635612c2c81612923565b95506020870135612c3c81612923565b945060408701359350612c5160608801612a29565b9250608087013567ffffffffffffffff811115612c6d57600080fd5b612c7989828a01612948565b979a9699509497509295939492505050565b60008060408385031215612c9e57600080fd5b8235612ca981612923565b91506020830135612cb981612923565b809150509250929050565b60008060008060608587031215612cda57600080fd5b8435612ce581612923565b9350612cf360208601612a29565b9250604085013567ffffffffffffffff811115612d0f57600080fd5b612d1b87828801612948565b95989497509550505050565b600080600060608486031215612d3c57600080fd5b8335612d4781612923565b92506020840135612d5781612923565b91506040840135612d6781612923565b809150509250925092565b600060208284031215612d8457600080fd5b815161219881612923565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015612dd057612dd0612d8f565b500390565b600060208284031215612de757600080fd5b8151801515811461219857600080fd5b600073ffffffffffffffffffffffffffffffffffffffff808716835280861660208401525083604083015260806060830152612e366080830184612bab565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff84168152606060208201526000612e6f6060830185612bab565b905063ffffffff83166040830152949350505050565b73ffffffffffffffffffffffffffffffffffffffff84168152826020820152606060408201526000612eba6060830184612bab565b95945050505050565b8281526040602082015260006126ca6040830184612bab565b60008219821115612eef57612eef612d8f565b500190565b600073ffffffffffffffffffffffffffffffffffffffff80891683528088166020840152808716604084015280861660608401525083608083015260c060a0830152612f4360c0830184612bab565b98975050505050505050565b60008060408385031215612f6257600080fd5b8251612f6d81612923565b602084015190925060ff81168114612cb957600080fd5b60008251612f96818460208701612b7f565b919091019291505056fea164736f6c634300080f000a"; bytes internal constant l1ERC721BridgeCode = - hex"608060405234801561001057600080fd5b50600436106100d45760003560e01c80635d93a3fc11610081578063927ede2d1161005b578063927ede2d14610231578063aa5574521461024f578063c89701a21461026257600080fd5b80635d93a3fc146101cc578063761f4493146102005780637f46ddb21461021357600080fd5b8063485cc955116100b2578063485cc9551461015857806354fd4d501461016b5780635c975abb146101b457600080fd5b806335e80ab3146100d95780633687011a146101235780633cb747bf14610138575b600080fd5b6032546100f99073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b610136610131366004610fe1565b610282565b005b6001546100f99073ffffffffffffffffffffffffffffffffffffffff1681565b610136610166366004611064565b61032e565b6101a76040518060400160405280600c81526020017f322e312e312b626574612e31000000000000000000000000000000000000000081525081565b60405161011a9190611108565b6101bc610518565b604051901515815260200161011a565b6101bc6101da366004611122565b603160209081526000938452604080852082529284528284209052825290205460ff1681565b61013661020e366004611163565b6105b1565b60025473ffffffffffffffffffffffffffffffffffffffff166100f9565b60015473ffffffffffffffffffffffffffffffffffffffff166100f9565b61013661025d3660046111fb565b610a58565b6002546100f99073ffffffffffffffffffffffffffffffffffffffff1681565b333b15610316576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4552433732314272696467653a206163636f756e74206973206e6f742065787460448201527f65726e616c6c79206f776e65640000000000000000000000000000000000000060648201526084015b60405180910390fd5b6103268686333388888888610b30565b505050505050565b600054610100900460ff161580801561034e5750600054600160ff909116105b806103685750303b158015610368575060005460ff166001145b6103f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161030d565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561045257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84161790556104b083734200000000000000000000000000000000000014610e70565b801561051357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b603254604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa158015610588573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ac9190611272565b905090565b60015473ffffffffffffffffffffffffffffffffffffffff16331480156106865750600254600154604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9384169390921691636e296e45916004808201926020929091908290030181865afa15801561064a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061066e9190611294565b73ffffffffffffffffffffffffffffffffffffffff16145b610712576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4552433732314272696467653a2066756e6374696f6e2063616e206f6e6c792060448201527f62652063616c6c65642066726f6d20746865206f746865722062726964676500606482015260840161030d565b61071a610518565b15610781576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4c314552433732314272696467653a2070617573656400000000000000000000604482015260640161030d565b3073ffffffffffffffffffffffffffffffffffffffff881603610826576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4c314552433732314272696467653a206c6f63616c20746f6b656e2063616e6e60448201527f6f742062652073656c6600000000000000000000000000000000000000000000606482015260840161030d565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152603160209081526040808320938a1683529281528282208683529052205460ff1615156001146108f5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4c314552433732314272696467653a20546f6b656e204944206973206e6f742060448201527f657363726f77656420696e20746865204c312042726964676500000000000000606482015260840161030d565b73ffffffffffffffffffffffffffffffffffffffff87811660008181526031602090815260408083208b8616845282528083208884529091529081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517f42842e0e000000000000000000000000000000000000000000000000000000008152306004820152918616602483015260448201859052906342842e0e90606401600060405180830381600087803b1580156109b557600080fd5b505af11580156109c9573d6000803e3d6000fd5b505050508473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff167f1f39bf6707b5d608453e0ae4c067b562bcc4c85c0f562ef5d2c774d2e7f131ac87878787604051610a4794939291906112fa565b60405180910390a450505050505050565b73ffffffffffffffffffffffffffffffffffffffff8516610afb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4552433732314272696467653a206e667420726563697069656e742063616e6e60448201527f6f74206265206164647265737328302900000000000000000000000000000000606482015260840161030d565b610b0b8787338888888888610b30565b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b73ffffffffffffffffffffffffffffffffffffffff8716610bd3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f4c314552433732314272696467653a2072656d6f746520746f6b656e2063616e60448201527f6e6f742062652061646472657373283029000000000000000000000000000000606482015260840161030d565b600063761f449360e01b888a8989898888604051602401610bfa979695949392919061133a565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000959095169490941790935273ffffffffffffffffffffffffffffffffffffffff8c81166000818152603186528381208e8416825286528381208b82529095529382902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905590517f23b872dd000000000000000000000000000000000000000000000000000000008152908a166004820152306024820152604481018890529092506323b872dd90606401600060405180830381600087803b158015610d3a57600080fd5b505af1158015610d4e573d6000803e3d6000fd5b50506001546002546040517f3dbb202b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9283169450633dbb202b9350610db1929091169085908990600401611397565b600060405180830381600087803b158015610dcb57600080fd5b505af1158015610ddf573d6000803e3d6000fd5b505050508673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff167fb7460e2a880f256ebef3406116ff3eee0cee51ebccdc2a40698f87ebb2e9c1a589898888604051610e5d94939291906112fa565b60405180910390a4505050505050505050565b600054610100900460ff16610f07576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161030d565b6001805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560028054929093169116179055565b73ffffffffffffffffffffffffffffffffffffffff81168114610f7c57600080fd5b50565b803563ffffffff81168114610f9357600080fd5b919050565b60008083601f840112610faa57600080fd5b50813567ffffffffffffffff811115610fc257600080fd5b602083019150836020828501011115610fda57600080fd5b9250929050565b60008060008060008060a08789031215610ffa57600080fd5b863561100581610f5a565b9550602087013561101581610f5a565b94506040870135935061102a60608801610f7f565b9250608087013567ffffffffffffffff81111561104657600080fd5b61105289828a01610f98565b979a9699509497509295939492505050565b6000806040838503121561107757600080fd5b823561108281610f5a565b9150602083013561109281610f5a565b809150509250929050565b6000815180845260005b818110156110c3576020818501810151868301820152016110a7565b818111156110d5576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061111b602083018461109d565b9392505050565b60008060006060848603121561113757600080fd5b833561114281610f5a565b9250602084013561115281610f5a565b929592945050506040919091013590565b600080600080600080600060c0888a03121561117e57600080fd5b873561118981610f5a565b9650602088013561119981610f5a565b955060408801356111a981610f5a565b945060608801356111b981610f5a565b93506080880135925060a088013567ffffffffffffffff8111156111dc57600080fd5b6111e88a828b01610f98565b989b979a50959850939692959293505050565b600080600080600080600060c0888a03121561121657600080fd5b873561122181610f5a565b9650602088013561123181610f5a565b9550604088013561124181610f5a565b94506060880135935061125660808901610f7f565b925060a088013567ffffffffffffffff8111156111dc57600080fd5b60006020828403121561128457600080fd5b8151801515811461111b57600080fd5b6000602082840312156112a657600080fd5b815161111b81610f5a565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff851681528360208201526060604082015260006113306060830184866112b1565b9695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff808a1683528089166020840152808816604084015280871660608401525084608083015260c060a083015261138a60c0830184866112b1565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006113c6606083018561109d565b905063ffffffff8316604083015294935050505056fea164736f6c634300080f000a"; +- hex"608060405234801561001057600080fd5b50600436106100d45760003560e01c80635d93a3fc11610081578063927ede2d1161005b578063927ede2d14610231578063aa5574521461024f578063c89701a21461026257600080fd5b80635d93a3fc146101cc578063761f4493146102005780637f46ddb21461021357600080fd5b8063485cc955116100b2578063485cc9551461015857806354fd4d501461016b5780635c975abb146101b457600080fd5b806335e80ab3146100d95780633687011a146101235780633cb747bf14610138575b600080fd5b6032546100f99073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b610136610131366004610fe1565b610282565b005b6001546100f99073ffffffffffffffffffffffffffffffffffffffff1681565b610136610166366004611064565b61032e565b6101a76040518060400160405280600c81526020017f322e312e312b626574612e31000000000000000000000000000000000000000081525081565b60405161011a9190611108565b6101bc610518565b604051901515815260200161011a565b6101bc6101da366004611122565b603160209081526000938452604080852082529284528284209052825290205460ff1681565b61013661020e366004611163565b6105b1565b60025473ffffffffffffffffffffffffffffffffffffffff166100f9565b60015473ffffffffffffffffffffffffffffffffffffffff166100f9565b61013661025d3660046111fb565b610a58565b6002546100f99073ffffffffffffffffffffffffffffffffffffffff1681565b333b15610316576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4552433732314272696467653a206163636f756e74206973206e6f742065787460448201527f65726e616c6c79206f776e65640000000000000000000000000000000000000060648201526084015b60405180910390fd5b6103268686333388888888610b30565b505050505050565b600054610100900460ff161580801561034e5750600054600160ff909116105b806103685750303b158015610368575060005460ff166001145b6103f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161030d565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561045257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84161790556104b083734200000000000000000000000000000000000014610e70565b801561051357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b603254604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa158015610588573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ac9190611272565b905090565b60015473ffffffffffffffffffffffffffffffffffffffff16331480156106865750600254600154604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9384169390921691636e296e45916004808201926020929091908290030181865afa15801561064a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061066e9190611294565b73ffffffffffffffffffffffffffffffffffffffff16145b610712576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4552433732314272696467653a2066756e6374696f6e2063616e206f6e6c792060448201527f62652063616c6c65642066726f6d20746865206f746865722062726964676500606482015260840161030d565b61071a610518565b15610781576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4c314552433732314272696467653a2070617573656400000000000000000000604482015260640161030d565b3073ffffffffffffffffffffffffffffffffffffffff881603610826576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4c314552433732314272696467653a206c6f63616c20746f6b656e2063616e6e60448201527f6f742062652073656c6600000000000000000000000000000000000000000000606482015260840161030d565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152603160209081526040808320938a1683529281528282208683529052205460ff1615156001146108f5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4c314552433732314272696467653a20546f6b656e204944206973206e6f742060448201527f657363726f77656420696e20746865204c312042726964676500000000000000606482015260840161030d565b73ffffffffffffffffffffffffffffffffffffffff87811660008181526031602090815260408083208b8616845282528083208884529091529081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517f42842e0e000000000000000000000000000000000000000000000000000000008152306004820152918616602483015260448201859052906342842e0e90606401600060405180830381600087803b1580156109b557600080fd5b505af11580156109c9573d6000803e3d6000fd5b505050508473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff167f1f39bf6707b5d608453e0ae4c067b562bcc4c85c0f562ef5d2c774d2e7f131ac87878787604051610a4794939291906112fa565b60405180910390a450505050505050565b73ffffffffffffffffffffffffffffffffffffffff8516610afb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4552433732314272696467653a206e667420726563697069656e742063616e6e60448201527f6f74206265206164647265737328302900000000000000000000000000000000606482015260840161030d565b610b0b8787338888888888610b30565b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b73ffffffffffffffffffffffffffffffffffffffff8716610bd3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f4c314552433732314272696467653a2072656d6f746520746f6b656e2063616e60448201527f6e6f742062652061646472657373283029000000000000000000000000000000606482015260840161030d565b600063761f449360e01b888a8989898888604051602401610bfa979695949392919061133a565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000959095169490941790935273ffffffffffffffffffffffffffffffffffffffff8c81166000818152603186528381208e8416825286528381208b82529095529382902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905590517f23b872dd000000000000000000000000000000000000000000000000000000008152908a166004820152306024820152604481018890529092506323b872dd90606401600060405180830381600087803b158015610d3a57600080fd5b505af1158015610d4e573d6000803e3d6000fd5b50506001546002546040517f3dbb202b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9283169450633dbb202b9350610db1929091169085908990600401611397565b600060405180830381600087803b158015610dcb57600080fd5b505af1158015610ddf573d6000803e3d6000fd5b505050508673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff167fb7460e2a880f256ebef3406116ff3eee0cee51ebccdc2a40698f87ebb2e9c1a589898888604051610e5d94939291906112fa565b60405180910390a4505050505050505050565b600054610100900460ff16610f07576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161030d565b6001805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560028054929093169116179055565b73ffffffffffffffffffffffffffffffffffffffff81168114610f7c57600080fd5b50565b803563ffffffff81168114610f9357600080fd5b919050565b60008083601f840112610faa57600080fd5b50813567ffffffffffffffff811115610fc257600080fd5b602083019150836020828501011115610fda57600080fd5b9250929050565b60008060008060008060a08789031215610ffa57600080fd5b863561100581610f5a565b9550602087013561101581610f5a565b94506040870135935061102a60608801610f7f565b9250608087013567ffffffffffffffff81111561104657600080fd5b61105289828a01610f98565b979a9699509497509295939492505050565b6000806040838503121561107757600080fd5b823561108281610f5a565b9150602083013561109281610f5a565b809150509250929050565b6000815180845260005b818110156110c3576020818501810151868301820152016110a7565b818111156110d5576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061111b602083018461109d565b9392505050565b60008060006060848603121561113757600080fd5b833561114281610f5a565b9250602084013561115281610f5a565b929592945050506040919091013590565b600080600080600080600060c0888a03121561117e57600080fd5b873561118981610f5a565b9650602088013561119981610f5a565b955060408801356111a981610f5a565b945060608801356111b981610f5a565b93506080880135925060a088013567ffffffffffffffff8111156111dc57600080fd5b6111e88a828b01610f98565b989b979a50959850939692959293505050565b600080600080600080600060c0888a03121561121657600080fd5b873561122181610f5a565b9650602088013561123181610f5a565b9550604088013561124181610f5a565b94506060880135935061125660808901610f7f565b925060a088013567ffffffffffffffff8111156111dc57600080fd5b60006020828403121561128457600080fd5b8151801515811461111b57600080fd5b6000602082840312156112a657600080fd5b815161111b81610f5a565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff851681528360208201526060604082015260006113306060830184866112b1565b9695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff808a1683528089166020840152808816604084015280871660608401525084608083015260c060a083015261138a60c0830184866112b1565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006113c6606083018561109d565b905063ffffffff8316604083015294935050505056fea164736f6c634300080f000a"; ++ hex"608060405234801561001057600080fd5b50600436106100d45760003560e01c80635d93a3fc11610081578063927ede2d1161005b578063927ede2d14610231578063aa5574521461024f578063c89701a21461026257600080fd5b80635d93a3fc146101cc578063761f4493146102005780637f46ddb21461021357600080fd5b8063485cc955116100b2578063485cc9551461015857806354fd4d501461016b5780635c975abb146101b457600080fd5b806335e80ab3146100d95780633687011a146101235780633cb747bf14610138575b600080fd5b6032546100f99073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b610136610131366004610fe1565b610282565b005b6001546100f99073ffffffffffffffffffffffffffffffffffffffff1681565b610136610166366004611064565b61032e565b6101a76040518060400160405280600c81526020017f322e312e312d626574612e32000000000000000000000000000000000000000081525081565b60405161011a9190611108565b6101bc610518565b604051901515815260200161011a565b6101bc6101da366004611122565b603160209081526000938452604080852082529284528284209052825290205460ff1681565b61013661020e366004611163565b6105b1565b60025473ffffffffffffffffffffffffffffffffffffffff166100f9565b60015473ffffffffffffffffffffffffffffffffffffffff166100f9565b61013661025d3660046111fb565b610a58565b6002546100f99073ffffffffffffffffffffffffffffffffffffffff1681565b333b15610316576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4552433732314272696467653a206163636f756e74206973206e6f742065787460448201527f65726e616c6c79206f776e65640000000000000000000000000000000000000060648201526084015b60405180910390fd5b6103268686333388888888610b30565b505050505050565b600054610100900460ff161580801561034e5750600054600160ff909116105b806103685750303b158015610368575060005460ff166001145b6103f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161030d565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561045257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84161790556104b083734200000000000000000000000000000000000014610e70565b801561051357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b603254604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa158015610588573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ac9190611272565b905090565b60015473ffffffffffffffffffffffffffffffffffffffff16331480156106865750600254600154604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9384169390921691636e296e45916004808201926020929091908290030181865afa15801561064a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061066e9190611294565b73ffffffffffffffffffffffffffffffffffffffff16145b610712576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4552433732314272696467653a2066756e6374696f6e2063616e206f6e6c792060448201527f62652063616c6c65642066726f6d20746865206f746865722062726964676500606482015260840161030d565b61071a610518565b15610781576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4c314552433732314272696467653a2070617573656400000000000000000000604482015260640161030d565b3073ffffffffffffffffffffffffffffffffffffffff881603610826576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4c314552433732314272696467653a206c6f63616c20746f6b656e2063616e6e60448201527f6f742062652073656c6600000000000000000000000000000000000000000000606482015260840161030d565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152603160209081526040808320938a1683529281528282208683529052205460ff1615156001146108f5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4c314552433732314272696467653a20546f6b656e204944206973206e6f742060448201527f657363726f77656420696e20746865204c312042726964676500000000000000606482015260840161030d565b73ffffffffffffffffffffffffffffffffffffffff87811660008181526031602090815260408083208b8616845282528083208884529091529081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517f42842e0e000000000000000000000000000000000000000000000000000000008152306004820152918616602483015260448201859052906342842e0e90606401600060405180830381600087803b1580156109b557600080fd5b505af11580156109c9573d6000803e3d6000fd5b505050508473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff167f1f39bf6707b5d608453e0ae4c067b562bcc4c85c0f562ef5d2c774d2e7f131ac87878787604051610a4794939291906112fa565b60405180910390a450505050505050565b73ffffffffffffffffffffffffffffffffffffffff8516610afb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4552433732314272696467653a206e667420726563697069656e742063616e6e60448201527f6f74206265206164647265737328302900000000000000000000000000000000606482015260840161030d565b610b0b8787338888888888610b30565b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b73ffffffffffffffffffffffffffffffffffffffff8716610bd3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f4c314552433732314272696467653a2072656d6f746520746f6b656e2063616e60448201527f6e6f742062652061646472657373283029000000000000000000000000000000606482015260840161030d565b600063761f449360e01b888a8989898888604051602401610bfa979695949392919061133a565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000959095169490941790935273ffffffffffffffffffffffffffffffffffffffff8c81166000818152603186528381208e8416825286528381208b82529095529382902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905590517f23b872dd000000000000000000000000000000000000000000000000000000008152908a166004820152306024820152604481018890529092506323b872dd90606401600060405180830381600087803b158015610d3a57600080fd5b505af1158015610d4e573d6000803e3d6000fd5b50506001546002546040517f3dbb202b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9283169450633dbb202b9350610db1929091169085908990600401611397565b600060405180830381600087803b158015610dcb57600080fd5b505af1158015610ddf573d6000803e3d6000fd5b505050508673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff167fb7460e2a880f256ebef3406116ff3eee0cee51ebccdc2a40698f87ebb2e9c1a589898888604051610e5d94939291906112fa565b60405180910390a4505050505050505050565b600054610100900460ff16610f07576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161030d565b6001805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560028054929093169116179055565b73ffffffffffffffffffffffffffffffffffffffff81168114610f7c57600080fd5b50565b803563ffffffff81168114610f9357600080fd5b919050565b60008083601f840112610faa57600080fd5b50813567ffffffffffffffff811115610fc257600080fd5b602083019150836020828501011115610fda57600080fd5b9250929050565b60008060008060008060a08789031215610ffa57600080fd5b863561100581610f5a565b9550602087013561101581610f5a565b94506040870135935061102a60608801610f7f565b9250608087013567ffffffffffffffff81111561104657600080fd5b61105289828a01610f98565b979a9699509497509295939492505050565b6000806040838503121561107757600080fd5b823561108281610f5a565b9150602083013561109281610f5a565b809150509250929050565b6000815180845260005b818110156110c3576020818501810151868301820152016110a7565b818111156110d5576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061111b602083018461109d565b9392505050565b60008060006060848603121561113757600080fd5b833561114281610f5a565b9250602084013561115281610f5a565b929592945050506040919091013590565b600080600080600080600060c0888a03121561117e57600080fd5b873561118981610f5a565b9650602088013561119981610f5a565b955060408801356111a981610f5a565b945060608801356111b981610f5a565b93506080880135925060a088013567ffffffffffffffff8111156111dc57600080fd5b6111e88a828b01610f98565b989b979a50959850939692959293505050565b600080600080600080600060c0888a03121561121657600080fd5b873561122181610f5a565b9650602088013561123181610f5a565b9550604088013561124181610f5a565b94506060880135935061125660808901610f7f565b925060a088013567ffffffffffffffff8111156111dc57600080fd5b60006020828403121561128457600080fd5b8151801515811461111b57600080fd5b6000602082840312156112a657600080fd5b815161111b81610f5a565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff851681528360208201526060604082015260006113306060830184866112b1565b9695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff808a1683528089166020840152808816604084015280871660608401525084608083015260c060a083015261138a60c0830184866112b1565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006113c6606083018561109d565b905063ffffffff8316604083015294935050505056fea164736f6c634300080f000a"; bytes internal constant optimismPortalCode = - hex"6080604052600436106101635760003560e01c80638c3152e9116100c0578063b69ef8a811610074578063cff0ab9611610059578063cff0ab9614610444578063e965084c146104e5578063e9e05c421461057157600080fd5b8063b69ef8a814610401578063c0c53b8b1461042457600080fd5b80639bf62d82116100a55780639bf62d821461036b578063a14238e714610398578063a35d99df146103c857600080fd5b80638c3152e91461031e5780639b5f694a1461033e57600080fd5b806354fd4d50116101175780636dbffb78116100fc5780636dbffb78146102de57806371cfaa3f146102fe5780638b4c40b01461018857600080fd5b806354fd4d501461026d5780635c975abb146102b957600080fd5b806335e80ab31161014857806335e80ab314610206578063452a9320146102385780634870496f1461024d57600080fd5b8063149f2f221461018f57806333d7e2bd146101af57600080fd5b3661018a576101883334620186a060006040518060200160405280600081525061057f565b005b600080fd5b34801561019b57600080fd5b506101886101aa366004614b97565b610624565b3480156101bb57600080fd5b506037546101dc9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561021257600080fd5b506035546101dc90610100900473ffffffffffffffffffffffffffffffffffffffff1681565b34801561024457600080fd5b506101dc610865565b34801561025957600080fd5b50610188610268366004614ccb565b6108fd565b34801561027957600080fd5b50604080518082018252600c81527f322e382e312d626574612e310000000000000000000000000000000000000000602082015290516101fd9190614e1d565b3480156102c557600080fd5b506102ce610eaa565b60405190151581526020016101fd565b3480156102ea57600080fd5b506102ce6102f9366004614e30565b610f3d565b34801561030a57600080fd5b50610188610319366004614e58565b610ff8565b34801561032a57600080fd5b50610188610339366004614e9e565b6111ba565b34801561034a57600080fd5b506036546101dc9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561037757600080fd5b506032546101dc9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156103a457600080fd5b506102ce6103b3366004614e30565b60336020526000908152604090205460ff1681565b3480156103d457600080fd5b506103e86103e3366004614edb565b611c3c565b60405167ffffffffffffffff90911681526020016101fd565b34801561040d57600080fd5b50610416611c55565b6040519081526020016101fd565b34801561043057600080fd5b5061018861043f366004614ef6565b611caf565b34801561045057600080fd5b506001546104ac906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff92831660208501529116908201526060016101fd565b3480156104f157600080fd5b50610543610500366004614e30565b603460205260009081526040902080546001909101546fffffffffffffffffffffffffffffffff8082169170010000000000000000000000000000000090041683565b604080519384526fffffffffffffffffffffffffffffffff92831660208501529116908201526060016101fd565b61018861057f366004614f41565b8260005a9050600061058f611f19565b50905073ffffffffffffffffffffffffffffffffffffffff811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee148015906105cb57503415155b15610602576040517ff2365b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610610883489898989611fb6565b5061061b8282612162565b50505050505050565b8260005a90506000610634611f19565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8216016106a6576040517f0eaf3c0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87603d60008282546106b89190614fed565b90915550506040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa15801561072a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061074e9190615005565b905061077273ffffffffffffffffffffffffffffffffffffffff831633308c61242f565b61077c8982614fed565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa1580156107e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061080a9190615005565b14610841576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61084f8a8a8a8a8a8a611fb6565b505061085b8282612162565b5050505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f8919061501e565b905090565b610905610eaa565b1561093c576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff16036109a5576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6036546040517fa25ae5570000000000000000000000000000000000000000000000000000000081526004810186905260009173ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa158015610a15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a39919061505b565b519050610a53610a4e368690038601866150c0565b61250b565b8114610ae6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f7074696d69736d506f7274616c3a20696e76616c6964206f7574707574207260448201527f6f6f742070726f6f66000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000610af187612567565b6000818152603460209081526040918290208251606081018452815481526001909101546fffffffffffffffffffffffffffffffff8082169383018490527001000000000000000000000000000000009091041692810192909252919250901580610c075750805160365460408084015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff909116600482015273ffffffffffffffffffffffffffffffffffffffff9091169063a25ae55790602401606060405180830381865afa158015610bdf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c03919061505b565b5114155b610c93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173682060448201527f68617320616c7265616479206265656e2070726f76656e0000000000000000006064820152608401610add565b60408051602081018490526000918101829052606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201209083018190529250610d5c9101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152600182527f0100000000000000000000000000000000000000000000000000000000000000602083015290610d52888a615126565b8a60400135612597565b610de8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a20696e76616c696420776974686472617760448201527f616c20696e636c7573696f6e2070726f6f6600000000000000000000000000006064820152608401610add565b604080516060810182528581526fffffffffffffffffffffffffffffffff42811660208084019182528c831684860190815260008981526034835286812095518655925190518416700100000000000000000000000000000000029316929092176001909301929092558b830151908c0151925173ffffffffffffffffffffffffffffffffffffffff918216939091169186917f67a6208cfcc0801d50f6cbe764733f4fddf66ac0b04442061a8a8c0cb6b63f629190a4505050505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f19573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f891906151aa565b6036546040517fa25ae55700000000000000000000000000000000000000000000000000000000815260048101839052600091610ff29173ffffffffffffffffffffffffffffffffffffffff9091169063a25ae55790602401606060405180830381865afa158015610fb3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fd7919061505b565b602001516fffffffffffffffffffffffffffffffff166125bb565b92915050565b60375473ffffffffffffffffffffffffffffffffffffffff163314611049576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61105562030d40612661565b60405173ffffffffffffffffffffffffffffffffffffffff8516602482015260ff8416604482015260648101839052608481018290526000907342000000000000000000000000000000000000159073deaddeaddeaddeaddeaddeaddeaddeaddead0001907fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32908490819062030d4090829060a401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f71cfaa3f000000000000000000000000000000000000000000000000000000001790529051611172969594939291016151c7565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526111aa91614e1d565b60405180910390a450505050565b565b6111c2610eaa565b156111f9576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60325473ffffffffffffffffffffffffffffffffffffffff1661dead1461124c576040517f9396d15600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061125782612567565b60008181526034602090815260408083208151606081018352815481526001909101546fffffffffffffffffffffffffffffffff80821694830185905270010000000000000000000000000000000090910416918101919091529293509003611342576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206e60448201527f6f74206265656e2070726f76656e2079657400000000000000000000000000006064820152608401610add565b603660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663887862726040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113d39190615005565b81602001516fffffffffffffffffffffffffffffffff16101561149e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604b60248201527f4f7074696d69736d506f7274616c3a207769746864726177616c2074696d657360448201527f74616d70206c657373207468616e204c32204f7261636c65207374617274696e60648201527f672074696d657374616d70000000000000000000000000000000000000000000608482015260a401610add565b6114bd81602001516fffffffffffffffffffffffffffffffff166125bb565b61156f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604560248201527f4f7074696d69736d506f7274616c3a2070726f76656e2077697468647261776160448201527f6c2066696e616c697a6174696f6e20706572696f6420686173206e6f7420656c60648201527f6170736564000000000000000000000000000000000000000000000000000000608482015260a401610add565b60365460408281015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff909116600482015260009173ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa1580156115f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061161a919061505b565b82518151919250146116d4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604960248201527f4f7074696d69736d506f7274616c3a206f757470757420726f6f742070726f7660448201527f656e206973206e6f74207468652073616d652061732063757272656e74206f7560648201527f7470757420726f6f740000000000000000000000000000000000000000000000608482015260a401610add565b6116f381602001516fffffffffffffffffffffffffffffffff166125bb565b6117a5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f4f7074696d69736d506f7274616c3a206f75747075742070726f706f73616c2060448201527f66696e616c697a6174696f6e20706572696f6420686173206e6f7420656c617060648201527f7365640000000000000000000000000000000000000000000000000000000000608482015260a401610add565b60008381526033602052604090205460ff1615611844576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206160448201527f6c7265616479206265656e2066696e616c697a656400000000000000000000006064820152608401610add565b6000838152603360209081526040822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558501516032805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff0000000000000000000000000000000000000000909216919091179055806118cf611f19565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8216016119325761192b8660400151876080015188606001518960a001516126c3565b9150611b85565b8073ffffffffffffffffffffffffffffffffffffffff16866040015173ffffffffffffffffffffffffffffffffffffffff160361199b576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606086015115611b5c578560600151603d60008282546119bb919061522c565b90915550506040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015611a2d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a519190615005565b9050611a86876040015188606001518473ffffffffffffffffffffffffffffffffffffffff166127219092919063ffffffff16565b6060870151611a95908261522c565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa158015611aff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b239190615005565b14611b5a576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b60a08601515115611b805761192b8660400151876080015160008960a001516126c3565b600191505b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405185907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b90611be790851515815260200190565b60405180910390a281158015611bfd5750326001145b15611c34576040517feeae4ed300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000611c49826010615243565b610ff290615208615273565b600080611c60611f19565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff821601611ca7574791505090565b5050603d5490565b600054610100900460ff1615808015611ccf5750600054600160ff909116105b80611ce95750303b158015611ce9575060005460ff166001145b611d75576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610add565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015611dd357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603680547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff8781169190911790925560378054909116858316179055603580547fffffffffffffffffffffff0000000000000000000000000000000000000000ff166101008584160217905560325416611e8c57603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790555b611e9461277c565b8015611ef757600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b603754604080517f4397dfef0000000000000000000000000000000000000000000000000000000081528151600093849373ffffffffffffffffffffffffffffffffffffffff90911692634397dfef92600480830193928290030181865afa158015611f89573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fad919061529f565b90939092509050565b818015611fd8575073ffffffffffffffffffffffffffffffffffffffff861615155b1561200f576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6120198151611c3c565b67ffffffffffffffff168367ffffffffffffffff161015612066576040517f4929b80800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6201d4c0815111156120a4576040517f73052b0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b333281146120c5575033731111000000000000000000000000000000001111015b600086868686866040516020016120e09594939291906151c7565b604051602081830303815290604052905060008873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32846040516121509190614e1d565b60405180910390a45050505050505050565b600154600090612198907801000000000000000000000000000000000000000000000000900467ffffffffffffffff164361522c565b905060006121a461288f565b90506000816020015160ff16826000015163ffffffff166121c59190615308565b905082156122fc576001546000906121fc908390700100000000000000000000000000000000900467ffffffffffffffff16615370565b90506000836040015160ff168361221391906153e4565b6001546122339084906fffffffffffffffffffffffffffffffff166153e4565b61223d9190615308565b60015490915060009061228e906122679084906fffffffffffffffffffffffffffffffff166154a0565b866060015163ffffffff168760a001516fffffffffffffffffffffffffffffffff16612950565b905060018611156122bd576122ba61226782876040015160ff1660018a6122b5919061522c565b61296f565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760015550505b6001805486919060109061232f908490700100000000000000000000000000000000900467ffffffffffffffff16615273565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550816000015163ffffffff16600160000160109054906101000a900467ffffffffffffffff1667ffffffffffffffff1613156123bc576040517f77ebef4d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001546000906123e8906fffffffffffffffffffffffffffffffff1667ffffffffffffffff8816615514565b905060006123fa48633b9aca006129c4565b6124049083615551565b905060005a612413908861522c565b90508082111561085b5761085b61242a828461522c565b6129db565b60405173ffffffffffffffffffffffffffffffffffffffff80851660248301528316604482015260648101829052611ef79085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152612a04565b6000816000015182602001518360400151846060015160405160200161254a949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b80516020808301516040808501516060860151608087015160a0880151935160009761254a979096959101615565565b6000806125a386612b10565b90506125b181868686612b42565b9695505050505050565b603654604080517ff4daa291000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163f4daa2919160048083019260209291908290030181865afa15801561262b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061264f9190615005565b6126599083614fed565b421192915050565b6001805463ffffffff8316919060109061269a908490700100000000000000000000000000000000900467ffffffffffffffff16615273565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555050565b60008060006126d3866000612b72565b905080612709576308c379a06000526020805278185361666543616c6c3a204e6f7420656e6f756768206761736058526064601cfd5b600080855160208701888b5af1979650505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526127779084907fa9059cbb0000000000000000000000000000000000000000000000000000000090606401612489565b505050565b600054610100900460ff16612813576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610add565b6001547801000000000000000000000000000000000000000000000000900467ffffffffffffffff166000036111b85760408051606081018252633b9aca00808252600060208301524367ffffffffffffffff169190920181905278010000000000000000000000000000000000000000000000000217600155565b6040805160c08082018352600080835260208301819052828401819052606083018190526080830181905260a083015260375483517fcc731b020000000000000000000000000000000000000000000000000000000081529351929373ffffffffffffffffffffffffffffffffffffffff9091169263cc731b02926004808401939192918290030181865afa15801561292c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f891906155d0565b600061296561295f8585612b90565b83612ba0565b90505b9392505050565b6000670de0b6b3a76400006129b06129878583615308565b61299990670de0b6b3a7640000615370565b6129ab85670de0b6b3a76400006153e4565b612baf565b6129ba90866153e4565b6129659190615308565b6000818310156129d45781612968565b5090919050565b6000805a90505b825a6129ee908361522c565b1015612777576129fd82615673565b91506129e2565b6000612a66826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612be09092919063ffffffff16565b8051909150156127775780806020019051810190612a8491906151aa565b612777576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610add565b60608180519060200120604051602001612b2c91815260200190565b6040516020818303038152906040529050919050565b6000612b6984612b53878686612bef565b8051602091820120825192909101919091201490565b95945050505050565b600080603f83619c4001026040850201603f5a021015949350505050565b6000818312156129d45781612968565b60008183126129d45781612968565b6000612968670de0b6b3a764000083612bc78661366d565b612bd191906153e4565b612bdb9190615308565b6138b1565b60606129658484600085613af0565b60606000845111612c5c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4d65726b6c65547269653a20656d707479206b657900000000000000000000006044820152606401610add565b6000612c6784613c86565b90506000612c7486613d72565b9050600084604051602001612c8b91815260200190565b60405160208183030381529060405290506000805b84518110156135e4576000858281518110612cbd57612cbd6156ab565b602002602001015190508451831115612d58576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4d65726b6c65547269653a206b657920696e646578206578636565647320746f60448201527f74616c206b6579206c656e6774680000000000000000000000000000000000006064820152608401610add565b82600003612e115780518051602091820120604051612da692612d8092910190815260200190565b604051602081830303815290604052858051602091820120825192909101919091201490565b612e0c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4d65726b6c65547269653a20696e76616c696420726f6f7420686173680000006044820152606401610add565b612f68565b805151602011612ec75780518051602091820120604051612e3b92612d8092910190815260200190565b612e0c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d65726b6c65547269653a20696e76616c6964206c6172676520696e7465726e60448201527f616c2068617368000000000000000000000000000000000000000000000000006064820152608401610add565b805184516020808701919091208251919092012014612f68576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4d65726b6c65547269653a20696e76616c696420696e7465726e616c206e6f6460448201527f65206861736800000000000000000000000000000000000000000000000000006064820152608401610add565b612f7460106001614fed565b8160200151510361315057845183036130e857612fae8160200151601081518110612fa157612fa16156ab565b6020026020010151613dd5565b96506000875111613041576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603b60248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286272616e63682900000000006064820152608401610add565b6001865161304f919061522c565b82146130dd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286272616e6368290000000000006064820152608401610add565b505050505050612968565b60008584815181106130fc576130fc6156ab565b602001015160f81c60f81b60f81c9050600082602001518260ff1681518110613127576131276156ab565b6020026020010151905061313a81613e89565b9550613147600186614fed565b945050506135d1565b60028160200151510361354957600061316882613eae565b905060008160008151811061317f5761317f6156ab565b016020015160f81c905060006131966002836156da565b6131a19060026156fc565b905060006131b2848360ff16613ed2565b905060006131c08a89613ed2565b905060006131ce8383613f08565b905080835114613260576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a20706174682072656d61696e646572206d7573742060448201527f736861726520616c6c206e6962626c65732077697468206b65790000000000006064820152608401610add565b60ff851660021480613275575060ff85166003145b15613464578082511461330a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f4d65726b6c65547269653a206b65792072656d61696e646572206d757374206260448201527f65206964656e746963616c20746f20706174682072656d61696e6465720000006064820152608401610add565b6133248760200151600181518110612fa157612fa16156ab565b9c5060008d51116133b7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286c65616629000000000000006064820152608401610add565b60018c516133c5919061522c565b8814613453576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286c6561662900000000000000006064820152608401610add565b505050505050505050505050612968565b60ff85161580613477575060ff85166001145b156134b6576134a38760200151600181518110613496576134966156ab565b6020026020010151613e89565b99506134af818a614fed565b985061353e565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4d65726b6c65547269653a2072656365697665642061206e6f6465207769746860448201527f20616e20756e6b6e6f776e2070726566697800000000000000000000000000006064820152608401610add565b5050505050506135d1565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4d65726b6c65547269653a20726563656976656420616e20756e70617273656160448201527f626c65206e6f64650000000000000000000000000000000000000000000000006064820152608401610add565b50806135dc81615673565b915050612ca0565b506040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4d65726b6c65547269653a2072616e206f7574206f662070726f6f6620656c6560448201527f6d656e74730000000000000000000000000000000000000000000000000000006064820152608401610add565b60008082136136d8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401610add565b600060606136e584613fbc565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c182136138e257506000919050565b680755bf798b4a1bf1e58212613954576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4558505f4f564552464c4f5700000000000000000000000000000000000000006044820152606401610add565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b606082471015613b82576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610add565b73ffffffffffffffffffffffffffffffffffffffff85163b613c00576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610add565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051613c29919061571f565b60006040518083038185875af1925050503d8060008114613c66576040519150601f19603f3d011682016040523d82523d6000602084013e613c6b565b606091505b5091509150613c7b828286614092565b979650505050505050565b80516060908067ffffffffffffffff811115613ca457613ca4614a8b565b604051908082528060200260200182016040528015613ce957816020015b6040805180820190915260608082526020820152815260200190600190039081613cc25790505b50915060005b81811015613d6b576040518060400160405280858381518110613d1457613d146156ab565b60200260200101518152602001613d43868481518110613d3657613d366156ab565b60200260200101516140e5565b815250838281518110613d5857613d586156ab565b6020908102919091010152600101613cef565b5050919050565b606080604051905082518060011b603f8101601f1916830160405280835250602084016020830160005b83811015613dca578060011b82018184015160001a8060041c8253600f811660018301535050600101613d9c565b509295945050505050565b60606000806000613de5856140f8565b919450925090506000816001811115613e0057613e0061573b565b14613e37576040517f1ff9b2e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613e418284614fed565b855114613e7a576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612b6985602001518484614596565b60606020826000015110613ea557613ea082613dd5565b610ff2565b610ff28261462a565b6060610ff2613ecd8360200151600081518110612fa157612fa16156ab565b613d72565b606082518210613ef15750604080516020810190915260008152610ff2565b6129688383848651613f03919061522c565b614640565b6000808251845110613f1b578251613f1e565b83515b90505b8082108015613fa55750828281518110613f3d57613f3d6156ab565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916848381518110613f7c57613f7c6156ab565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b15613fb557816001019150613f21565b5092915050565b6000808211614027576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401610add565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b606083156140a1575081612968565b8251156140b15782518084602001fd5b816040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610add9190614e1d565b6060610ff26140f383614818565b614885565b6000806000836000015160000361413b576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020840151805160001a607f811161416057600060016000945094509450505061458f565b60b7811161427657600061417560808361522c565b9050808760000151116141b4576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001838101517fff0000000000000000000000000000000000000000000000000000000000000016908214801561422c57507f80000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000008216105b15614263576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506001955093506000925061458f915050565b60bf81116143d457600061428b60b78361522c565b9050808760000151116142ca576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff0000000000000000000000000000000000000000000000000000000000000016600081900361432c576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c60378111614374576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61437e8184614fed565b8951116143b7576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6143c2836001614fed565b975095506000945061458f9350505050565b60f781116144395760006143e960c08361522c565b905080876000015111614428576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60019550935084925061458f915050565b600061444660f78361522c565b905080876000015111614485576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff000000000000000000000000000000000000000000000000000000000000001660008190036144e7576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c6037811161452f576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6145398184614fed565b895111614572576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61457d836001614fed565b975095506001945061458f9350505050565b9193909250565b60608167ffffffffffffffff8111156145b1576145b1614a8b565b6040519080825280601f01601f1916602001820160405280156145db576020820181803683370190505b50905081156129685760006145f08486614fed565b90506020820160005b848110156146115782810151828201526020016145f9565b84811115614620576000858301525b5050509392505050565b6060610ff2826020015160008460000151614596565b60608182601f0110156146af576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610add565b82828401101561471b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610add565b81830184511015614788576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401610add565b6060821580156147a7576040519150600082526020820160405261480f565b6040519150601f8416801560200281840101858101878315602002848b0101015b818310156147e05780518352602092830192016147c8565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b60408051808201909152600080825260208201528151600003614867576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50604080518082019091528151815260209182019181019190915290565b60606000806000614895856140f8565b9194509250905060018160018111156148b0576148b061573b565b146148e7576040517f4b9c6abe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84516148f38385614fed565b1461492a576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516020808252610420820190925290816020015b60408051808201909152600080825260208201528152602001906001900390816149415790505093506000835b8651811015614a2f576000806149b46040518060400160405280858c60000151614998919061522c565b8152602001858c602001516149ad9190614fed565b90526140f8565b5091509150604051806040016040528083836149d09190614fed565b8152602001848b602001516149e59190614fed565b8152508885815181106149fa576149fa6156ab565b6020908102919091010152614a10600185614fed565b9350614a1c8183614fed565b614a269084614fed565b9250505061496e565b50845250919392505050565b73ffffffffffffffffffffffffffffffffffffffff81168114614a5d57600080fd5b50565b803567ffffffffffffffff81168114614a7857600080fd5b919050565b8015158114614a5d57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614b0157614b01614a8b565b604052919050565b600082601f830112614b1a57600080fd5b813567ffffffffffffffff811115614b3457614b34614a8b565b614b6560207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601614aba565b818152846020838601011115614b7a57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060008060c08789031215614bb057600080fd5b8635614bbb81614a3b565b95506020870135945060408701359350614bd760608801614a60565b92506080870135614be781614a7d565b915060a087013567ffffffffffffffff811115614c0357600080fd5b614c0f89828a01614b09565b9150509295509295509295565b600060c08284031215614c2e57600080fd5b60405160c0810167ffffffffffffffff8282108183111715614c5257614c52614a8b565b816040528293508435835260208501359150614c6d82614a3b565b81602084015260408501359150614c8382614a3b565b816040840152606085013560608401526080850135608084015260a0850135915080821115614cb157600080fd5b50614cbe85828601614b09565b60a0830152505092915050565b600080600080600085870360e0811215614ce457600080fd5b863567ffffffffffffffff80821115614cfc57600080fd5b614d088a838b01614c1c565b97506020890135965060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc084011215614d4157600080fd5b60408901955060c0890135925080831115614d5b57600080fd5b828901925089601f840112614d6f57600080fd5b8235915080821115614d8057600080fd5b508860208260051b8401011115614d9657600080fd5b959894975092955050506020019190565b60005b83811015614dc2578181015183820152602001614daa565b83811115611ef75750506000910152565b60008151808452614deb816020860160208601614da7565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006129686020830184614dd3565b600060208284031215614e4257600080fd5b5035919050565b60ff81168114614a5d57600080fd5b60008060008060808587031215614e6e57600080fd5b8435614e7981614a3b565b93506020850135614e8981614e49565b93969395505050506040820135916060013590565b600060208284031215614eb057600080fd5b813567ffffffffffffffff811115614ec757600080fd5b614ed384828501614c1c565b949350505050565b600060208284031215614eed57600080fd5b61296882614a60565b600080600060608486031215614f0b57600080fd5b8335614f1681614a3b565b92506020840135614f2681614a3b565b91506040840135614f3681614a3b565b809150509250925092565b600080600080600060a08688031215614f5957600080fd5b8535614f6481614a3b565b945060208601359350614f7960408701614a60565b92506060860135614f8981614a7d565b9150608086013567ffffffffffffffff811115614fa557600080fd5b614fb188828901614b09565b9150509295509295909350565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561500057615000614fbe565b500190565b60006020828403121561501757600080fd5b5051919050565b60006020828403121561503057600080fd5b815161296881614a3b565b80516fffffffffffffffffffffffffffffffff81168114614a7857600080fd5b60006060828403121561506d57600080fd5b6040516060810181811067ffffffffffffffff8211171561509057615090614a8b565b604052825181526150a36020840161503b565b60208201526150b46040840161503b565b60408201529392505050565b6000608082840312156150d257600080fd5b6040516080810181811067ffffffffffffffff821117156150f5576150f5614a8b565b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b600067ffffffffffffffff8084111561514157615141614a8b565b8360051b6020615152818301614aba565b86815291850191818101903684111561516a57600080fd5b865b8481101561519e578035868111156151845760008081fd5b61519036828b01614b09565b84525091830191830161516c565b50979650505050505050565b6000602082840312156151bc57600080fd5b815161296881614a7d565b8581528460208201527fffffffffffffffff0000000000000000000000000000000000000000000000008460c01b16604082015282151560f81b60488201526000825161521b816049850160208701614da7565b919091016049019695505050505050565b60008282101561523e5761523e614fbe565b500390565b600067ffffffffffffffff8083168185168183048111821515161561526a5761526a614fbe565b02949350505050565b600067ffffffffffffffff80831681851680830382111561529657615296614fbe565b01949350505050565b600080604083850312156152b257600080fd5b82516152bd81614a3b565b60208401519092506152ce81614e49565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082615317576153176152d9565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f80000000000000000000000000000000000000000000000000000000000000008314161561536b5761536b614fbe565b500590565b6000808312837f8000000000000000000000000000000000000000000000000000000000000000018312811516156153aa576153aa614fbe565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0183138116156153de576153de614fbe565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60008413600084138583048511828216161561542557615425614fbe565b7f8000000000000000000000000000000000000000000000000000000000000000600087128682058812818416161561546057615460614fbe565b6000871292508782058712848416161561547c5761547c614fbe565b8785058712818416161561549257615492614fbe565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038413811516156154da576154da614fbe565b827f800000000000000000000000000000000000000000000000000000000000000003841281161561550e5761550e614fbe565b50500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561554c5761554c614fbe565b500290565b600082615560576155606152d9565b500490565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a08301526155b060c0830184614dd3565b98975050505050505050565b805163ffffffff81168114614a7857600080fd5b600060c082840312156155e257600080fd5b60405160c0810181811067ffffffffffffffff8211171561560557615605614a8b565b604052615611836155bc565b8152602083015161562181614e49565b6020820152604083015161563481614e49565b6040820152615645606084016155bc565b6060820152615656608084016155bc565b608082015261566760a0840161503b565b60a08201529392505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036156a4576156a4614fbe565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060ff8316806156ed576156ed6152d9565b8060ff84160691505092915050565b600060ff821660ff84168082101561571657615716614fbe565b90039392505050565b60008251615731818460208701614da7565b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea164736f6c634300080f000a"; -+ hex"6080604052600436106101635760003560e01c80638c3152e9116100c0578063b69ef8a811610074578063cff0ab9611610059578063cff0ab9614610444578063e965084c146104e5578063e9e05c421461057157600080fd5b8063b69ef8a814610401578063cf756fdf1461042457600080fd5b80639bf62d82116100a55780639bf62d821461036b578063a14238e714610398578063a35d99df146103c857600080fd5b80638c3152e91461031e5780639b5f694a1461033e57600080fd5b806354fd4d50116101175780636dbffb78116100fc5780636dbffb78146102de57806371cfaa3f146102fe5780638b4c40b01461018857600080fd5b806354fd4d501461026d5780635c975abb146102b957600080fd5b806335e80ab31161014857806335e80ab314610206578063452a9320146102385780634870496f1461024d57600080fd5b8063149f2f221461018f57806333d7e2bd146101af57600080fd5b3661018a576101883334620186a060006040518060200160405280600081525061057f565b005b600080fd5b34801561019b57600080fd5b506101886101aa366004614ba3565b610624565b3480156101bb57600080fd5b506037546101dc9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561021257600080fd5b506035546101dc90610100900473ffffffffffffffffffffffffffffffffffffffff1681565b34801561024457600080fd5b506101dc610865565b34801561025957600080fd5b50610188610268366004614cd7565b6108fd565b34801561027957600080fd5b50604080518082018252600c81527f322e382e312d626574612e310000000000000000000000000000000000000000602082015290516101fd9190614e29565b3480156102c557600080fd5b506102ce610eaa565b60405190151581526020016101fd565b3480156102ea57600080fd5b506102ce6102f9366004614e3c565b610f3d565b34801561030a57600080fd5b50610188610319366004614e64565b610ff8565b34801561032a57600080fd5b50610188610339366004614eaa565b6111ba565b34801561034a57600080fd5b506036546101dc9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561037757600080fd5b506032546101dc9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156103a457600080fd5b506102ce6103b3366004614e3c565b60336020526000908152604090205460ff1681565b3480156103d457600080fd5b506103e86103e3366004614ee7565b611c3c565b60405167ffffffffffffffff90911681526020016101fd565b34801561040d57600080fd5b50610416611c55565b6040519081526020016101fd565b34801561043057600080fd5b5061018861043f366004614f02565b611caf565b34801561045057600080fd5b506001546104ac906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff92831660208501529116908201526060016101fd565b3480156104f157600080fd5b50610543610500366004614e3c565b603460205260009081526040902080546001909101546fffffffffffffffffffffffffffffffff8082169170010000000000000000000000000000000090041683565b604080519384526fffffffffffffffffffffffffffffffff92831660208501529116908201526060016101fd565b61018861057f366004614f53565b8260005a9050600061058f611f1f565b50905073ffffffffffffffffffffffffffffffffffffffff811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee148015906105cb57503415155b15610602576040517ff2365b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610610883489898989611fbc565b5061061b8282612168565b50505050505050565b8260005a90506000610634611f1f565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8216016106a6576040517f0eaf3c0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87603d60008282546106b89190614fff565b90915550506040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa15801561072a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061074e9190615017565b905061077273ffffffffffffffffffffffffffffffffffffffff831633308c612435565b61077c8982614fff565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa1580156107e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061080a9190615017565b14610841576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61084f8a8a8a8a8a8a611fbc565b505061085b8282612168565b5050505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f89190615030565b905090565b610905610eaa565b1561093c576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff16036109a5576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6036546040517fa25ae5570000000000000000000000000000000000000000000000000000000081526004810186905260009173ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa158015610a15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a39919061506d565b519050610a53610a4e368690038601866150d2565b612517565b8114610ae6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f7074696d69736d506f7274616c3a20696e76616c6964206f7574707574207260448201527f6f6f742070726f6f66000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000610af187612573565b6000818152603460209081526040918290208251606081018452815481526001909101546fffffffffffffffffffffffffffffffff8082169383018490527001000000000000000000000000000000009091041692810192909252919250901580610c075750805160365460408084015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff909116600482015273ffffffffffffffffffffffffffffffffffffffff9091169063a25ae55790602401606060405180830381865afa158015610bdf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c03919061506d565b5114155b610c93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173682060448201527f68617320616c7265616479206265656e2070726f76656e0000000000000000006064820152608401610add565b60408051602081018490526000918101829052606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201209083018190529250610d5c9101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152600182527f0100000000000000000000000000000000000000000000000000000000000000602083015290610d52888a615138565b8a604001356125a3565b610de8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a20696e76616c696420776974686472617760448201527f616c20696e636c7573696f6e2070726f6f6600000000000000000000000000006064820152608401610add565b604080516060810182528581526fffffffffffffffffffffffffffffffff42811660208084019182528c831684860190815260008981526034835286812095518655925190518416700100000000000000000000000000000000029316929092176001909301929092558b830151908c0151925173ffffffffffffffffffffffffffffffffffffffff918216939091169186917f67a6208cfcc0801d50f6cbe764733f4fddf66ac0b04442061a8a8c0cb6b63f629190a4505050505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f19573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f891906151bc565b6036546040517fa25ae55700000000000000000000000000000000000000000000000000000000815260048101839052600091610ff29173ffffffffffffffffffffffffffffffffffffffff9091169063a25ae55790602401606060405180830381865afa158015610fb3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fd7919061506d565b602001516fffffffffffffffffffffffffffffffff166125c7565b92915050565b60375473ffffffffffffffffffffffffffffffffffffffff163314611049576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61105562030d4061266d565b60405173ffffffffffffffffffffffffffffffffffffffff8516602482015260ff8416604482015260648101839052608481018290526000907342000000000000000000000000000000000000159073deaddeaddeaddeaddeaddeaddeaddeaddead0001907fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32908490819062030d4090829060a401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f71cfaa3f000000000000000000000000000000000000000000000000000000001790529051611172969594939291016151d9565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526111aa91614e29565b60405180910390a450505050565b565b6111c2610eaa565b156111f9576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60325473ffffffffffffffffffffffffffffffffffffffff1661dead1461124c576040517f9396d15600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061125782612573565b60008181526034602090815260408083208151606081018352815481526001909101546fffffffffffffffffffffffffffffffff80821694830185905270010000000000000000000000000000000090910416918101919091529293509003611342576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206e60448201527f6f74206265656e2070726f76656e2079657400000000000000000000000000006064820152608401610add565b603660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663887862726040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113d39190615017565b81602001516fffffffffffffffffffffffffffffffff16101561149e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604b60248201527f4f7074696d69736d506f7274616c3a207769746864726177616c2074696d657360448201527f74616d70206c657373207468616e204c32204f7261636c65207374617274696e60648201527f672074696d657374616d70000000000000000000000000000000000000000000608482015260a401610add565b6114bd81602001516fffffffffffffffffffffffffffffffff166125c7565b61156f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604560248201527f4f7074696d69736d506f7274616c3a2070726f76656e2077697468647261776160448201527f6c2066696e616c697a6174696f6e20706572696f6420686173206e6f7420656c60648201527f6170736564000000000000000000000000000000000000000000000000000000608482015260a401610add565b60365460408281015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff909116600482015260009173ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa1580156115f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061161a919061506d565b82518151919250146116d4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604960248201527f4f7074696d69736d506f7274616c3a206f757470757420726f6f742070726f7660448201527f656e206973206e6f74207468652073616d652061732063757272656e74206f7560648201527f7470757420726f6f740000000000000000000000000000000000000000000000608482015260a401610add565b6116f381602001516fffffffffffffffffffffffffffffffff166125c7565b6117a5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f4f7074696d69736d506f7274616c3a206f75747075742070726f706f73616c2060448201527f66696e616c697a6174696f6e20706572696f6420686173206e6f7420656c617060648201527f7365640000000000000000000000000000000000000000000000000000000000608482015260a401610add565b60008381526033602052604090205460ff1615611844576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206160448201527f6c7265616479206265656e2066696e616c697a656400000000000000000000006064820152608401610add565b6000838152603360209081526040822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558501516032805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff0000000000000000000000000000000000000000909216919091179055806118cf611f1f565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8216016119325761192b8660400151876080015188606001518960a001516126cf565b9150611b85565b8073ffffffffffffffffffffffffffffffffffffffff16866040015173ffffffffffffffffffffffffffffffffffffffff160361199b576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606086015115611b5c578560600151603d60008282546119bb919061523e565b90915550506040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015611a2d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a519190615017565b9050611a86876040015188606001518473ffffffffffffffffffffffffffffffffffffffff1661272d9092919063ffffffff16565b6060870151611a95908261523e565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa158015611aff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b239190615017565b14611b5a576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b60a08601515115611b805761192b8660400151876080015160008960a001516126cf565b600191505b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405185907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b90611be790851515815260200190565b60405180910390a281158015611bfd5750326001145b15611c34576040517feeae4ed300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000611c49826010615255565b610ff290615208615285565b600080611c60611f1f565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff821601611ca7574791505090565b5050603d5490565b600054610100900460ff1615808015611ccf5750600054600160ff909116105b80611ce95750303b158015611ce9575060005460ff166001145b611d75576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610add565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015611dd357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603680547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff8881169190911790925560378054909116868316179055603580547fffffffffffffffffffffff0000000000000000000000000000000000000000ff166101008684160217905560325416611e8c57603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790555b603d829055611e99612788565b8015611efc57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b603754604080517f4397dfef0000000000000000000000000000000000000000000000000000000081528151600093849373ffffffffffffffffffffffffffffffffffffffff90911692634397dfef92600480830193928290030181865afa158015611f8f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fb391906152b1565b90939092509050565b818015611fde575073ffffffffffffffffffffffffffffffffffffffff861615155b15612015576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61201f8151611c3c565b67ffffffffffffffff168367ffffffffffffffff16101561206c576040517f4929b80800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6201d4c0815111156120aa576040517f73052b0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b333281146120cb575033731111000000000000000000000000000000001111015b600086868686866040516020016120e69594939291906151d9565b604051602081830303815290604052905060008873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32846040516121569190614e29565b60405180910390a45050505050505050565b60015460009061219e907801000000000000000000000000000000000000000000000000900467ffffffffffffffff164361523e565b905060006121aa61289b565b90506000816020015160ff16826000015163ffffffff166121cb919061531a565b9050821561230257600154600090612202908390700100000000000000000000000000000000900467ffffffffffffffff16615382565b90506000836040015160ff168361221991906153f6565b6001546122399084906fffffffffffffffffffffffffffffffff166153f6565b612243919061531a565b6001549091506000906122949061226d9084906fffffffffffffffffffffffffffffffff166154b2565b866060015163ffffffff168760a001516fffffffffffffffffffffffffffffffff1661295c565b905060018611156122c3576122c061226d82876040015160ff1660018a6122bb919061523e565b61297b565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760015550505b60018054869190601090612335908490700100000000000000000000000000000000900467ffffffffffffffff16615285565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550816000015163ffffffff16600160000160109054906101000a900467ffffffffffffffff1667ffffffffffffffff1613156123c2576040517f77ebef4d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001546000906123ee906fffffffffffffffffffffffffffffffff1667ffffffffffffffff8816615526565b9050600061240048633b9aca006129d0565b61240a9083615563565b905060005a612419908861523e565b90508082111561085b5761085b612430828461523e565b6129e7565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526125119085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152612a10565b50505050565b60008160000151826020015183604001518460600151604051602001612556949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b80516020808301516040808501516060860151608087015160a08801519351600097612556979096959101615577565b6000806125af86612b1c565b90506125bd81868686612b4e565b9695505050505050565b603654604080517ff4daa291000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163f4daa2919160048083019260209291908290030181865afa158015612637573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061265b9190615017565b6126659083614fff565b421192915050565b6001805463ffffffff831691906010906126a6908490700100000000000000000000000000000000900467ffffffffffffffff16615285565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555050565b60008060006126df866000612b7e565b905080612715576308c379a06000526020805278185361666543616c6c3a204e6f7420656e6f756768206761736058526064601cfd5b600080855160208701888b5af1979650505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526127839084907fa9059cbb000000000000000000000000000000000000000000000000000000009060640161248f565b505050565b600054610100900460ff1661281f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610add565b6001547801000000000000000000000000000000000000000000000000900467ffffffffffffffff166000036111b85760408051606081018252633b9aca00808252600060208301524367ffffffffffffffff169190920181905278010000000000000000000000000000000000000000000000000217600155565b6040805160c08082018352600080835260208301819052828401819052606083018190526080830181905260a083015260375483517fcc731b020000000000000000000000000000000000000000000000000000000081529351929373ffffffffffffffffffffffffffffffffffffffff9091169263cc731b02926004808401939192918290030181865afa158015612938573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f891906155e2565b600061297161296b8585612b9c565b83612bac565b90505b9392505050565b6000670de0b6b3a76400006129bc612993858361531a565b6129a590670de0b6b3a7640000615382565b6129b785670de0b6b3a76400006153f6565b612bbb565b6129c690866153f6565b612971919061531a565b6000818310156129e05781612974565b5090919050565b6000805a90505b825a6129fa908361523e565b101561278357612a0982615685565b91506129ee565b6000612a72826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612bec9092919063ffffffff16565b8051909150156127835780806020019051810190612a9091906151bc565b612783576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610add565b60608180519060200120604051602001612b3891815260200190565b6040516020818303038152906040529050919050565b6000612b7584612b5f878686612bfb565b8051602091820120825192909101919091201490565b95945050505050565b600080603f83619c4001026040850201603f5a021015949350505050565b6000818312156129e05781612974565b60008183126129e05781612974565b6000612974670de0b6b3a764000083612bd386613679565b612bdd91906153f6565b612be7919061531a565b6138bd565b60606129718484600085613afc565b60606000845111612c68576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4d65726b6c65547269653a20656d707479206b657900000000000000000000006044820152606401610add565b6000612c7384613c92565b90506000612c8086613d7e565b9050600084604051602001612c9791815260200190565b60405160208183030381529060405290506000805b84518110156135f0576000858281518110612cc957612cc96156bd565b602002602001015190508451831115612d64576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4d65726b6c65547269653a206b657920696e646578206578636565647320746f60448201527f74616c206b6579206c656e6774680000000000000000000000000000000000006064820152608401610add565b82600003612e1d5780518051602091820120604051612db292612d8c92910190815260200190565b604051602081830303815290604052858051602091820120825192909101919091201490565b612e18576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4d65726b6c65547269653a20696e76616c696420726f6f7420686173680000006044820152606401610add565b612f74565b805151602011612ed35780518051602091820120604051612e4792612d8c92910190815260200190565b612e18576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d65726b6c65547269653a20696e76616c6964206c6172676520696e7465726e60448201527f616c2068617368000000000000000000000000000000000000000000000000006064820152608401610add565b805184516020808701919091208251919092012014612f74576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4d65726b6c65547269653a20696e76616c696420696e7465726e616c206e6f6460448201527f65206861736800000000000000000000000000000000000000000000000000006064820152608401610add565b612f8060106001614fff565b8160200151510361315c57845183036130f457612fba8160200151601081518110612fad57612fad6156bd565b6020026020010151613de1565b9650600087511161304d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603b60248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286272616e63682900000000006064820152608401610add565b6001865161305b919061523e565b82146130e9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286272616e6368290000000000006064820152608401610add565b505050505050612974565b6000858481518110613108576131086156bd565b602001015160f81c60f81b60f81c9050600082602001518260ff1681518110613133576131336156bd565b6020026020010151905061314681613e95565b9550613153600186614fff565b945050506135dd565b60028160200151510361355557600061317482613eba565b905060008160008151811061318b5761318b6156bd565b016020015160f81c905060006131a26002836156ec565b6131ad90600261570e565b905060006131be848360ff16613ede565b905060006131cc8a89613ede565b905060006131da8383613f14565b90508083511461326c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a20706174682072656d61696e646572206d7573742060448201527f736861726520616c6c206e6962626c65732077697468206b65790000000000006064820152608401610add565b60ff851660021480613281575060ff85166003145b156134705780825114613316576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f4d65726b6c65547269653a206b65792072656d61696e646572206d757374206260448201527f65206964656e746963616c20746f20706174682072656d61696e6465720000006064820152608401610add565b6133308760200151600181518110612fad57612fad6156bd565b9c5060008d51116133c3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286c65616629000000000000006064820152608401610add565b60018c516133d1919061523e565b881461345f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286c6561662900000000000000006064820152608401610add565b505050505050505050505050612974565b60ff85161580613483575060ff85166001145b156134c2576134af87602001516001815181106134a2576134a26156bd565b6020026020010151613e95565b99506134bb818a614fff565b985061354a565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4d65726b6c65547269653a2072656365697665642061206e6f6465207769746860448201527f20616e20756e6b6e6f776e2070726566697800000000000000000000000000006064820152608401610add565b5050505050506135dd565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4d65726b6c65547269653a20726563656976656420616e20756e70617273656160448201527f626c65206e6f64650000000000000000000000000000000000000000000000006064820152608401610add565b50806135e881615685565b915050612cac565b506040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4d65726b6c65547269653a2072616e206f7574206f662070726f6f6620656c6560448201527f6d656e74730000000000000000000000000000000000000000000000000000006064820152608401610add565b60008082136136e4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401610add565b600060606136f184613fc8565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c182136138ee57506000919050565b680755bf798b4a1bf1e58212613960576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4558505f4f564552464c4f5700000000000000000000000000000000000000006044820152606401610add565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b606082471015613b8e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610add565b73ffffffffffffffffffffffffffffffffffffffff85163b613c0c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610add565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051613c359190615731565b60006040518083038185875af1925050503d8060008114613c72576040519150601f19603f3d011682016040523d82523d6000602084013e613c77565b606091505b5091509150613c8782828661409e565b979650505050505050565b80516060908067ffffffffffffffff811115613cb057613cb0614a97565b604051908082528060200260200182016040528015613cf557816020015b6040805180820190915260608082526020820152815260200190600190039081613cce5790505b50915060005b81811015613d77576040518060400160405280858381518110613d2057613d206156bd565b60200260200101518152602001613d4f868481518110613d4257613d426156bd565b60200260200101516140f1565b815250838281518110613d6457613d646156bd565b6020908102919091010152600101613cfb565b5050919050565b606080604051905082518060011b603f8101601f1916830160405280835250602084016020830160005b83811015613dd6578060011b82018184015160001a8060041c8253600f811660018301535050600101613da8565b509295945050505050565b60606000806000613df185614104565b919450925090506000816001811115613e0c57613e0c61574d565b14613e43576040517f1ff9b2e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613e4d8284614fff565b855114613e86576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612b75856020015184846145a2565b60606020826000015110613eb157613eac82613de1565b610ff2565b610ff282614636565b6060610ff2613ed98360200151600081518110612fad57612fad6156bd565b613d7e565b606082518210613efd5750604080516020810190915260008152610ff2565b6129748383848651613f0f919061523e565b61464c565b6000808251845110613f27578251613f2a565b83515b90505b8082108015613fb15750828281518110613f4957613f496156bd565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916848381518110613f8857613f886156bd565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b15613fc157816001019150613f2d565b5092915050565b6000808211614033576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401610add565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b606083156140ad575081612974565b8251156140bd5782518084602001fd5b816040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610add9190614e29565b6060610ff26140ff83614824565b614891565b60008060008360000151600003614147576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020840151805160001a607f811161416c57600060016000945094509450505061459b565b60b7811161428257600061418160808361523e565b9050808760000151116141c0576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001838101517fff0000000000000000000000000000000000000000000000000000000000000016908214801561423857507f80000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000008216105b1561426f576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506001955093506000925061459b915050565b60bf81116143e057600061429760b78361523e565b9050808760000151116142d6576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614338576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c60378111614380576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61438a8184614fff565b8951116143c3576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6143ce836001614fff565b975095506000945061459b9350505050565b60f781116144455760006143f560c08361523e565b905080876000015111614434576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60019550935084925061459b915050565b600061445260f78361523e565b905080876000015111614491576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff000000000000000000000000000000000000000000000000000000000000001660008190036144f3576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c6037811161453b576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6145458184614fff565b89511161457e576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614589836001614fff565b975095506001945061459b9350505050565b9193909250565b60608167ffffffffffffffff8111156145bd576145bd614a97565b6040519080825280601f01601f1916602001820160405280156145e7576020820181803683370190505b50905081156129745760006145fc8486614fff565b90506020820160005b8481101561461d578281015182820152602001614605565b8481111561462c576000858301525b5050509392505050565b6060610ff28260200151600084600001516145a2565b60608182601f0110156146bb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610add565b828284011015614727576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610add565b81830184511015614794576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401610add565b6060821580156147b3576040519150600082526020820160405261481b565b6040519150601f8416801560200281840101858101878315602002848b0101015b818310156147ec5780518352602092830192016147d4565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b60408051808201909152600080825260208201528151600003614873576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50604080518082019091528151815260209182019181019190915290565b606060008060006148a185614104565b9194509250905060018160018111156148bc576148bc61574d565b146148f3576040517f4b9c6abe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84516148ff8385614fff565b14614936576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516020808252610420820190925290816020015b604080518082019091526000808252602082015281526020019060019003908161494d5790505093506000835b8651811015614a3b576000806149c06040518060400160405280858c600001516149a4919061523e565b8152602001858c602001516149b99190614fff565b9052614104565b5091509150604051806040016040528083836149dc9190614fff565b8152602001848b602001516149f19190614fff565b815250888581518110614a0657614a066156bd565b6020908102919091010152614a1c600185614fff565b9350614a288183614fff565b614a329084614fff565b9250505061497a565b50845250919392505050565b73ffffffffffffffffffffffffffffffffffffffff81168114614a6957600080fd5b50565b803567ffffffffffffffff81168114614a8457600080fd5b919050565b8015158114614a6957600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614b0d57614b0d614a97565b604052919050565b600082601f830112614b2657600080fd5b813567ffffffffffffffff811115614b4057614b40614a97565b614b7160207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601614ac6565b818152846020838601011115614b8657600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060008060c08789031215614bbc57600080fd5b8635614bc781614a47565b95506020870135945060408701359350614be360608801614a6c565b92506080870135614bf381614a89565b915060a087013567ffffffffffffffff811115614c0f57600080fd5b614c1b89828a01614b15565b9150509295509295509295565b600060c08284031215614c3a57600080fd5b60405160c0810167ffffffffffffffff8282108183111715614c5e57614c5e614a97565b816040528293508435835260208501359150614c7982614a47565b81602084015260408501359150614c8f82614a47565b816040840152606085013560608401526080850135608084015260a0850135915080821115614cbd57600080fd5b50614cca85828601614b15565b60a0830152505092915050565b600080600080600085870360e0811215614cf057600080fd5b863567ffffffffffffffff80821115614d0857600080fd5b614d148a838b01614c28565b97506020890135965060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc084011215614d4d57600080fd5b60408901955060c0890135925080831115614d6757600080fd5b828901925089601f840112614d7b57600080fd5b8235915080821115614d8c57600080fd5b508860208260051b8401011115614da257600080fd5b959894975092955050506020019190565b60005b83811015614dce578181015183820152602001614db6565b838111156125115750506000910152565b60008151808452614df7816020860160208601614db3565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006129746020830184614ddf565b600060208284031215614e4e57600080fd5b5035919050565b60ff81168114614a6957600080fd5b60008060008060808587031215614e7a57600080fd5b8435614e8581614a47565b93506020850135614e9581614e55565b93969395505050506040820135916060013590565b600060208284031215614ebc57600080fd5b813567ffffffffffffffff811115614ed357600080fd5b614edf84828501614c28565b949350505050565b600060208284031215614ef957600080fd5b61297482614a6c565b60008060008060808587031215614f1857600080fd5b8435614f2381614a47565b93506020850135614f3381614a47565b92506040850135614f4381614a47565b9396929550929360600135925050565b600080600080600060a08688031215614f6b57600080fd5b8535614f7681614a47565b945060208601359350614f8b60408701614a6c565b92506060860135614f9b81614a89565b9150608086013567ffffffffffffffff811115614fb757600080fd5b614fc388828901614b15565b9150509295509295909350565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561501257615012614fd0565b500190565b60006020828403121561502957600080fd5b5051919050565b60006020828403121561504257600080fd5b815161297481614a47565b80516fffffffffffffffffffffffffffffffff81168114614a8457600080fd5b60006060828403121561507f57600080fd5b6040516060810181811067ffffffffffffffff821117156150a2576150a2614a97565b604052825181526150b56020840161504d565b60208201526150c66040840161504d565b60408201529392505050565b6000608082840312156150e457600080fd5b6040516080810181811067ffffffffffffffff8211171561510757615107614a97565b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b600067ffffffffffffffff8084111561515357615153614a97565b8360051b6020615164818301614ac6565b86815291850191818101903684111561517c57600080fd5b865b848110156151b0578035868111156151965760008081fd5b6151a236828b01614b15565b84525091830191830161517e565b50979650505050505050565b6000602082840312156151ce57600080fd5b815161297481614a89565b8581528460208201527fffffffffffffffff0000000000000000000000000000000000000000000000008460c01b16604082015282151560f81b60488201526000825161522d816049850160208701614db3565b919091016049019695505050505050565b60008282101561525057615250614fd0565b500390565b600067ffffffffffffffff8083168185168183048111821515161561527c5761527c614fd0565b02949350505050565b600067ffffffffffffffff8083168185168083038211156152a8576152a8614fd0565b01949350505050565b600080604083850312156152c457600080fd5b82516152cf81614a47565b60208401519092506152e081614e55565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082615329576153296152eb565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f80000000000000000000000000000000000000000000000000000000000000008314161561537d5761537d614fd0565b500590565b6000808312837f8000000000000000000000000000000000000000000000000000000000000000018312811516156153bc576153bc614fd0565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0183138116156153f0576153f0614fd0565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60008413600084138583048511828216161561543757615437614fd0565b7f8000000000000000000000000000000000000000000000000000000000000000600087128682058812818416161561547257615472614fd0565b6000871292508782058712848416161561548e5761548e614fd0565b878505871281841616156154a4576154a4614fd0565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038413811516156154ec576154ec614fd0565b827f800000000000000000000000000000000000000000000000000000000000000003841281161561552057615520614fd0565b50500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561555e5761555e614fd0565b500290565b600082615572576155726152eb565b500490565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a08301526155c260c0830184614ddf565b98975050505050505050565b805163ffffffff81168114614a8457600080fd5b600060c082840312156155f457600080fd5b60405160c0810181811067ffffffffffffffff8211171561561757615617614a97565b604052615623836155ce565b8152602083015161563381614e55565b6020820152604083015161564681614e55565b6040820152615657606084016155ce565b6060820152615668608084016155ce565b608082015261567960a0840161504d565b60a08201529392505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036156b6576156b6614fd0565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060ff8316806156ff576156ff6152eb565b8060ff84160691505092915050565b600060ff821660ff84168082101561572857615728614fd0565b90039392505050565b60008251615743818460208701614db3565b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea164736f6c634300080f000a"; ++ hex"6080604052600436106101635760003560e01c80638c3152e9116100c0578063b69ef8a811610074578063cff0ab9611610059578063cff0ab9614610444578063e965084c146104e5578063e9e05c421461057157600080fd5b8063b69ef8a814610401578063c0c53b8b1461042457600080fd5b80639bf62d82116100a55780639bf62d821461036b578063a14238e714610398578063a35d99df146103c857600080fd5b80638c3152e91461031e5780639b5f694a1461033e57600080fd5b806354fd4d50116101175780636dbffb78116100fc5780636dbffb78146102de57806371cfaa3f146102fe5780638b4c40b01461018857600080fd5b806354fd4d501461026d5780635c975abb146102b957600080fd5b806335e80ab31161014857806335e80ab314610206578063452a9320146102385780634870496f1461024d57600080fd5b8063149f2f221461018f57806333d7e2bd146101af57600080fd5b3661018a576101883334620186a060006040518060200160405280600081525061057f565b005b600080fd5b34801561019b57600080fd5b506101886101aa366004614c13565b610624565b3480156101bb57600080fd5b506037546101dc9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561021257600080fd5b506035546101dc90610100900473ffffffffffffffffffffffffffffffffffffffff1681565b34801561024457600080fd5b506101dc610865565b34801561025957600080fd5b50610188610268366004614d47565b6108fd565b34801561027957600080fd5b50604080518082018252600c81527f322e382e312d626574612e320000000000000000000000000000000000000000602082015290516101fd9190614e99565b3480156102c557600080fd5b506102ce610eaa565b60405190151581526020016101fd565b3480156102ea57600080fd5b506102ce6102f9366004614eac565b610f3d565b34801561030a57600080fd5b50610188610319366004614ed4565b610ff8565b34801561032a57600080fd5b50610188610339366004614f1a565b6111ba565b34801561034a57600080fd5b506036546101dc9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561037757600080fd5b506032546101dc9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156103a457600080fd5b506102ce6103b3366004614eac565b60336020526000908152604090205460ff1681565b3480156103d457600080fd5b506103e86103e3366004614f57565b611c3c565b60405167ffffffffffffffff90911681526020016101fd565b34801561040d57600080fd5b50610416611c55565b6040519081526020016101fd565b34801561043057600080fd5b5061018861043f366004614f72565b611caf565b34801561045057600080fd5b506001546104ac906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff92831660208501529116908201526060016101fd565b3480156104f157600080fd5b50610543610500366004614eac565b603460205260009081526040902080546001909101546fffffffffffffffffffffffffffffffff8082169170010000000000000000000000000000000090041683565b604080519384526fffffffffffffffffffffffffffffffff92831660208501529116908201526060016101fd565b61018861057f366004614fbd565b8260005a9050600061058f611f19565b50905073ffffffffffffffffffffffffffffffffffffffff811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee148015906105cb57503415155b15610602576040517ff2365b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610610883489898989611fb6565b5061061b8282612162565b50505050505050565b8260005a90506000610634611f19565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8216016106a6576040517f0eaf3c0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87603d60008282546106b89190615069565b90915550506040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa15801561072a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061074e9190615081565b905061077273ffffffffffffffffffffffffffffffffffffffff831633308c61242f565b61077c8982615069565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa1580156107e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061080a9190615081565b14610841576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61084f8a8a8a8a8a8a611fb6565b505061085b8282612162565b5050505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f8919061509a565b905090565b610905610eaa565b1561093c576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff16036109a5576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6036546040517fa25ae5570000000000000000000000000000000000000000000000000000000081526004810186905260009173ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa158015610a15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a3991906150d7565b519050610a53610a4e3686900386018661513c565b61250b565b8114610ae6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f7074696d69736d506f7274616c3a20696e76616c6964206f7574707574207260448201527f6f6f742070726f6f66000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000610af187612567565b6000818152603460209081526040918290208251606081018452815481526001909101546fffffffffffffffffffffffffffffffff8082169383018490527001000000000000000000000000000000009091041692810192909252919250901580610c075750805160365460408084015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff909116600482015273ffffffffffffffffffffffffffffffffffffffff9091169063a25ae55790602401606060405180830381865afa158015610bdf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c0391906150d7565b5114155b610c93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173682060448201527f68617320616c7265616479206265656e2070726f76656e0000000000000000006064820152608401610add565b60408051602081018490526000918101829052606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201209083018190529250610d5c9101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152600182527f0100000000000000000000000000000000000000000000000000000000000000602083015290610d52888a6151a2565b8a60400135612597565b610de8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a20696e76616c696420776974686472617760448201527f616c20696e636c7573696f6e2070726f6f6600000000000000000000000000006064820152608401610add565b604080516060810182528581526fffffffffffffffffffffffffffffffff42811660208084019182528c831684860190815260008981526034835286812095518655925190518416700100000000000000000000000000000000029316929092176001909301929092558b830151908c0151925173ffffffffffffffffffffffffffffffffffffffff918216939091169186917f67a6208cfcc0801d50f6cbe764733f4fddf66ac0b04442061a8a8c0cb6b63f629190a4505050505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f19573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f89190615226565b6036546040517fa25ae55700000000000000000000000000000000000000000000000000000000815260048101839052600091610ff29173ffffffffffffffffffffffffffffffffffffffff9091169063a25ae55790602401606060405180830381865afa158015610fb3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fd791906150d7565b602001516fffffffffffffffffffffffffffffffff166125bb565b92915050565b60375473ffffffffffffffffffffffffffffffffffffffff163314611049576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61105562030d40612661565b60405173ffffffffffffffffffffffffffffffffffffffff8516602482015260ff8416604482015260648101839052608481018290526000907342000000000000000000000000000000000000159073deaddeaddeaddeaddeaddeaddeaddeaddead0001907fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32908490819062030d4090829060a401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f71cfaa3f00000000000000000000000000000000000000000000000000000000179052905161117296959493929101615243565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526111aa91614e99565b60405180910390a450505050565b565b6111c2610eaa565b156111f9576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60325473ffffffffffffffffffffffffffffffffffffffff1661dead1461124c576040517f9396d15600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061125782612567565b60008181526034602090815260408083208151606081018352815481526001909101546fffffffffffffffffffffffffffffffff80821694830185905270010000000000000000000000000000000090910416918101919091529293509003611342576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206e60448201527f6f74206265656e2070726f76656e2079657400000000000000000000000000006064820152608401610add565b603660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663887862726040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113d39190615081565b81602001516fffffffffffffffffffffffffffffffff16101561149e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604b60248201527f4f7074696d69736d506f7274616c3a207769746864726177616c2074696d657360448201527f74616d70206c657373207468616e204c32204f7261636c65207374617274696e60648201527f672074696d657374616d70000000000000000000000000000000000000000000608482015260a401610add565b6114bd81602001516fffffffffffffffffffffffffffffffff166125bb565b61156f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604560248201527f4f7074696d69736d506f7274616c3a2070726f76656e2077697468647261776160448201527f6c2066696e616c697a6174696f6e20706572696f6420686173206e6f7420656c60648201527f6170736564000000000000000000000000000000000000000000000000000000608482015260a401610add565b60365460408281015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff909116600482015260009173ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa1580156115f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061161a91906150d7565b82518151919250146116d4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604960248201527f4f7074696d69736d506f7274616c3a206f757470757420726f6f742070726f7660448201527f656e206973206e6f74207468652073616d652061732063757272656e74206f7560648201527f7470757420726f6f740000000000000000000000000000000000000000000000608482015260a401610add565b6116f381602001516fffffffffffffffffffffffffffffffff166125bb565b6117a5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f4f7074696d69736d506f7274616c3a206f75747075742070726f706f73616c2060448201527f66696e616c697a6174696f6e20706572696f6420686173206e6f7420656c617060648201527f7365640000000000000000000000000000000000000000000000000000000000608482015260a401610add565b60008381526033602052604090205460ff1615611844576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206160448201527f6c7265616479206265656e2066696e616c697a656400000000000000000000006064820152608401610add565b6000838152603360209081526040822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558501516032805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff0000000000000000000000000000000000000000909216919091179055806118cf611f19565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8216016119325761192b8660400151876080015188606001518960a001516126c3565b9150611b85565b8073ffffffffffffffffffffffffffffffffffffffff16866040015173ffffffffffffffffffffffffffffffffffffffff160361199b576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606086015115611b5c578560600151603d60008282546119bb91906152a8565b90915550506040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015611a2d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a519190615081565b9050611a86876040015188606001518473ffffffffffffffffffffffffffffffffffffffff166127219092919063ffffffff16565b6060870151611a9590826152a8565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa158015611aff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b239190615081565b14611b5a576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b60a08601515115611b805761192b8660400151876080015160008960a001516126c3565b600191505b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405185907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b90611be790851515815260200190565b60405180910390a281158015611bfd5750326001145b15611c34576040517feeae4ed300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000611c498260106152bf565b610ff2906152086152ef565b600080611c60611f19565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff821601611ca7574791505090565b5050603d5490565b600054610100900460ff1615808015611ccf5750600054600160ff909116105b80611ce95750303b158015611ce9575060005460ff166001145b611d75576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610add565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015611dd357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603680547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff8781169190911790925560378054909116858316179055603580547fffffffffffffffffffffff0000000000000000000000000000000000000000ff166101008584160217905560325416611e8c57603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790555b611e9461277c565b8015611ef757600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b603754604080517f4397dfef0000000000000000000000000000000000000000000000000000000081528151600093849373ffffffffffffffffffffffffffffffffffffffff90911692634397dfef92600480830193928290030181865afa158015611f89573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fad919061531b565b90939092509050565b818015611fd8575073ffffffffffffffffffffffffffffffffffffffff861615155b1561200f576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6120198151611c3c565b67ffffffffffffffff168367ffffffffffffffff161015612066576040517f4929b80800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6201d4c0815111156120a4576040517f73052b0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b333281146120c5575033731111000000000000000000000000000000001111015b600086868686866040516020016120e0959493929190615243565b604051602081830303815290604052905060008873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32846040516121509190614e99565b60405180910390a45050505050505050565b600154600090612198907801000000000000000000000000000000000000000000000000900467ffffffffffffffff16436152a8565b905060006121a461288f565b90506000816020015160ff16826000015163ffffffff166121c59190615384565b905082156122fc576001546000906121fc908390700100000000000000000000000000000000900467ffffffffffffffff166153ec565b90506000836040015160ff16836122139190615460565b6001546122339084906fffffffffffffffffffffffffffffffff16615460565b61223d9190615384565b60015490915060009061228e906122679084906fffffffffffffffffffffffffffffffff1661551c565b866060015163ffffffff168760a001516fffffffffffffffffffffffffffffffff166129cc565b905060018611156122bd576122ba61226782876040015160ff1660018a6122b591906152a8565b6129eb565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760015550505b6001805486919060109061232f908490700100000000000000000000000000000000900467ffffffffffffffff166152ef565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550816000015163ffffffff16600160000160109054906101000a900467ffffffffffffffff1667ffffffffffffffff1613156123bc576040517f77ebef4d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001546000906123e8906fffffffffffffffffffffffffffffffff1667ffffffffffffffff8816615590565b905060006123fa48633b9aca00612a40565b61240490836155cd565b905060005a61241390886152a8565b90508082111561085b5761085b61242a82846152a8565b612a57565b60405173ffffffffffffffffffffffffffffffffffffffff80851660248301528316604482015260648101829052611ef79085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152612a80565b6000816000015182602001518360400151846060015160405160200161254a949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b80516020808301516040808501516060860151608087015160a0880151935160009761254a9790969591016155e1565b6000806125a386612b8c565b90506125b181868686612bbe565b9695505050505050565b603654604080517ff4daa291000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163f4daa2919160048083019260209291908290030181865afa15801561262b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061264f9190615081565b6126599083615069565b421192915050565b6001805463ffffffff8316919060109061269a908490700100000000000000000000000000000000900467ffffffffffffffff166152ef565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555050565b60008060006126d3866000612bee565b905080612709576308c379a06000526020805278185361666543616c6c3a204e6f7420656e6f756768206761736058526064601cfd5b600080855160208701888b5af1979650505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526127779084907fa9059cbb0000000000000000000000000000000000000000000000000000000090606401612489565b505050565b600054610100900460ff16612813576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610add565b6001547801000000000000000000000000000000000000000000000000900467ffffffffffffffff166000036111b85760408051606081018252633b9aca00808252600060208301524367ffffffffffffffff169190920181905278010000000000000000000000000000000000000000000000000217600155565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152603754604080517fcc731b02000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163cc731b029160048083019260c09291908290030181865afa158015612931573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612955919061564c565b90506040518060c00160405280826000015163ffffffff168152602001826020015160ff168152602001826040015160ff168152602001826060015163ffffffff168152602001826080015163ffffffff1681526020018260a001516fffffffffffffffffffffffffffffffff1681525091505090565b60006129e16129db8585612c0c565b83612c1c565b90505b9392505050565b6000670de0b6b3a7640000612a2c612a038583615384565b612a1590670de0b6b3a76400006153ec565b612a2785670de0b6b3a7640000615460565b612c2b565b612a369086615460565b6129e19190615384565b600081831015612a5057816129e4565b5090919050565b6000805a90505b825a612a6a90836152a8565b101561277757612a79826156ef565b9150612a5e565b6000612ae2826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612c5c9092919063ffffffff16565b8051909150156127775780806020019051810190612b009190615226565b612777576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610add565b60608180519060200120604051602001612ba891815260200190565b6040516020818303038152906040529050919050565b6000612be584612bcf878686612c6b565b8051602091820120825192909101919091201490565b95945050505050565b600080603f83619c4001026040850201603f5a021015949350505050565b600081831215612a5057816129e4565b6000818312612a5057816129e4565b60006129e4670de0b6b3a764000083612c43866136e9565b612c4d9190615460565b612c579190615384565b61392d565b60606129e18484600085613b6c565b60606000845111612cd8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4d65726b6c65547269653a20656d707479206b657900000000000000000000006044820152606401610add565b6000612ce384613d02565b90506000612cf086613dee565b9050600084604051602001612d0791815260200190565b60405160208183030381529060405290506000805b8451811015613660576000858281518110612d3957612d39615727565b602002602001015190508451831115612dd4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4d65726b6c65547269653a206b657920696e646578206578636565647320746f60448201527f74616c206b6579206c656e6774680000000000000000000000000000000000006064820152608401610add565b82600003612e8d5780518051602091820120604051612e2292612dfc92910190815260200190565b604051602081830303815290604052858051602091820120825192909101919091201490565b612e88576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4d65726b6c65547269653a20696e76616c696420726f6f7420686173680000006044820152606401610add565b612fe4565b805151602011612f435780518051602091820120604051612eb792612dfc92910190815260200190565b612e88576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d65726b6c65547269653a20696e76616c6964206c6172676520696e7465726e60448201527f616c2068617368000000000000000000000000000000000000000000000000006064820152608401610add565b805184516020808701919091208251919092012014612fe4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4d65726b6c65547269653a20696e76616c696420696e7465726e616c206e6f6460448201527f65206861736800000000000000000000000000000000000000000000000000006064820152608401610add565b612ff060106001615069565b816020015151036131cc57845183036131645761302a816020015160108151811061301d5761301d615727565b6020026020010151613e51565b965060008751116130bd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603b60248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286272616e63682900000000006064820152608401610add565b600186516130cb91906152a8565b8214613159576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286272616e6368290000000000006064820152608401610add565b5050505050506129e4565b600085848151811061317857613178615727565b602001015160f81c60f81b60f81c9050600082602001518260ff16815181106131a3576131a3615727565b602002602001015190506131b681613f05565b95506131c3600186615069565b9450505061364d565b6002816020015151036135c55760006131e482613f2a565b90506000816000815181106131fb576131fb615727565b016020015160f81c90506000613212600283615756565b61321d906002615778565b9050600061322e848360ff16613f4e565b9050600061323c8a89613f4e565b9050600061324a8383613f84565b9050808351146132dc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a20706174682072656d61696e646572206d7573742060448201527f736861726520616c6c206e6962626c65732077697468206b65790000000000006064820152608401610add565b60ff8516600214806132f1575060ff85166003145b156134e05780825114613386576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f4d65726b6c65547269653a206b65792072656d61696e646572206d757374206260448201527f65206964656e746963616c20746f20706174682072656d61696e6465720000006064820152608401610add565b6133a0876020015160018151811061301d5761301d615727565b9c5060008d5111613433576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286c65616629000000000000006064820152608401610add565b60018c5161344191906152a8565b88146134cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286c6561662900000000000000006064820152608401610add565b5050505050505050505050506129e4565b60ff851615806134f3575060ff85166001145b156135325761351f876020015160018151811061351257613512615727565b6020026020010151613f05565b995061352b818a615069565b98506135ba565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4d65726b6c65547269653a2072656365697665642061206e6f6465207769746860448201527f20616e20756e6b6e6f776e2070726566697800000000000000000000000000006064820152608401610add565b50505050505061364d565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4d65726b6c65547269653a20726563656976656420616e20756e70617273656160448201527f626c65206e6f64650000000000000000000000000000000000000000000000006064820152608401610add565b5080613658816156ef565b915050612d1c565b506040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4d65726b6c65547269653a2072616e206f7574206f662070726f6f6620656c6560448201527f6d656e74730000000000000000000000000000000000000000000000000000006064820152608401610add565b6000808213613754576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401610add565b6000606061376184614038565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c1821361395e57506000919050565b680755bf798b4a1bf1e582126139d0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4558505f4f564552464c4f5700000000000000000000000000000000000000006044820152606401610add565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b606082471015613bfe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610add565b73ffffffffffffffffffffffffffffffffffffffff85163b613c7c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610add565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051613ca5919061579b565b60006040518083038185875af1925050503d8060008114613ce2576040519150601f19603f3d011682016040523d82523d6000602084013e613ce7565b606091505b5091509150613cf782828661410e565b979650505050505050565b80516060908067ffffffffffffffff811115613d2057613d20614b07565b604051908082528060200260200182016040528015613d6557816020015b6040805180820190915260608082526020820152815260200190600190039081613d3e5790505b50915060005b81811015613de7576040518060400160405280858381518110613d9057613d90615727565b60200260200101518152602001613dbf868481518110613db257613db2615727565b6020026020010151614161565b815250838281518110613dd457613dd4615727565b6020908102919091010152600101613d6b565b5050919050565b606080604051905082518060011b603f8101601f1916830160405280835250602084016020830160005b83811015613e46578060011b82018184015160001a8060041c8253600f811660018301535050600101613e18565b509295945050505050565b60606000806000613e6185614174565b919450925090506000816001811115613e7c57613e7c6157b7565b14613eb3576040517f1ff9b2e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613ebd8284615069565b855114613ef6576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612be585602001518484614612565b60606020826000015110613f2157613f1c82613e51565b610ff2565b610ff2826146a6565b6060610ff2613f49836020015160008151811061301d5761301d615727565b613dee565b606082518210613f6d5750604080516020810190915260008152610ff2565b6129e48383848651613f7f91906152a8565b6146bc565b6000808251845110613f97578251613f9a565b83515b90505b80821080156140215750828281518110613fb957613fb9615727565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916848381518110613ff857613ff8615727565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b1561403157816001019150613f9d565b5092915050565b60008082116140a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401610add565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b6060831561411d5750816129e4565b82511561412d5782518084602001fd5b816040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610add9190614e99565b6060610ff261416f83614894565b614901565b600080600083600001516000036141b7576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020840151805160001a607f81116141dc57600060016000945094509450505061460b565b60b781116142f25760006141f16080836152a8565b905080876000015111614230576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001838101517fff000000000000000000000000000000000000000000000000000000000000001690821480156142a857507f80000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000008216105b156142df576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506001955093506000925061460b915050565b60bf811161445057600061430760b7836152a8565b905080876000015111614346576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff000000000000000000000000000000000000000000000000000000000000001660008190036143a8576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c603781116143f0576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6143fa8184615069565b895111614433576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61443e836001615069565b975095506000945061460b9350505050565b60f781116144b557600061446560c0836152a8565b9050808760000151116144a4576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60019550935084925061460b915050565b60006144c260f7836152a8565b905080876000015111614501576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614563576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c603781116145ab576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6145b58184615069565b8951116145ee576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6145f9836001615069565b975095506001945061460b9350505050565b9193909250565b60608167ffffffffffffffff81111561462d5761462d614b07565b6040519080825280601f01601f191660200182016040528015614657576020820181803683370190505b50905081156129e457600061466c8486615069565b90506020820160005b8481101561468d578281015182820152602001614675565b8481111561469c576000858301525b5050509392505050565b6060610ff2826020015160008460000151614612565b60608182601f01101561472b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610add565b828284011015614797576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610add565b81830184511015614804576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401610add565b606082158015614823576040519150600082526020820160405261488b565b6040519150601f8416801560200281840101858101878315602002848b0101015b8183101561485c578051835260209283019201614844565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b604080518082019091526000808252602082015281516000036148e3576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50604080518082019091528151815260209182019181019190915290565b6060600080600061491185614174565b91945092509050600181600181111561492c5761492c6157b7565b14614963576040517f4b9c6abe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845161496f8385615069565b146149a6576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516020808252610420820190925290816020015b60408051808201909152600080825260208201528152602001906001900390816149bd5790505093506000835b8651811015614aab57600080614a306040518060400160405280858c60000151614a1491906152a8565b8152602001858c60200151614a299190615069565b9052614174565b509150915060405180604001604052808383614a4c9190615069565b8152602001848b60200151614a619190615069565b815250888581518110614a7657614a76615727565b6020908102919091010152614a8c600185615069565b9350614a988183615069565b614aa29084615069565b925050506149ea565b50845250919392505050565b73ffffffffffffffffffffffffffffffffffffffff81168114614ad957600080fd5b50565b803567ffffffffffffffff81168114614af457600080fd5b919050565b8015158114614ad957600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614b7d57614b7d614b07565b604052919050565b600082601f830112614b9657600080fd5b813567ffffffffffffffff811115614bb057614bb0614b07565b614be160207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601614b36565b818152846020838601011115614bf657600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060008060c08789031215614c2c57600080fd5b8635614c3781614ab7565b95506020870135945060408701359350614c5360608801614adc565b92506080870135614c6381614af9565b915060a087013567ffffffffffffffff811115614c7f57600080fd5b614c8b89828a01614b85565b9150509295509295509295565b600060c08284031215614caa57600080fd5b60405160c0810167ffffffffffffffff8282108183111715614cce57614cce614b07565b816040528293508435835260208501359150614ce982614ab7565b81602084015260408501359150614cff82614ab7565b816040840152606085013560608401526080850135608084015260a0850135915080821115614d2d57600080fd5b50614d3a85828601614b85565b60a0830152505092915050565b600080600080600085870360e0811215614d6057600080fd5b863567ffffffffffffffff80821115614d7857600080fd5b614d848a838b01614c98565b97506020890135965060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc084011215614dbd57600080fd5b60408901955060c0890135925080831115614dd757600080fd5b828901925089601f840112614deb57600080fd5b8235915080821115614dfc57600080fd5b508860208260051b8401011115614e1257600080fd5b959894975092955050506020019190565b60005b83811015614e3e578181015183820152602001614e26565b83811115611ef75750506000910152565b60008151808452614e67816020860160208601614e23565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006129e46020830184614e4f565b600060208284031215614ebe57600080fd5b5035919050565b60ff81168114614ad957600080fd5b60008060008060808587031215614eea57600080fd5b8435614ef581614ab7565b93506020850135614f0581614ec5565b93969395505050506040820135916060013590565b600060208284031215614f2c57600080fd5b813567ffffffffffffffff811115614f4357600080fd5b614f4f84828501614c98565b949350505050565b600060208284031215614f6957600080fd5b6129e482614adc565b600080600060608486031215614f8757600080fd5b8335614f9281614ab7565b92506020840135614fa281614ab7565b91506040840135614fb281614ab7565b809150509250925092565b600080600080600060a08688031215614fd557600080fd5b8535614fe081614ab7565b945060208601359350614ff560408701614adc565b9250606086013561500581614af9565b9150608086013567ffffffffffffffff81111561502157600080fd5b61502d88828901614b85565b9150509295509295909350565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561507c5761507c61503a565b500190565b60006020828403121561509357600080fd5b5051919050565b6000602082840312156150ac57600080fd5b81516129e481614ab7565b80516fffffffffffffffffffffffffffffffff81168114614af457600080fd5b6000606082840312156150e957600080fd5b6040516060810181811067ffffffffffffffff8211171561510c5761510c614b07565b6040528251815261511f602084016150b7565b6020820152615130604084016150b7565b60408201529392505050565b60006080828403121561514e57600080fd5b6040516080810181811067ffffffffffffffff8211171561517157615171614b07565b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b600067ffffffffffffffff808411156151bd576151bd614b07565b8360051b60206151ce818301614b36565b8681529185019181810190368411156151e657600080fd5b865b8481101561521a578035868111156152005760008081fd5b61520c36828b01614b85565b8452509183019183016151e8565b50979650505050505050565b60006020828403121561523857600080fd5b81516129e481614af9565b8581528460208201527fffffffffffffffff0000000000000000000000000000000000000000000000008460c01b16604082015282151560f81b604882015260008251615297816049850160208701614e23565b919091016049019695505050505050565b6000828210156152ba576152ba61503a565b500390565b600067ffffffffffffffff808316818516818304811182151516156152e6576152e661503a565b02949350505050565b600067ffffffffffffffff8083168185168083038211156153125761531261503a565b01949350505050565b6000806040838503121561532e57600080fd5b825161533981614ab7565b602084015190925061534a81614ec5565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261539357615393615355565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f8000000000000000000000000000000000000000000000000000000000000000831416156153e7576153e761503a565b500590565b6000808312837f8000000000000000000000000000000000000000000000000000000000000000018312811516156154265761542661503a565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01831381161561545a5761545a61503a565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6000841360008413858304851182821616156154a1576154a161503a565b7f800000000000000000000000000000000000000000000000000000000000000060008712868205881281841616156154dc576154dc61503a565b600087129250878205871284841616156154f8576154f861503a565b8785058712818416161561550e5761550e61503a565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038413811516156155565761555661503a565b827f800000000000000000000000000000000000000000000000000000000000000003841281161561558a5761558a61503a565b50500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156155c8576155c861503a565b500290565b6000826155dc576155dc615355565b500490565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a083015261562c60c0830184614e4f565b98975050505050505050565b805163ffffffff81168114614af457600080fd5b600060c0828403121561565e57600080fd5b60405160c0810181811067ffffffffffffffff8211171561568157615681614b07565b60405261568d83615638565b8152602083015161569d81614ec5565b602082015260408301516156b081614ec5565b60408201526156c160608401615638565b60608201526156d260808401615638565b60808201526156e360a084016150b7565b60a08201529392505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036157205761572061503a565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060ff83168061576957615769615355565b8060ff84160691505092915050565b600060ff821660ff8416808210156157925761579261503a565b90039392505050565b600082516157ad818460208701614e23565b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea164736f6c634300080f000a"; bytes internal constant l2OutputOracleCode = - hex"60806040526004361061018a5760003560e01c806389c44cbb116100d6578063ce5db8d61161007f578063dcec334811610059578063dcec33481461049b578063e1a41bcf146104b0578063f4daa291146104c657600080fd5b8063ce5db8d614610445578063cf8e5cf01461045b578063d1de856c1461047b57600080fd5b8063a25ae557116100b0578063a25ae55714610391578063a8e4fb90146103ed578063bffa7f0f1461041a57600080fd5b806389c44cbb1461034857806393991af3146103685780639aaab6481461037e57600080fd5b806369f16eec1161013857806370872aa51161011257806370872aa5146102fc5780637f00642014610312578063887862721461033257600080fd5b806369f16eec146102a75780636abcf563146102bc5780636b4d98dd146102d157600080fd5b8063529933df11610169578063529933df146101ea578063534db0e2146101ff57806354fd4d501461025157600080fd5b80622134cc1461018f5780631c89c97d146101b35780634599c788146101d5575b600080fd5b34801561019b57600080fd5b506005545b6040519081526020015b60405180910390f35b3480156101bf57600080fd5b506101d36101ce3660046113a2565b6104db565b005b3480156101e157600080fd5b506101a06108b6565b3480156101f657600080fd5b506004546101a0565b34801561020b57600080fd5b5060065461022c9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101aa565b34801561025d57600080fd5b5061029a6040518060400160405280600581526020017f312e382e3000000000000000000000000000000000000000000000000000000081525081565b6040516101aa9190611405565b3480156102b357600080fd5b506101a0610929565b3480156102c857600080fd5b506003546101a0565b3480156102dd57600080fd5b5060065473ffffffffffffffffffffffffffffffffffffffff1661022c565b34801561030857600080fd5b506101a060015481565b34801561031e57600080fd5b506101a061032d366004611478565b61093b565b34801561033e57600080fd5b506101a060025481565b34801561035457600080fd5b506101d3610363366004611478565b610b4f565b34801561037457600080fd5b506101a060055481565b6101d361038c366004611491565b610de9565b34801561039d57600080fd5b506103b16103ac366004611478565b61124a565b60408051825181526020808401516fffffffffffffffffffffffffffffffff9081169183019190915292820151909216908201526060016101aa565b3480156103f957600080fd5b5060075461022c9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561042657600080fd5b5060075473ffffffffffffffffffffffffffffffffffffffff1661022c565b34801561045157600080fd5b506101a060085481565b34801561046757600080fd5b506103b1610476366004611478565b6112de565b34801561048757600080fd5b506101a0610496366004611478565b611316565b3480156104a757600080fd5b506101a0611346565b3480156104bc57600080fd5b506101a060045481565b3480156104d257600080fd5b506008546101a0565b600054610100900460ff16158080156104fb5750600054600160ff909116105b806105155750303b158015610515575060005460ff166001145b6105a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561060457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b60008811610694576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4c324f75747075744f7261636c653a207375626d697373696f6e20696e74657260448201527f76616c206d7573742062652067726561746572207468616e2030000000000000606482015260840161059d565b60008711610724576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4c324f75747075744f7261636c653a204c3220626c6f636b2074696d65206d7560448201527f73742062652067726561746572207468616e2030000000000000000000000000606482015260840161059d565b428511156107db576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526044602482018190527f4c324f75747075744f7261636c653a207374617274696e67204c322074696d65908201527f7374616d70206d757374206265206c657373207468616e2063757272656e742060648201527f74696d6500000000000000000000000000000000000000000000000000000000608482015260a40161059d565b60048890556005879055600186905560028590556007805473ffffffffffffffffffffffffffffffffffffffff8087167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179092556006805492861692909116919091179055600882905580156108ac57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b6003546000901561092057600380546108d1906001906114f2565b815481106108e1576108e1611509565b600091825260209091206002909102016001015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16919050565b6001545b905090565b600354600090610924906001906114f2565b60006109456108b6565b8211156109fa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f4c324f75747075744f7261636c653a2063616e6e6f7420676574206f7574707560448201527f7420666f72206120626c6f636b207468617420686173206e6f74206265656e2060648201527f70726f706f736564000000000000000000000000000000000000000000000000608482015260a40161059d565b600354610aaf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f4c324f75747075744f7261636c653a2063616e6e6f7420676574206f7574707560448201527f74206173206e6f206f7574707574732068617665206265656e2070726f706f7360648201527f6564207965740000000000000000000000000000000000000000000000000000608482015260a40161059d565b6003546000905b80821015610b485760006002610acc8385611538565b610ad69190611550565b90508460038281548110610aec57610aec611509565b600091825260209091206002909102016001015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff161015610b3e57610b37816001611538565b9250610b42565b8091505b50610ab6565b5092915050565b60065473ffffffffffffffffffffffffffffffffffffffff163314610bf6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f4c324f75747075744f7261636c653a206f6e6c7920746865206368616c6c656e60448201527f67657220616464726573732063616e2064656c657465206f7574707574730000606482015260840161059d565b6003548110610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f4c324f75747075744f7261636c653a2063616e6e6f742064656c657465206f7560448201527f747075747320616674657220746865206c6174657374206f757470757420696e60648201527f6465780000000000000000000000000000000000000000000000000000000000608482015260a40161059d565b60085460038281548110610cc357610cc3611509565b6000918252602090912060016002909202010154610cf3906fffffffffffffffffffffffffffffffff16426114f2565b10610da6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f4c324f75747075744f7261636c653a2063616e6e6f742064656c657465206f7560448201527f74707574732074686174206861766520616c7265616479206265656e2066696e60648201527f616c697a65640000000000000000000000000000000000000000000000000000608482015260a40161059d565b6000610db160035490565b90508160035581817f4ee37ac2c786ec85e87592d3c5c8a1dd66f8496dda3f125d9ea8ca5f657629b660405160405180910390a35050565b60075473ffffffffffffffffffffffffffffffffffffffff163314610eb6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f4c324f75747075744f7261636c653a206f6e6c79207468652070726f706f736560448201527f7220616464726573732063616e2070726f706f7365206e6577206f757470757460648201527f7300000000000000000000000000000000000000000000000000000000000000608482015260a40161059d565b610ebe611346565b8314610f72576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f4c324f75747075744f7261636c653a20626c6f636b206e756d626572206d757360448201527f7420626520657175616c20746f206e65787420657870656374656420626c6f6360648201527f6b206e756d626572000000000000000000000000000000000000000000000000608482015260a40161059d565b42610f7c84611316565b10611009576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f4c324f75747075744f7261636c653a2063616e6e6f742070726f706f7365204c60448201527f32206f757470757420696e207468652066757475726500000000000000000000606482015260840161059d565b83611096576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4c324f75747075744f7261636c653a204c32206f75747075742070726f706f7360448201527f616c2063616e6e6f7420626520746865207a65726f2068617368000000000000606482015260840161059d565b81156111525781814014611152576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604960248201527f4c324f75747075744f7261636c653a20626c6f636b206861736820646f65732060448201527f6e6f74206d61746368207468652068617368206174207468652065787065637460648201527f6564206865696768740000000000000000000000000000000000000000000000608482015260a40161059d565b8261115c60035490565b857fa7aaf2512769da4e444e3de247be2564225c2e7a8f74cfe528e46e17d24868e24260405161118e91815260200190565b60405180910390a45050604080516060810182529283526fffffffffffffffffffffffffffffffff4281166020850190815292811691840191825260038054600181018255600091909152935160029094027fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b810194909455915190518216700100000000000000000000000000000000029116177fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85c90910155565b60408051606081018252600080825260208201819052918101919091526003828154811061127a5761127a611509565b600091825260209182902060408051606081018252600290930290910180548352600101546fffffffffffffffffffffffffffffffff8082169484019490945270010000000000000000000000000000000090049092169181019190915292915050565b604080516060810182526000808252602082018190529181019190915260036113068361093b565b8154811061127a5761127a611509565b60006005546001548361132991906114f2565b611333919061158b565b6002546113409190611538565b92915050565b60006004546113536108b6565b6109249190611538565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b803573ffffffffffffffffffffffffffffffffffffffff8116811461139d57600080fd5b919050565b600080600080600080600060e0888a0312156113bd57600080fd5b873596506020880135955060408801359450606088013593506113e260808901611379565b92506113f060a08901611379565b915060c0880135905092959891949750929550565b600060208083528351808285015260005b8181101561143257858101830151858201604001528201611416565b81811115611444576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b60006020828403121561148a57600080fd5b5035919050565b600080600080608085870312156114a757600080fd5b5050823594602084013594506040840135936060013592509050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015611504576115046114c3565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000821982111561154b5761154b6114c3565b500190565b600082611586577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156115c3576115c36114c3565b50029056fea164736f6c634300080f000a"; - bytes internal constant optimismPortal2Code =
+- hex"60806040526004361061018a5760003560e01c806389c44cbb116100d6578063ce5db8d61161007f578063dcec334811610059578063dcec33481461049b578063e1a41bcf146104b0578063f4daa291146104c657600080fd5b8063ce5db8d614610445578063cf8e5cf01461045b578063d1de856c1461047b57600080fd5b8063a25ae557116100b0578063a25ae55714610391578063a8e4fb90146103ed578063bffa7f0f1461041a57600080fd5b806389c44cbb1461034857806393991af3146103685780639aaab6481461037e57600080fd5b806369f16eec1161013857806370872aa51161011257806370872aa5146102fc5780637f00642014610312578063887862721461033257600080fd5b806369f16eec146102a75780636abcf563146102bc5780636b4d98dd146102d157600080fd5b8063529933df11610169578063529933df146101ea578063534db0e2146101ff57806354fd4d501461025157600080fd5b80622134cc1461018f5780631c89c97d146101b35780634599c788146101d5575b600080fd5b34801561019b57600080fd5b506005545b6040519081526020015b60405180910390f35b3480156101bf57600080fd5b506101d36101ce3660046113a2565b6104db565b005b3480156101e157600080fd5b506101a06108b6565b3480156101f657600080fd5b506004546101a0565b34801561020b57600080fd5b5060065461022c9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101aa565b34801561025d57600080fd5b5061029a6040518060400160405280600581526020017f312e382e3000000000000000000000000000000000000000000000000000000081525081565b6040516101aa9190611405565b3480156102b357600080fd5b506101a0610929565b3480156102c857600080fd5b506003546101a0565b3480156102dd57600080fd5b5060065473ffffffffffffffffffffffffffffffffffffffff1661022c565b34801561030857600080fd5b506101a060015481565b34801561031e57600080fd5b506101a061032d366004611478565b61093b565b34801561033e57600080fd5b506101a060025481565b34801561035457600080fd5b506101d3610363366004611478565b610b4f565b34801561037457600080fd5b506101a060055481565b6101d361038c366004611491565b610de9565b34801561039d57600080fd5b506103b16103ac366004611478565b61124a565b60408051825181526020808401516fffffffffffffffffffffffffffffffff9081169183019190915292820151909216908201526060016101aa565b3480156103f957600080fd5b5060075461022c9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561042657600080fd5b5060075473ffffffffffffffffffffffffffffffffffffffff1661022c565b34801561045157600080fd5b506101a060085481565b34801561046757600080fd5b506103b1610476366004611478565b6112de565b34801561048757600080fd5b506101a0610496366004611478565b611316565b3480156104a757600080fd5b506101a0611346565b3480156104bc57600080fd5b506101a060045481565b3480156104d257600080fd5b506008546101a0565b600054610100900460ff16158080156104fb5750600054600160ff909116105b806105155750303b158015610515575060005460ff166001145b6105a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561060457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b60008811610694576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4c324f75747075744f7261636c653a207375626d697373696f6e20696e74657260448201527f76616c206d7573742062652067726561746572207468616e2030000000000000606482015260840161059d565b60008711610724576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4c324f75747075744f7261636c653a204c3220626c6f636b2074696d65206d7560448201527f73742062652067726561746572207468616e2030000000000000000000000000606482015260840161059d565b428511156107db576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526044602482018190527f4c324f75747075744f7261636c653a207374617274696e67204c322074696d65908201527f7374616d70206d757374206265206c657373207468616e2063757272656e742060648201527f74696d6500000000000000000000000000000000000000000000000000000000608482015260a40161059d565b60048890556005879055600186905560028590556007805473ffffffffffffffffffffffffffffffffffffffff8087167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179092556006805492861692909116919091179055600882905580156108ac57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b6003546000901561092057600380546108d1906001906114f2565b815481106108e1576108e1611509565b600091825260209091206002909102016001015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16919050565b6001545b905090565b600354600090610924906001906114f2565b60006109456108b6565b8211156109fa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f4c324f75747075744f7261636c653a2063616e6e6f7420676574206f7574707560448201527f7420666f72206120626c6f636b207468617420686173206e6f74206265656e2060648201527f70726f706f736564000000000000000000000000000000000000000000000000608482015260a40161059d565b600354610aaf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f4c324f75747075744f7261636c653a2063616e6e6f7420676574206f7574707560448201527f74206173206e6f206f7574707574732068617665206265656e2070726f706f7360648201527f6564207965740000000000000000000000000000000000000000000000000000608482015260a40161059d565b6003546000905b80821015610b485760006002610acc8385611538565b610ad69190611550565b90508460038281548110610aec57610aec611509565b600091825260209091206002909102016001015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff161015610b3e57610b37816001611538565b9250610b42565b8091505b50610ab6565b5092915050565b60065473ffffffffffffffffffffffffffffffffffffffff163314610bf6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f4c324f75747075744f7261636c653a206f6e6c7920746865206368616c6c656e60448201527f67657220616464726573732063616e2064656c657465206f7574707574730000606482015260840161059d565b6003548110610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f4c324f75747075744f7261636c653a2063616e6e6f742064656c657465206f7560448201527f747075747320616674657220746865206c6174657374206f757470757420696e60648201527f6465780000000000000000000000000000000000000000000000000000000000608482015260a40161059d565b60085460038281548110610cc357610cc3611509565b6000918252602090912060016002909202010154610cf3906fffffffffffffffffffffffffffffffff16426114f2565b10610da6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f4c324f75747075744f7261636c653a2063616e6e6f742064656c657465206f7560448201527f74707574732074686174206861766520616c7265616479206265656e2066696e60648201527f616c697a65640000000000000000000000000000000000000000000000000000608482015260a40161059d565b6000610db160035490565b90508160035581817f4ee37ac2c786ec85e87592d3c5c8a1dd66f8496dda3f125d9ea8ca5f657629b660405160405180910390a35050565b60075473ffffffffffffffffffffffffffffffffffffffff163314610eb6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f4c324f75747075744f7261636c653a206f6e6c79207468652070726f706f736560448201527f7220616464726573732063616e2070726f706f7365206e6577206f757470757460648201527f7300000000000000000000000000000000000000000000000000000000000000608482015260a40161059d565b610ebe611346565b8314610f72576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f4c324f75747075744f7261636c653a20626c6f636b206e756d626572206d757360448201527f7420626520657175616c20746f206e65787420657870656374656420626c6f6360648201527f6b206e756d626572000000000000000000000000000000000000000000000000608482015260a40161059d565b42610f7c84611316565b10611009576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f4c324f75747075744f7261636c653a2063616e6e6f742070726f706f7365204c60448201527f32206f757470757420696e207468652066757475726500000000000000000000606482015260840161059d565b83611096576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4c324f75747075744f7261636c653a204c32206f75747075742070726f706f7360448201527f616c2063616e6e6f7420626520746865207a65726f2068617368000000000000606482015260840161059d565b81156111525781814014611152576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604960248201527f4c324f75747075744f7261636c653a20626c6f636b206861736820646f65732060448201527f6e6f74206d61746368207468652068617368206174207468652065787065637460648201527f6564206865696768740000000000000000000000000000000000000000000000608482015260a40161059d565b8261115c60035490565b857fa7aaf2512769da4e444e3de247be2564225c2e7a8f74cfe528e46e17d24868e24260405161118e91815260200190565b60405180910390a45050604080516060810182529283526fffffffffffffffffffffffffffffffff4281166020850190815292811691840191825260038054600181018255600091909152935160029094027fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b810194909455915190518216700100000000000000000000000000000000029116177fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85c90910155565b60408051606081018252600080825260208201819052918101919091526003828154811061127a5761127a611509565b600091825260209182902060408051606081018252600290930290910180548352600101546fffffffffffffffffffffffffffffffff8082169484019490945270010000000000000000000000000000000090049092169181019190915292915050565b604080516060810182526000808252602082018190529181019190915260036113068361093b565b8154811061127a5761127a611509565b60006005546001548361132991906114f2565b611333919061158b565b6002546113409190611538565b92915050565b60006004546113536108b6565b6109249190611538565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b803573ffffffffffffffffffffffffffffffffffffffff8116811461139d57600080fd5b919050565b600080600080600080600060e0888a0312156113bd57600080fd5b873596506020880135955060408801359450606088013593506113e260808901611379565b92506113f060a08901611379565b915060c0880135905092959891949750929550565b600060208083528351808285015260005b8181101561143257858101830151858201604001528201611416565b81811115611444576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b60006020828403121561148a57600080fd5b5035919050565b600080600080608085870312156114a757600080fd5b5050823594602084013594506040840135936060013592509050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015611504576115046114c3565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000821982111561154b5761154b6114c3565b500190565b600082611586577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156115c3576115c36114c3565b50029056fea164736f6c634300080f000a"; ++ hex"60806040526004361061018a5760003560e01c806389c44cbb116100d6578063ce5db8d61161007f578063dcec334811610059578063dcec33481461049b578063e1a41bcf146104b0578063f4daa291146104c657600080fd5b8063ce5db8d614610445578063cf8e5cf01461045b578063d1de856c1461047b57600080fd5b8063a25ae557116100b0578063a25ae55714610391578063a8e4fb90146103ed578063bffa7f0f1461041a57600080fd5b806389c44cbb1461034857806393991af3146103685780639aaab6481461037e57600080fd5b806369f16eec1161013857806370872aa51161011257806370872aa5146102fc5780637f00642014610312578063887862721461033257600080fd5b806369f16eec146102a75780636abcf563146102bc5780636b4d98dd146102d157600080fd5b8063529933df11610169578063529933df146101ea578063534db0e2146101ff57806354fd4d501461025157600080fd5b80622134cc1461018f5780631c89c97d146101b35780634599c788146101d5575b600080fd5b34801561019b57600080fd5b506005545b6040519081526020015b60405180910390f35b3480156101bf57600080fd5b506101d36101ce3660046113a2565b6104db565b005b3480156101e157600080fd5b506101a06108b6565b3480156101f657600080fd5b506004546101a0565b34801561020b57600080fd5b5060065461022c9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101aa565b34801561025d57600080fd5b5061029a6040518060400160405280600c81526020017f312e382e312d626574612e31000000000000000000000000000000000000000081525081565b6040516101aa9190611405565b3480156102b357600080fd5b506101a0610929565b3480156102c857600080fd5b506003546101a0565b3480156102dd57600080fd5b5060065473ffffffffffffffffffffffffffffffffffffffff1661022c565b34801561030857600080fd5b506101a060015481565b34801561031e57600080fd5b506101a061032d366004611478565b61093b565b34801561033e57600080fd5b506101a060025481565b34801561035457600080fd5b506101d3610363366004611478565b610b4f565b34801561037457600080fd5b506101a060055481565b6101d361038c366004611491565b610de9565b34801561039d57600080fd5b506103b16103ac366004611478565b61124a565b60408051825181526020808401516fffffffffffffffffffffffffffffffff9081169183019190915292820151909216908201526060016101aa565b3480156103f957600080fd5b5060075461022c9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561042657600080fd5b5060075473ffffffffffffffffffffffffffffffffffffffff1661022c565b34801561045157600080fd5b506101a060085481565b34801561046757600080fd5b506103b1610476366004611478565b6112de565b34801561048757600080fd5b506101a0610496366004611478565b611316565b3480156104a757600080fd5b506101a0611346565b3480156104bc57600080fd5b506101a060045481565b3480156104d257600080fd5b506008546101a0565b600054610100900460ff16158080156104fb5750600054600160ff909116105b806105155750303b158015610515575060005460ff166001145b6105a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561060457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b60008811610694576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4c324f75747075744f7261636c653a207375626d697373696f6e20696e74657260448201527f76616c206d7573742062652067726561746572207468616e2030000000000000606482015260840161059d565b60008711610724576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4c324f75747075744f7261636c653a204c3220626c6f636b2074696d65206d7560448201527f73742062652067726561746572207468616e2030000000000000000000000000606482015260840161059d565b428511156107db576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526044602482018190527f4c324f75747075744f7261636c653a207374617274696e67204c322074696d65908201527f7374616d70206d757374206265206c657373207468616e2063757272656e742060648201527f74696d6500000000000000000000000000000000000000000000000000000000608482015260a40161059d565b60048890556005879055600186905560028590556007805473ffffffffffffffffffffffffffffffffffffffff8087167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179092556006805492861692909116919091179055600882905580156108ac57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b6003546000901561092057600380546108d1906001906114f2565b815481106108e1576108e1611509565b600091825260209091206002909102016001015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16919050565b6001545b905090565b600354600090610924906001906114f2565b60006109456108b6565b8211156109fa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f4c324f75747075744f7261636c653a2063616e6e6f7420676574206f7574707560448201527f7420666f72206120626c6f636b207468617420686173206e6f74206265656e2060648201527f70726f706f736564000000000000000000000000000000000000000000000000608482015260a40161059d565b600354610aaf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f4c324f75747075744f7261636c653a2063616e6e6f7420676574206f7574707560448201527f74206173206e6f206f7574707574732068617665206265656e2070726f706f7360648201527f6564207965740000000000000000000000000000000000000000000000000000608482015260a40161059d565b6003546000905b80821015610b485760006002610acc8385611538565b610ad69190611550565b90508460038281548110610aec57610aec611509565b600091825260209091206002909102016001015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff161015610b3e57610b37816001611538565b9250610b42565b8091505b50610ab6565b5092915050565b60065473ffffffffffffffffffffffffffffffffffffffff163314610bf6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f4c324f75747075744f7261636c653a206f6e6c7920746865206368616c6c656e60448201527f67657220616464726573732063616e2064656c657465206f7574707574730000606482015260840161059d565b6003548110610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f4c324f75747075744f7261636c653a2063616e6e6f742064656c657465206f7560448201527f747075747320616674657220746865206c6174657374206f757470757420696e60648201527f6465780000000000000000000000000000000000000000000000000000000000608482015260a40161059d565b60085460038281548110610cc357610cc3611509565b6000918252602090912060016002909202010154610cf3906fffffffffffffffffffffffffffffffff16426114f2565b10610da6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f4c324f75747075744f7261636c653a2063616e6e6f742064656c657465206f7560448201527f74707574732074686174206861766520616c7265616479206265656e2066696e60648201527f616c697a65640000000000000000000000000000000000000000000000000000608482015260a40161059d565b6000610db160035490565b90508160035581817f4ee37ac2c786ec85e87592d3c5c8a1dd66f8496dda3f125d9ea8ca5f657629b660405160405180910390a35050565b60075473ffffffffffffffffffffffffffffffffffffffff163314610eb6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f4c324f75747075744f7261636c653a206f6e6c79207468652070726f706f736560448201527f7220616464726573732063616e2070726f706f7365206e6577206f757470757460648201527f7300000000000000000000000000000000000000000000000000000000000000608482015260a40161059d565b610ebe611346565b8314610f72576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f4c324f75747075744f7261636c653a20626c6f636b206e756d626572206d757360448201527f7420626520657175616c20746f206e65787420657870656374656420626c6f6360648201527f6b206e756d626572000000000000000000000000000000000000000000000000608482015260a40161059d565b42610f7c84611316565b10611009576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f4c324f75747075744f7261636c653a2063616e6e6f742070726f706f7365204c60448201527f32206f757470757420696e207468652066757475726500000000000000000000606482015260840161059d565b83611096576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4c324f75747075744f7261636c653a204c32206f75747075742070726f706f7360448201527f616c2063616e6e6f7420626520746865207a65726f2068617368000000000000606482015260840161059d565b81156111525781814014611152576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604960248201527f4c324f75747075744f7261636c653a20626c6f636b206861736820646f65732060448201527f6e6f74206d61746368207468652068617368206174207468652065787065637460648201527f6564206865696768740000000000000000000000000000000000000000000000608482015260a40161059d565b8261115c60035490565b857fa7aaf2512769da4e444e3de247be2564225c2e7a8f74cfe528e46e17d24868e24260405161118e91815260200190565b60405180910390a45050604080516060810182529283526fffffffffffffffffffffffffffffffff4281166020850190815292811691840191825260038054600181018255600091909152935160029094027fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b810194909455915190518216700100000000000000000000000000000000029116177fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85c90910155565b60408051606081018252600080825260208201819052918101919091526003828154811061127a5761127a611509565b600091825260209182902060408051606081018252600290930290910180548352600101546fffffffffffffffffffffffffffffffff8082169484019490945270010000000000000000000000000000000090049092169181019190915292915050565b604080516060810182526000808252602082018190529181019190915260036113068361093b565b8154811061127a5761127a611509565b60006005546001548361132991906114f2565b611333919061158b565b6002546113409190611538565b92915050565b60006004546113536108b6565b6109249190611538565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b803573ffffffffffffffffffffffffffffffffffffffff8116811461139d57600080fd5b919050565b600080600080600080600060e0888a0312156113bd57600080fd5b873596506020880135955060408801359450606088013593506113e260808901611379565b92506113f060a08901611379565b915060c0880135905092959891949750929550565b600060208083528351808285015260005b8181101561143257858101830151858201604001528201611416565b81811115611444576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b60006020828403121561148a57600080fd5b5035919050565b600080600080608085870312156114a757600080fd5b5050823594602084013594506040840135936060013592509050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015611504576115046114c3565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000821982111561154b5761154b6114c3565b500190565b600082611586577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156115c3576115c36114c3565b50029056fea164736f6c634300080f000a"; + bytes internal constant optimismPortal2Code = +- hex"6080604052600436106101d15760003560e01c80637fc48504116100f7578063a35d99df11610095578063bf653a5c11610064578063bf653a5c14610697578063cff0ab96146106ca578063e9e05c421461076b578063f2b4e6171461077e57600080fd5b8063a35d99df1461059b578063a3860f48146105bb578063b69ef8a8146105db578063bb2c727e146105f057600080fd5b80638e819e54116100d15780638e819e54146104eb578063952b27971461050b5780639bf62d821461053e578063a14238e71461056b57600080fd5b80637fc48504146104ab5780638b4c40b0146101f65780638c3152e9146104cb57600080fd5b80634870496f1161016f5780635c975abb1161013e5780635c975abb1461043657806371c1566e1461044b57806371cfaa3f1461046b5780637d6be8dc1461048b57600080fd5b80634870496f1461034d5780634fd0434c1461036d578063513747ab146103af57806354fd4d50146103ea57600080fd5b80633c9f397c116101ab5780633c9f397c146102a657806343ca1c50146102d8578063452a9320146102f857806345884d321461030d57600080fd5b8063149f2f22146101fd57806333d7e2bd1461021d57806335e80ab31461027457600080fd5b366101f8576101f63334620186a06000604051806020016040528060008152506107ab565b005b600080fd5b34801561020957600080fd5b506101f6610218366004614fe6565b610850565b34801561022957600080fd5b5060375461024a9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561028057600080fd5b5060355461024a90610100900473ffffffffffffffffffffffffffffffffffffffff1681565b3480156102b257600080fd5b50603b546102c39063ffffffff1681565b60405163ffffffff909116815260200161026b565b3480156102e457600080fd5b506101f66102f336600461511c565b610a91565b34801561030457600080fd5b5061024a610f31565b34801561031957600080fd5b5061033d61032836600461516e565b603a6020526000908152604090205460ff1681565b604051901515815260200161026b565b34801561035957600080fd5b506101f661036836600461518b565b610fc9565b34801561037957600080fd5b50603b5461039690640100000000900467ffffffffffffffff1681565b60405167ffffffffffffffff909116815260200161026b565b3480156103bb57600080fd5b506103dc6103ca366004615267565b6000908152603c602052604090205490565b60405190815260200161026b565b3480156103f657600080fd5b50604080518082018252600d81527f332e31312e302d626574612e32000000000000000000000000000000000000006020820152905161026b91906152f6565b34801561044257600080fd5b5061033d611531565b34801561045757600080fd5b506101f6610466366004615309565b6115c4565b34801561047757600080fd5b506101f661048636600461533d565b611c7f565b34801561049757600080fd5b506101f66104a636600461516e565b611e3f565b3480156104b757600080fd5b506101f66104c6366004615395565b611f22565b3480156104d757600080fd5b506101f66104e63660046153b2565b61200e565b3480156104f757600080fd5b506101f66105063660046153ef565b61205a565b34801561051757600080fd5b507f00000000000000000000000000000000000000000000000000000000000000066103dc565b34801561054a57600080fd5b5060325461024a9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561057757600080fd5b5061033d610586366004615267565b60336020526000908152604090205460ff1681565b3480156105a757600080fd5b506103966105b636600461544b565b61230f565b3480156105c757600080fd5b5061024a6105d6366004615468565b61232e565b3480156105e757600080fd5b506103dc612373565b3480156105fc57600080fd5b5061066261060b366004615309565b603960209081526000928352604080842090915290825290205473ffffffffffffffffffffffffffffffffffffffff81169074010000000000000000000000000000000000000000900467ffffffffffffffff1682565b6040805173ffffffffffffffffffffffffffffffffffffffff909316835267ffffffffffffffff90911660208301520161026b565b3480156106a357600080fd5b507f000000000000000000000000000000000000000000000000000000000000000c6103dc565b3480156106d657600080fd5b50600154610732906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff928316602085015291169082015260600161026b565b6101f661077936600461548a565b6107ab565b34801561078a57600080fd5b5060385461024a9073ffffffffffffffffffffffffffffffffffffffff1681565b8260005a905060006107bb6123e9565b50905073ffffffffffffffffffffffffffffffffffffffff811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee148015906107f757503415155b1561082e576040517ff2365b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61083c883489898989612486565b506108478282612632565b50505050505050565b8260005a905060006108606123e9565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8216016108d2576040517f0eaf3c0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87603d60008282546108e49190615538565b90915550506040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015610956573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097a9190615550565b905061099e73ffffffffffffffffffffffffffffffffffffffff831633308c6128ff565b6109a88982615538565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa158015610a12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a369190615550565b14610a6d576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a7b8a8a8a8a8a8a612486565b5050610a878282612632565b5050505050505050565b610a99611531565b15610ad0576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60325473ffffffffffffffffffffffffffffffffffffffff1661dead14610b23576040517f9396d15600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610b2e836129e1565b9050610b3a81836115c4565b6000818152603360209081526040822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558401516032805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff000000000000000000000000000000000000000090921691909117905580610bc56123e9565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff821601610c2857610c218560400151866080015187606001518860a00151612a2e565b9150610e7b565b8073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff1603610c91576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606085015115610e52578460600151603d6000828254610cb19190615569565b90915550506040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015610d23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d479190615550565b9050610d7c866040015187606001518473ffffffffffffffffffffffffffffffffffffffff16612a8c9092919063ffffffff16565b6060860151610d8b9082615569565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa158015610df5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e199190615550565b14610e50576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b60a08501515115610e7657610c218560400151866080015160008860a00151612a2e565b600191505b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405183907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b90610edd90851515815260200190565b60405180910390a281158015610ef35750326001145b15610f2a576040517feeae4ed300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa158015610fa0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc49190615580565b905090565b610fd1611531565b15611008576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff1603611071576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6038546040517fbb8aa1fc00000000000000000000000000000000000000000000000000000000815260048101869052600091829173ffffffffffffffffffffffffffffffffffffffff9091169063bb8aa1fc90602401606060405180830381865afa1580156110e5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611109919061559d565b925050915060008173ffffffffffffffffffffffffffffffffffffffff1663bcef3b556040518163ffffffff1660e01b8152600401602060405180830381865afa15801561115b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061117f9190615550565b603b5490915063ffffffff8481169116146111c6576040517f27a10cc200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111dd6111d8368890038801886155ea565b612ae7565b8114611215576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611220896129e1565b905060018373ffffffffffffffffffffffffffffffffffffffff1663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa15801561126f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611293919061567f565b60028111156112a4576112a4615650565b036112db576040517fd357347400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051602081018390526000918101829052606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012090830181905292506113a49101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152600182527f010000000000000000000000000000000000000000000000000000000000000060208301529061139a898b6156a0565b8b60400135612b26565b15156000036113df576040517fb05e92fa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051808201825273ffffffffffffffffffffffffffffffffffffffff808716825267ffffffffffffffff4281166020808501918252600088815260398252868120338252825286812095518654935190941674010000000000000000000000000000000000000000027fffffffff0000000000000000000000000000000000000000000000000000000090931693851693909317919091179093558d840151928e01519351928216939091169185917f67a6208cfcc0801d50f6cbe764733f4fddf66ac0b04442061a8a8c0cb6b63f6291a4604051339083907f798f9f13695f8f045aa5f80ed8efebb695f3c7fe65da381969f2f28bf3c60b9790600090a3506000908152603c602090815260408220805460018101825590835291200180547fffffffffffffffffffffffff000000000000000000000000000000000000000016331790555050505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115a0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc49190615724565b600082815260396020908152604080832073ffffffffffffffffffffffffffffffffffffffff85811685529083528184208251808401845290549182168082527401000000000000000000000000000000000000000090920467ffffffffffffffff1681850152818552603a90935292205490919060ff1615611673576040517f09550c7700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b816020015167ffffffffffffffff166000036116bb576040517f94efd49b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061173c8273ffffffffffffffffffffffffffffffffffffffff1663cf09e0d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561170b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061172f9190615741565b67ffffffffffffffff1690565b90508067ffffffffffffffff16836020015167ffffffffffffffff1611611810576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604e60248201527f4f7074696d69736d506f7274616c3a207769746864726177616c2074696d657360448201527f74616d70206c657373207468616e20646973707574652067616d65206372656160648201527f74696f6e2074696d657374616d70000000000000000000000000000000000000608482015260a4015b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000c836020015167ffffffffffffffff164261184b9190615569565b116118d8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4f7074696d69736d506f7274616c3a2070726f76656e2077697468647261776160448201527f6c20686173206e6f74206d6174757265642079657400000000000000000000006064820152608401611807565b60028273ffffffffffffffffffffffffffffffffffffffff1663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611925573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611949919061567f565b600281111561195a5761195a615650565b14611991576040517fa080a3c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603b5463ffffffff1663ffffffff16611a1b8373ffffffffffffffffffffffffffffffffffffffff1663bbdc02db6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119ee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a12919061575e565b63ffffffff1690565b63ffffffff1614611a58576040517f27a10cc200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603b5467ffffffffffffffff64010000000090910481169082161015611b26576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604b60248201527f4f7074696d69736d506f7274616c3a20646973707574652067616d652063726560448201527f61746564206265666f7265207265737065637465642067616d6520747970652060648201527f7761732075706461746564000000000000000000000000000000000000000000608482015260a401611807565b7f0000000000000000000000000000000000000000000000000000000000000006611b958373ffffffffffffffffffffffffffffffffffffffff166319effeb46040518163ffffffff1660e01b8152600401602060405180830381865afa15801561170b573d6000803e3d6000fd5b611ba99067ffffffffffffffff1642615569565b11611c36576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4f7074696d69736d506f7274616c3a206f75747075742070726f706f73616c2060448201527f696e206169722d676170000000000000000000000000000000000000000000006064820152608401611807565b60008581526033602052604090205460ff1615610f2a576040517f475a253500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60375473ffffffffffffffffffffffffffffffffffffffff163314611cd0576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611cdc62030d40612b4a565b60405173ffffffffffffffffffffffffffffffffffffffff8516602482015260ff8416604482015260648101839052608481018290526000907342000000000000000000000000000000000000159073deaddeaddeaddeaddeaddeaddeaddeaddead0001907fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32908490819062030d4090829060a401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f71cfaa3f000000000000000000000000000000000000000000000000000000001790529051611df99695949392910161577b565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815290829052611e31916152f6565b60405180910390a450505050565b611e47610f31565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611eab576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81166000818152603a602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055517f192c289026d59a41a27f5aea08f3969b57931b0589202d14f4368cded95d3cda9190a250565b611f2a610f31565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611f8e576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603b805463ffffffff83167fffffffffffffffffffffffffffffffffffffffff00000000000000000000000090911681176401000000004267ffffffffffffffff90811682029290921793849055604051930416917f049fe9dd413cdf037cce27011cc1790c753118272f3630e6e8bdfa5e8208176090600090a350565b565b612016611531565b1561204d576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6120578133610a91565b50565b600054610100900460ff161580801561207a5750600054600160ff909116105b806120945750303b158015612094575060005460ff166001145b612120576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401611807565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561217e57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603880547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff8881169190911790925560378054909116868316179055603580547fffffffffffffffffffffff0000000000000000000000000000000000000000ff16610100868416021790556032541661229e576032805461dead7fffffffffffffffffffffffff0000000000000000000000000000000000000000909116179055603b80547fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166401000000004267ffffffffffffffff16027fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000161763ffffffff84161790555b6122a6612bac565b8015610f2a57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050505050565b600061231c8260106157e0565b61232890615208615810565b92915050565b603c602052816000526040600020818154811061234a57600080fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff169150829050565b60008061237e6123e9565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8216016123c5574791505090565b5050603d5490565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b603754604080517f4397dfef0000000000000000000000000000000000000000000000000000000081528151600093849373ffffffffffffffffffffffffffffffffffffffff90911692634397dfef92600480830193928290030181865afa158015612459573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061247d919061583c565b90939092509050565b8180156124a8575073ffffffffffffffffffffffffffffffffffffffff861615155b156124df576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6124e9815161230f565b67ffffffffffffffff168367ffffffffffffffff161015612536576040517f4929b80800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6201d4c081511115612574576040517f73052b0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b33328114612595575033731111000000000000000000000000000000001111015b600086868686866040516020016125b095949392919061577b565b604051602081830303815290604052905060008873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c328460405161262091906152f6565b60405180910390a45050505050505050565b600154600090612668907801000000000000000000000000000000000000000000000000900467ffffffffffffffff1643615569565b90506000612674612cbf565b90506000816020015160ff16826000015163ffffffff16612695919061589a565b905082156127cc576001546000906126cc908390700100000000000000000000000000000000900467ffffffffffffffff16615902565b90506000836040015160ff16836126e39190615976565b6001546127039084906fffffffffffffffffffffffffffffffff16615976565b61270d919061589a565b60015490915060009061275e906127379084906fffffffffffffffffffffffffffffffff16615a32565b866060015163ffffffff168760a001516fffffffffffffffffffffffffffffffff16612d80565b9050600186111561278d5761278a61273782876040015160ff1660018a6127859190615569565b612d9f565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760015550505b600180548691906010906127ff908490700100000000000000000000000000000000900467ffffffffffffffff16615810565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550816000015163ffffffff16600160000160109054906101000a900467ffffffffffffffff1667ffffffffffffffff16131561288c576040517f77ebef4d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001546000906128b8906fffffffffffffffffffffffffffffffff1667ffffffffffffffff8816615aa6565b905060006128ca48633b9aca00612df4565b6128d49083615ae3565b905060005a6128e39088615569565b905080821115610a8757610a876128fa8284615569565b612e0b565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526129db9085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152612e34565b50505050565b80516020808301516040808501516060860151608087015160a08801519351600097612a11979096959101615af7565b604051602081830303815290604052805190602001209050919050565b6000806000612a3e866000612f40565b905080612a74576308c379a06000526020805278185361666543616c6c3a204e6f7420656e6f756768206761736058526064601cfd5b600080855160208701888b5af1979650505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052612ae29084907fa9059cbb0000000000000000000000000000000000000000000000000000000090606401612959565b505050565b60008160000151826020015183604001518460600151604051602001612a11949392919093845260208401929092526040830152606082015260800190565b600080612b3286612f5e565b9050612b4081868686612f90565b9695505050505050565b6001805463ffffffff83169190601090612b83908490700100000000000000000000000000000000900467ffffffffffffffff16615810565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555050565b600054610100900460ff16612c43576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401611807565b6001547801000000000000000000000000000000000000000000000000900467ffffffffffffffff1660000361200c5760408051606081018252633b9aca00808252600060208301524367ffffffffffffffff169190920181905278010000000000000000000000000000000000000000000000000217600155565b6040805160c08082018352600080835260208301819052828401819052606083018190526080830181905260a083015260375483517fcc731b020000000000000000000000000000000000000000000000000000000081529351929373ffffffffffffffffffffffffffffffffffffffff9091169263cc731b02926004808401939192918290030181865afa158015612d5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc49190615b4e565b6000612d95612d8f8585612fc0565b83612fd0565b90505b9392505050565b6000670de0b6b3a7640000612de0612db7858361589a565b612dc990670de0b6b3a7640000615902565b612ddb85670de0b6b3a7640000615976565b612fdf565b612dea9086615976565b612d95919061589a565b600081831015612e045781612d98565b5090919050565b6000805a90505b825a612e1e9083615569565b1015612ae257612e2d82615bf0565b9150612e12565b6000612e96826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166130109092919063ffffffff16565b805190915015612ae25780806020019051810190612eb49190615724565b612ae2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401611807565b600080603f83619c4001026040850201603f5a021015949350505050565b60608180519060200120604051602001612f7a91815260200190565b6040516020818303038152906040529050919050565b6000612fb784612fa187868661301f565b8051602091820120825192909101919091201490565b95945050505050565b600081831215612e045781612d98565b6000818312612e045781612d98565b6000612d98670de0b6b3a764000083612ff786613a9d565b6130019190615976565b61300b919061589a565b613ce1565b6060612d958484600085613f20565b6060600084511161308c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4d65726b6c65547269653a20656d707479206b657900000000000000000000006044820152606401611807565b6000613097846140b6565b905060006130a4866141a2565b90506000846040516020016130bb91815260200190565b60405160208183030381529060405290506000805b8451811015613a145760008582815181106130ed576130ed615c28565b602002602001015190508451831115613188576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4d65726b6c65547269653a206b657920696e646578206578636565647320746f60448201527f74616c206b6579206c656e6774680000000000000000000000000000000000006064820152608401611807565b8260000361324157805180516020918201206040516131d6926131b092910190815260200190565b604051602081830303815290604052858051602091820120825192909101919091201490565b61323c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4d65726b6c65547269653a20696e76616c696420726f6f7420686173680000006044820152606401611807565b613398565b8051516020116132f7578051805160209182012060405161326b926131b092910190815260200190565b61323c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d65726b6c65547269653a20696e76616c6964206c6172676520696e7465726e60448201527f616c2068617368000000000000000000000000000000000000000000000000006064820152608401611807565b805184516020808701919091208251919092012014613398576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4d65726b6c65547269653a20696e76616c696420696e7465726e616c206e6f6460448201527f65206861736800000000000000000000000000000000000000000000000000006064820152608401611807565b6133a460106001615538565b816020015151036135805784518303613518576133de81602001516010815181106133d1576133d1615c28565b6020026020010151614205565b96506000875111613471576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603b60248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286272616e63682900000000006064820152608401611807565b6001865161347f9190615569565b821461350d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286272616e6368290000000000006064820152608401611807565b505050505050612d98565b600085848151811061352c5761352c615c28565b602001015160f81c60f81b60f81c9050600082602001518260ff168151811061355757613557615c28565b6020026020010151905061356a816142b9565b9550613577600186615538565b94505050613a01565b600281602001515103613979576000613598826142de565b90506000816000815181106135af576135af615c28565b016020015160f81c905060006135c6600283615c57565b6135d1906002615c79565b905060006135e2848360ff16614302565b905060006135f08a89614302565b905060006135fe8383614338565b905080835114613690576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a20706174682072656d61696e646572206d7573742060448201527f736861726520616c6c206e6962626c65732077697468206b65790000000000006064820152608401611807565b60ff8516600214806136a5575060ff85166003145b15613894578082511461373a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f4d65726b6c65547269653a206b65792072656d61696e646572206d757374206260448201527f65206964656e746963616c20746f20706174682072656d61696e6465720000006064820152608401611807565b61375487602001516001815181106133d1576133d1615c28565b9c5060008d51116137e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286c65616629000000000000006064820152608401611807565b60018c516137f59190615569565b8814613883576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286c6561662900000000000000006064820152608401611807565b505050505050505050505050612d98565b60ff851615806138a7575060ff85166001145b156138e6576138d387602001516001815181106138c6576138c6615c28565b60200260200101516142b9565b99506138df818a615538565b985061396e565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4d65726b6c65547269653a2072656365697665642061206e6f6465207769746860448201527f20616e20756e6b6e6f776e2070726566697800000000000000000000000000006064820152608401611807565b505050505050613a01565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4d65726b6c65547269653a20726563656976656420616e20756e70617273656160448201527f626c65206e6f64650000000000000000000000000000000000000000000000006064820152608401611807565b5080613a0c81615bf0565b9150506130d0565b506040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4d65726b6c65547269653a2072616e206f7574206f662070726f6f6620656c6560448201527f6d656e74730000000000000000000000000000000000000000000000000000006064820152608401611807565b6000808213613b08576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401611807565b60006060613b15846143ec565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c18213613d1257506000919050565b680755bf798b4a1bf1e58212613d84576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4558505f4f564552464c4f5700000000000000000000000000000000000000006044820152606401611807565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b606082471015613fb2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401611807565b73ffffffffffffffffffffffffffffffffffffffff85163b614030576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401611807565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516140599190615c9c565b60006040518083038185875af1925050503d8060008114614096576040519150601f19603f3d011682016040523d82523d6000602084013e61409b565b606091505b50915091506140ab8282866144c2565b979650505050505050565b80516060908067ffffffffffffffff8111156140d4576140d4614eb1565b60405190808252806020026020018201604052801561411957816020015b60408051808201909152606080825260208201528152602001906001900390816140f25790505b50915060005b8181101561419b57604051806040016040528085838151811061414457614144615c28565b6020026020010151815260200161417386848151811061416657614166615c28565b6020026020010151614515565b81525083828151811061418857614188615c28565b602090810291909101015260010161411f565b5050919050565b606080604051905082518060011b603f8101601f1916830160405280835250602084016020830160005b838110156141fa578060011b82018184015160001a8060041c8253600f8116600183015350506001016141cc565b509295945050505050565b6060600080600061421585614528565b91945092509050600081600181111561423057614230615650565b14614267576040517f1ff9b2e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6142718284615538565b8551146142aa576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612fb7856020015184846149c6565b606060208260000151106142d5576142d082614205565b612328565b61232882614a5a565b60606123286142fd83602001516000815181106133d1576133d1615c28565b6141a2565b6060825182106143215750604080516020810190915260008152612328565b612d9883838486516143339190615569565b614a70565b600080825184511061434b57825161434e565b83515b90505b80821080156143d5575082828151811061436d5761436d615c28565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168483815181106143ac576143ac615c28565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b156143e557816001019150614351565b5092915050565b6000808211614457576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401611807565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b606083156144d1575081612d98565b8251156144e15782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161180791906152f6565b606061232861452383614c48565b614cb5565b6000806000836000015160000361456b576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020840151805160001a607f81116145905760006001600094509450945050506149bf565b60b781116146a65760006145a5608083615569565b9050808760000151116145e4576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001838101517fff0000000000000000000000000000000000000000000000000000000000000016908214801561465c57507f80000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000008216105b15614693576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50600195509350600092506149bf915050565b60bf81116148045760006146bb60b783615569565b9050808760000151116146fa576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff0000000000000000000000000000000000000000000000000000000000000016600081900361475c576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c603781116147a4576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6147ae8184615538565b8951116147e7576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6147f2836001615538565b97509550600094506149bf9350505050565b60f7811161486957600061481960c083615569565b905080876000015111614858576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001955093508492506149bf915050565b600061487660f783615569565b9050808760000151116148b5576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614917576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c6037811161495f576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6149698184615538565b8951116149a2576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6149ad836001615538565b97509550600194506149bf9350505050565b9193909250565b60608167ffffffffffffffff8111156149e1576149e1614eb1565b6040519080825280601f01601f191660200182016040528015614a0b576020820181803683370190505b5090508115612d98576000614a208486615538565b90506020820160005b84811015614a41578281015182820152602001614a29565b84811115614a50576000858301525b5050509392505050565b60606123288260200151600084600001516149c6565b60608182601f011015614adf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401611807565b828284011015614b4b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401611807565b81830184511015614bb8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401611807565b606082158015614bd75760405191506000825260208201604052614c3f565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015614c10578051835260209283019201614bf8565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b60408051808201909152600080825260208201528151600003614c97576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50604080518082019091528151815260209182019181019190915290565b60606000806000614cc585614528565b919450925090506001816001811115614ce057614ce0615650565b14614d17576040517f4b9c6abe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8451614d238385615538565b14614d5a576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516020808252610420820190925290816020015b6040805180820190915260008082526020820152815260200190600190039081614d715790505093506000835b8651811015614e5f57600080614de46040518060400160405280858c60000151614dc89190615569565b8152602001858c60200151614ddd9190615538565b9052614528565b509150915060405180604001604052808383614e009190615538565b8152602001848b60200151614e159190615538565b815250888581518110614e2a57614e2a615c28565b6020908102919091010152614e40600185615538565b9350614e4c8183615538565b614e569084615538565b92505050614d9e565b50845250919392505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461205757600080fd5b67ffffffffffffffff8116811461205757600080fd5b801515811461205757600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160c0810167ffffffffffffffff81118282101715614f0357614f03614eb1565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614f5057614f50614eb1565b604052919050565b600082601f830112614f6957600080fd5b813567ffffffffffffffff811115614f8357614f83614eb1565b614fb460207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601614f09565b818152846020838601011115614fc957600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060008060c08789031215614fff57600080fd5b863561500a81614e6b565b95506020870135945060408701359350606087013561502881614e8d565b9250608087013561503881614ea3565b915060a087013567ffffffffffffffff81111561505457600080fd5b61506089828a01614f58565b9150509295509295509295565b600060c0828403121561507f57600080fd5b60405160c0810167ffffffffffffffff82821081831117156150a3576150a3614eb1565b8160405282935084358352602085013591506150be82614e6b565b816020840152604085013591506150d482614e6b565b816040840152606085013560608401526080850135608084015260a085013591508082111561510257600080fd5b5061510f85828601614f58565b60a0830152505092915050565b6000806040838503121561512f57600080fd5b823567ffffffffffffffff81111561514657600080fd5b6151528582860161506d565b925050602083013561516381614e6b565b809150509250929050565b60006020828403121561518057600080fd5b8135612d9881614e6b565b600080600080600085870360e08112156151a457600080fd5b863567ffffffffffffffff808211156151bc57600080fd5b6151c88a838b0161506d565b97506020890135965060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08401121561520157600080fd5b60408901955060c089013592508083111561521b57600080fd5b828901925089601f84011261522f57600080fd5b823591508082111561524057600080fd5b508860208260051b840101111561525657600080fd5b959894975092955050506020019190565b60006020828403121561527957600080fd5b5035919050565b60005b8381101561529b578181015183820152602001615283565b838111156129db5750506000910152565b600081518084526152c4816020860160208601615280565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000612d9860208301846152ac565b6000806040838503121561531c57600080fd5b82359150602083013561516381614e6b565b60ff8116811461205757600080fd5b6000806000806080858703121561535357600080fd5b843561535e81614e6b565b9350602085013561536e8161532e565b93969395505050506040820135916060013590565b63ffffffff8116811461205757600080fd5b6000602082840312156153a757600080fd5b8135612d9881615383565b6000602082840312156153c457600080fd5b813567ffffffffffffffff8111156153db57600080fd5b6153e78482850161506d565b949350505050565b6000806000806080858703121561540557600080fd5b843561541081614e6b565b9350602085013561542081614e6b565b9250604085013561543081614e6b565b9150606085013561544081615383565b939692955090935050565b60006020828403121561545d57600080fd5b8135612d9881614e8d565b6000806040838503121561547b57600080fd5b50508035926020909101359150565b600080600080600060a086880312156154a257600080fd5b85356154ad81614e6b565b94506020860135935060408601356154c481614e8d565b925060608601356154d481614ea3565b9150608086013567ffffffffffffffff8111156154f057600080fd5b6154fc88828901614f58565b9150509295509295909350565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561554b5761554b615509565b500190565b60006020828403121561556257600080fd5b5051919050565b60008282101561557b5761557b615509565b500390565b60006020828403121561559257600080fd5b8151612d9881614e6b565b6000806000606084860312156155b257600080fd5b83516155bd81615383565b60208501519093506155ce81614e8d565b60408501519092506155df81614e6b565b809150509250925092565b6000608082840312156155fc57600080fd5b6040516080810181811067ffffffffffffffff8211171561561f5761561f614eb1565b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60006020828403121561569157600080fd5b815160038110612d9857600080fd5b600067ffffffffffffffff808411156156bb576156bb614eb1565b8360051b60206156cc818301614f09565b8681529185019181810190368411156156e457600080fd5b865b84811015615718578035868111156156fe5760008081fd5b61570a36828b01614f58565b8452509183019183016156e6565b50979650505050505050565b60006020828403121561573657600080fd5b8151612d9881614ea3565b60006020828403121561575357600080fd5b8151612d9881614e8d565b60006020828403121561577057600080fd5b8151612d9881615383565b8581528460208201527fffffffffffffffff0000000000000000000000000000000000000000000000008460c01b16604082015282151560f81b6048820152600082516157cf816049850160208701615280565b919091016049019695505050505050565b600067ffffffffffffffff8083168185168183048111821515161561580757615807615509565b02949350505050565b600067ffffffffffffffff80831681851680830382111561583357615833615509565b01949350505050565b6000806040838503121561584f57600080fd5b825161585a81614e6b565b60208401519092506151638161532e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826158a9576158a961586b565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f8000000000000000000000000000000000000000000000000000000000000000831416156158fd576158fd615509565b500590565b6000808312837f80000000000000000000000000000000000000000000000000000000000000000183128115161561593c5761593c615509565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01831381161561597057615970615509565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6000841360008413858304851182821616156159b7576159b7615509565b7f800000000000000000000000000000000000000000000000000000000000000060008712868205881281841616156159f2576159f2615509565b60008712925087820587128484161615615a0e57615a0e615509565b87850587128184161615615a2457615a24615509565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03841381151615615a6c57615a6c615509565b827f8000000000000000000000000000000000000000000000000000000000000000038412811615615aa057615aa0615509565b50500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615ade57615ade615509565b500290565b600082615af257615af261586b565b500490565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a0830152615b4260c08301846152ac565b98975050505050505050565b600060c08284031215615b6057600080fd5b615b68614ee0565b8251615b7381615383565b81526020830151615b838161532e565b60208201526040830151615b968161532e565b60408201526060830151615ba981615383565b60608201526080830151615bbc81615383565b608082015260a08301516fffffffffffffffffffffffffffffffff81168114615be457600080fd5b60a08201529392505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203615c2157615c21615509565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060ff831680615c6a57615c6a61586b565b8060ff84160691505092915050565b600060ff821660ff841680821015615c9357615c93615509565b90039392505050565b60008251615cae818460208701615280565b919091019291505056fea164736f6c634300080f000a"; ++ hex"6080604052600436106101d15760003560e01c80637fc48504116100f7578063a35d99df11610095578063bf653a5c11610064578063bf653a5c14610697578063cff0ab96146106ca578063e9e05c421461076b578063f2b4e6171461077e57600080fd5b8063a35d99df1461059b578063a3860f48146105bb578063b69ef8a8146105db578063bb2c727e146105f057600080fd5b80638e819e54116100d15780638e819e54146104eb578063952b27971461050b5780639bf62d821461053e578063a14238e71461056b57600080fd5b80637fc48504146104ab5780638b4c40b0146101f65780638c3152e9146104cb57600080fd5b80634870496f1161016f5780635c975abb1161013e5780635c975abb1461043657806371c1566e1461044b57806371cfaa3f1461046b5780637d6be8dc1461048b57600080fd5b80634870496f1461034d5780634fd0434c1461036d578063513747ab146103af57806354fd4d50146103ea57600080fd5b80633c9f397c116101ab5780633c9f397c146102a657806343ca1c50146102d8578063452a9320146102f857806345884d321461030d57600080fd5b8063149f2f22146101fd57806333d7e2bd1461021d57806335e80ab31461027457600080fd5b366101f8576101f63334620186a06000604051806020016040528060008152506107ab565b005b600080fd5b34801561020957600080fd5b506101f6610218366004614feb565b610850565b34801561022957600080fd5b5060375461024a9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561028057600080fd5b5060355461024a90610100900473ffffffffffffffffffffffffffffffffffffffff1681565b3480156102b257600080fd5b50603b546102c39063ffffffff1681565b60405163ffffffff909116815260200161026b565b3480156102e457600080fd5b506101f66102f3366004615121565b610a91565b34801561030457600080fd5b5061024a610f31565b34801561031957600080fd5b5061033d610328366004615173565b603a6020526000908152604090205460ff1681565b604051901515815260200161026b565b34801561035957600080fd5b506101f6610368366004615190565b610fc9565b34801561037957600080fd5b50603b5461039690640100000000900467ffffffffffffffff1681565b60405167ffffffffffffffff909116815260200161026b565b3480156103bb57600080fd5b506103dc6103ca36600461526c565b6000908152603c602052604090205490565b60405190815260200161026b565b3480156103f657600080fd5b50604080518082018252600d81527f332e31312e302d626574612e33000000000000000000000000000000000000006020820152905161026b91906152fb565b34801561044257600080fd5b5061033d611531565b34801561045757600080fd5b506101f661046636600461530e565b6115c4565b34801561047757600080fd5b506101f6610486366004615342565b611c7f565b34801561049757600080fd5b506101f66104a6366004615173565b611e3f565b3480156104b757600080fd5b506101f66104c636600461539a565b611f22565b3480156104d757600080fd5b506101f66104e63660046153b7565b61200e565b3480156104f757600080fd5b506101f66105063660046153f4565b61205a565b34801561051757600080fd5b507f00000000000000000000000000000000000000000000000000000000000000066103dc565b34801561054a57600080fd5b5060325461024a9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561057757600080fd5b5061033d61058636600461526c565b60336020526000908152604090205460ff1681565b3480156105a757600080fd5b506103966105b6366004615450565b61230f565b3480156105c757600080fd5b5061024a6105d636600461546d565b61232e565b3480156105e757600080fd5b506103dc612373565b3480156105fc57600080fd5b5061066261060b36600461530e565b603960209081526000928352604080842090915290825290205473ffffffffffffffffffffffffffffffffffffffff81169074010000000000000000000000000000000000000000900467ffffffffffffffff1682565b6040805173ffffffffffffffffffffffffffffffffffffffff909316835267ffffffffffffffff90911660208301520161026b565b3480156106a357600080fd5b507f000000000000000000000000000000000000000000000000000000000000000c6103dc565b3480156106d657600080fd5b50600154610732906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff928316602085015291169082015260600161026b565b6101f661077936600461548f565b6107ab565b34801561078a57600080fd5b5060385461024a9073ffffffffffffffffffffffffffffffffffffffff1681565b8260005a905060006107bb6123e9565b50905073ffffffffffffffffffffffffffffffffffffffff811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee148015906107f757503415155b1561082e576040517ff2365b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61083c883489898989612486565b506108478282612632565b50505050505050565b8260005a905060006108606123e9565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8216016108d2576040517f0eaf3c0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87603d60008282546108e4919061553d565b90915550506040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015610956573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097a9190615555565b905061099e73ffffffffffffffffffffffffffffffffffffffff831633308c6128ff565b6109a8898261553d565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa158015610a12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a369190615555565b14610a6d576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a7b8a8a8a8a8a8a612486565b5050610a878282612632565b5050505050505050565b610a99611531565b15610ad0576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60325473ffffffffffffffffffffffffffffffffffffffff1661dead14610b23576040517f9396d15600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610b2e836129e1565b9050610b3a81836115c4565b6000818152603360209081526040822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558401516032805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff000000000000000000000000000000000000000090921691909117905580610bc56123e9565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff821601610c2857610c218560400151866080015187606001518860a00151612a2e565b9150610e7b565b8073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff1603610c91576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606085015115610e52578460600151603d6000828254610cb1919061556e565b90915550506040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015610d23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d479190615555565b9050610d7c866040015187606001518473ffffffffffffffffffffffffffffffffffffffff16612a8c9092919063ffffffff16565b6060860151610d8b908261556e565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa158015610df5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e199190615555565b14610e50576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b60a08501515115610e7657610c218560400151866080015160008860a00151612a2e565b600191505b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405183907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b90610edd90851515815260200190565b60405180910390a281158015610ef35750326001145b15610f2a576040517feeae4ed300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa158015610fa0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc49190615585565b905090565b610fd1611531565b15611008576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff1603611071576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6038546040517fbb8aa1fc00000000000000000000000000000000000000000000000000000000815260048101869052600091829173ffffffffffffffffffffffffffffffffffffffff9091169063bb8aa1fc90602401606060405180830381865afa1580156110e5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061110991906155a2565b925050915060008173ffffffffffffffffffffffffffffffffffffffff1663bcef3b556040518163ffffffff1660e01b8152600401602060405180830381865afa15801561115b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061117f9190615555565b603b5490915063ffffffff8481169116146111c6576040517f27a10cc200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111dd6111d8368890038801886155ef565b612ae7565b8114611215576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611220896129e1565b905060018373ffffffffffffffffffffffffffffffffffffffff1663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa15801561126f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112939190615684565b60028111156112a4576112a4615655565b036112db576040517fd357347400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051602081018390526000918101829052606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012090830181905292506113a49101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152600182527f010000000000000000000000000000000000000000000000000000000000000060208301529061139a898b6156a5565b8b60400135612b26565b15156000036113df576040517fb05e92fa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051808201825273ffffffffffffffffffffffffffffffffffffffff808716825267ffffffffffffffff4281166020808501918252600088815260398252868120338252825286812095518654935190941674010000000000000000000000000000000000000000027fffffffff0000000000000000000000000000000000000000000000000000000090931693851693909317919091179093558d840151928e01519351928216939091169185917f67a6208cfcc0801d50f6cbe764733f4fddf66ac0b04442061a8a8c0cb6b63f6291a4604051339083907f798f9f13695f8f045aa5f80ed8efebb695f3c7fe65da381969f2f28bf3c60b9790600090a3506000908152603c602090815260408220805460018101825590835291200180547fffffffffffffffffffffffff000000000000000000000000000000000000000016331790555050505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115a0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc49190615729565b600082815260396020908152604080832073ffffffffffffffffffffffffffffffffffffffff85811685529083528184208251808401845290549182168082527401000000000000000000000000000000000000000090920467ffffffffffffffff1681850152818552603a90935292205490919060ff1615611673576040517f09550c7700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b816020015167ffffffffffffffff166000036116bb576040517f94efd49b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061173c8273ffffffffffffffffffffffffffffffffffffffff1663cf09e0d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561170b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061172f9190615746565b67ffffffffffffffff1690565b90508067ffffffffffffffff16836020015167ffffffffffffffff1611611810576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604e60248201527f4f7074696d69736d506f7274616c3a207769746864726177616c2074696d657360448201527f74616d70206c657373207468616e20646973707574652067616d65206372656160648201527f74696f6e2074696d657374616d70000000000000000000000000000000000000608482015260a4015b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000c836020015167ffffffffffffffff164261184b919061556e565b116118d8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4f7074696d69736d506f7274616c3a2070726f76656e2077697468647261776160448201527f6c20686173206e6f74206d6174757265642079657400000000000000000000006064820152608401611807565b60028273ffffffffffffffffffffffffffffffffffffffff1663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611925573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119499190615684565b600281111561195a5761195a615655565b14611991576040517fa080a3c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603b5463ffffffff1663ffffffff16611a1b8373ffffffffffffffffffffffffffffffffffffffff1663bbdc02db6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119ee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a129190615763565b63ffffffff1690565b63ffffffff1614611a58576040517f27a10cc200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603b5467ffffffffffffffff64010000000090910481169082161015611b26576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604b60248201527f4f7074696d69736d506f7274616c3a20646973707574652067616d652063726560448201527f61746564206265666f7265207265737065637465642067616d6520747970652060648201527f7761732075706461746564000000000000000000000000000000000000000000608482015260a401611807565b7f0000000000000000000000000000000000000000000000000000000000000006611b958373ffffffffffffffffffffffffffffffffffffffff166319effeb46040518163ffffffff1660e01b8152600401602060405180830381865afa15801561170b573d6000803e3d6000fd5b611ba99067ffffffffffffffff164261556e565b11611c36576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4f7074696d69736d506f7274616c3a206f75747075742070726f706f73616c2060448201527f696e206169722d676170000000000000000000000000000000000000000000006064820152608401611807565b60008581526033602052604090205460ff1615610f2a576040517f475a253500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60375473ffffffffffffffffffffffffffffffffffffffff163314611cd0576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611cdc62030d40612b4a565b60405173ffffffffffffffffffffffffffffffffffffffff8516602482015260ff8416604482015260648101839052608481018290526000907342000000000000000000000000000000000000159073deaddeaddeaddeaddeaddeaddeaddeaddead0001907fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32908490819062030d4090829060a401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f71cfaa3f000000000000000000000000000000000000000000000000000000001790529051611df996959493929101615780565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815290829052611e31916152fb565b60405180910390a450505050565b611e47610f31565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611eab576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81166000818152603a602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055517f192c289026d59a41a27f5aea08f3969b57931b0589202d14f4368cded95d3cda9190a250565b611f2a610f31565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611f8e576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603b805463ffffffff83167fffffffffffffffffffffffffffffffffffffffff00000000000000000000000090911681176401000000004267ffffffffffffffff90811682029290921793849055604051930416917f049fe9dd413cdf037cce27011cc1790c753118272f3630e6e8bdfa5e8208176090600090a350565b565b612016611531565b1561204d576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6120578133610a91565b50565b600054610100900460ff161580801561207a5750600054600160ff909116105b806120945750303b158015612094575060005460ff166001145b612120576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401611807565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561217e57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603880547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff8881169190911790925560378054909116868316179055603580547fffffffffffffffffffffff0000000000000000000000000000000000000000ff16610100868416021790556032541661229e576032805461dead7fffffffffffffffffffffffff0000000000000000000000000000000000000000909116179055603b80547fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166401000000004267ffffffffffffffff16027fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000161763ffffffff84161790555b6122a6612bac565b8015610f2a57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050505050565b600061231c8260106157e5565b61232890615208615815565b92915050565b603c602052816000526040600020818154811061234a57600080fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff169150829050565b60008061237e6123e9565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8216016123c5574791505090565b5050603d5490565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b603754604080517f4397dfef0000000000000000000000000000000000000000000000000000000081528151600093849373ffffffffffffffffffffffffffffffffffffffff90911692634397dfef92600480830193928290030181865afa158015612459573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061247d9190615841565b90939092509050565b8180156124a8575073ffffffffffffffffffffffffffffffffffffffff861615155b156124df576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6124e9815161230f565b67ffffffffffffffff168367ffffffffffffffff161015612536576040517f4929b80800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6201d4c081511115612574576040517f73052b0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b33328114612595575033731111000000000000000000000000000000001111015b600086868686866040516020016125b0959493929190615780565b604051602081830303815290604052905060008873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c328460405161262091906152fb565b60405180910390a45050505050505050565b600154600090612668907801000000000000000000000000000000000000000000000000900467ffffffffffffffff164361556e565b90506000612674612cbf565b90506000816020015160ff16826000015163ffffffff16612695919061589f565b905082156127cc576001546000906126cc908390700100000000000000000000000000000000900467ffffffffffffffff16615907565b90506000836040015160ff16836126e3919061597b565b6001546127039084906fffffffffffffffffffffffffffffffff1661597b565b61270d919061589f565b60015490915060009061275e906127379084906fffffffffffffffffffffffffffffffff16615a37565b866060015163ffffffff168760a001516fffffffffffffffffffffffffffffffff16612d85565b9050600186111561278d5761278a61273782876040015160ff1660018a612785919061556e565b612da4565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760015550505b600180548691906010906127ff908490700100000000000000000000000000000000900467ffffffffffffffff16615815565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550816000015163ffffffff16600160000160109054906101000a900467ffffffffffffffff1667ffffffffffffffff16131561288c576040517f77ebef4d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001546000906128b8906fffffffffffffffffffffffffffffffff1667ffffffffffffffff8816615aab565b905060006128ca48633b9aca00612df9565b6128d49083615ae8565b905060005a6128e3908861556e565b905080821115610a8757610a876128fa828461556e565b612e10565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526129db9085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152612e39565b50505050565b80516020808301516040808501516060860151608087015160a08801519351600097612a11979096959101615afc565b604051602081830303815290604052805190602001209050919050565b6000806000612a3e866000612f45565b905080612a74576308c379a06000526020805278185361666543616c6c3a204e6f7420656e6f756768206761736058526064601cfd5b600080855160208701888b5af1979650505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052612ae29084907fa9059cbb0000000000000000000000000000000000000000000000000000000090606401612959565b505050565b60008160000151826020015183604001518460600151604051602001612a11949392919093845260208401929092526040830152606082015260800190565b600080612b3286612f63565b9050612b4081868686612f95565b9695505050505050565b6001805463ffffffff83169190601090612b83908490700100000000000000000000000000000000900467ffffffffffffffff16615815565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555050565b600054610100900460ff16612c43576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401611807565b6001547801000000000000000000000000000000000000000000000000900467ffffffffffffffff1660000361200c5760408051606081018252633b9aca00808252600060208301524367ffffffffffffffff169190920181905278010000000000000000000000000000000000000000000000000217600155565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152603754604080517fcc731b02000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163cc731b029160048083019260c09291908290030181865afa158015612d61573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123289190615b53565b6000612d9a612d948585612fc5565b83612fd5565b90505b9392505050565b6000670de0b6b3a7640000612de5612dbc858361589f565b612dce90670de0b6b3a7640000615907565b612de085670de0b6b3a764000061597b565b612fe4565b612def908661597b565b612d9a919061589f565b600081831015612e095781612d9d565b5090919050565b6000805a90505b825a612e23908361556e565b1015612ae257612e3282615bf5565b9150612e17565b6000612e9b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166130159092919063ffffffff16565b805190915015612ae25780806020019051810190612eb99190615729565b612ae2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401611807565b600080603f83619c4001026040850201603f5a021015949350505050565b60608180519060200120604051602001612f7f91815260200190565b6040516020818303038152906040529050919050565b6000612fbc84612fa6878686613024565b8051602091820120825192909101919091201490565b95945050505050565b600081831215612e095781612d9d565b6000818312612e095781612d9d565b6000612d9d670de0b6b3a764000083612ffc86613aa2565b613006919061597b565b613010919061589f565b613ce6565b6060612d9a8484600085613f25565b60606000845111613091576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4d65726b6c65547269653a20656d707479206b657900000000000000000000006044820152606401611807565b600061309c846140bb565b905060006130a9866141a7565b90506000846040516020016130c091815260200190565b60405160208183030381529060405290506000805b8451811015613a195760008582815181106130f2576130f2615c2d565b60200260200101519050845183111561318d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4d65726b6c65547269653a206b657920696e646578206578636565647320746f60448201527f74616c206b6579206c656e6774680000000000000000000000000000000000006064820152608401611807565b8260000361324657805180516020918201206040516131db926131b592910190815260200190565b604051602081830303815290604052858051602091820120825192909101919091201490565b613241576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4d65726b6c65547269653a20696e76616c696420726f6f7420686173680000006044820152606401611807565b61339d565b8051516020116132fc5780518051602091820120604051613270926131b592910190815260200190565b613241576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d65726b6c65547269653a20696e76616c6964206c6172676520696e7465726e60448201527f616c2068617368000000000000000000000000000000000000000000000000006064820152608401611807565b80518451602080870191909120825191909201201461339d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4d65726b6c65547269653a20696e76616c696420696e7465726e616c206e6f6460448201527f65206861736800000000000000000000000000000000000000000000000000006064820152608401611807565b6133a96010600161553d565b81602001515103613585578451830361351d576133e381602001516010815181106133d6576133d6615c2d565b602002602001015161420a565b96506000875111613476576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603b60248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286272616e63682900000000006064820152608401611807565b60018651613484919061556e565b8214613512576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286272616e6368290000000000006064820152608401611807565b505050505050612d9d565b600085848151811061353157613531615c2d565b602001015160f81c60f81b60f81c9050600082602001518260ff168151811061355c5761355c615c2d565b6020026020010151905061356f816142be565b955061357c60018661553d565b94505050613a06565b60028160200151510361397e57600061359d826142e3565b90506000816000815181106135b4576135b4615c2d565b016020015160f81c905060006135cb600283615c5c565b6135d6906002615c7e565b905060006135e7848360ff16614307565b905060006135f58a89614307565b90506000613603838361433d565b905080835114613695576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a20706174682072656d61696e646572206d7573742060448201527f736861726520616c6c206e6962626c65732077697468206b65790000000000006064820152608401611807565b60ff8516600214806136aa575060ff85166003145b15613899578082511461373f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f4d65726b6c65547269653a206b65792072656d61696e646572206d757374206260448201527f65206964656e746963616c20746f20706174682072656d61696e6465720000006064820152608401611807565b61375987602001516001815181106133d6576133d6615c2d565b9c5060008d51116137ec576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286c65616629000000000000006064820152608401611807565b60018c516137fa919061556e565b8814613888576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286c6561662900000000000000006064820152608401611807565b505050505050505050505050612d9d565b60ff851615806138ac575060ff85166001145b156138eb576138d887602001516001815181106138cb576138cb615c2d565b60200260200101516142be565b99506138e4818a61553d565b9850613973565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4d65726b6c65547269653a2072656365697665642061206e6f6465207769746860448201527f20616e20756e6b6e6f776e2070726566697800000000000000000000000000006064820152608401611807565b505050505050613a06565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4d65726b6c65547269653a20726563656976656420616e20756e70617273656160448201527f626c65206e6f64650000000000000000000000000000000000000000000000006064820152608401611807565b5080613a1181615bf5565b9150506130d5565b506040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4d65726b6c65547269653a2072616e206f7574206f662070726f6f6620656c6560448201527f6d656e74730000000000000000000000000000000000000000000000000000006064820152608401611807565b6000808213613b0d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401611807565b60006060613b1a846143f1565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c18213613d1757506000919050565b680755bf798b4a1bf1e58212613d89576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4558505f4f564552464c4f5700000000000000000000000000000000000000006044820152606401611807565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b606082471015613fb7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401611807565b73ffffffffffffffffffffffffffffffffffffffff85163b614035576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401611807565b6000808673ffffffffffffffffffffffffffffffffffffffff16858760405161405e9190615ca1565b60006040518083038185875af1925050503d806000811461409b576040519150601f19603f3d011682016040523d82523d6000602084013e6140a0565b606091505b50915091506140b08282866144c7565b979650505050505050565b80516060908067ffffffffffffffff8111156140d9576140d9614eb6565b60405190808252806020026020018201604052801561411e57816020015b60408051808201909152606080825260208201528152602001906001900390816140f75790505b50915060005b818110156141a057604051806040016040528085838151811061414957614149615c2d565b6020026020010151815260200161417886848151811061416b5761416b615c2d565b602002602001015161451a565b81525083828151811061418d5761418d615c2d565b6020908102919091010152600101614124565b5050919050565b606080604051905082518060011b603f8101601f1916830160405280835250602084016020830160005b838110156141ff578060011b82018184015160001a8060041c8253600f8116600183015350506001016141d1565b509295945050505050565b6060600080600061421a8561452d565b91945092509050600081600181111561423557614235615655565b1461426c576040517f1ff9b2e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614276828461553d565b8551146142af576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612fbc856020015184846149cb565b606060208260000151106142da576142d58261420a565b612328565b61232882614a5f565b606061232861430283602001516000815181106133d6576133d6615c2d565b6141a7565b6060825182106143265750604080516020810190915260008152612328565b612d9d8383848651614338919061556e565b614a75565b6000808251845110614350578251614353565b83515b90505b80821080156143da575082828151811061437257614372615c2d565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168483815181106143b1576143b1615c2d565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b156143ea57816001019150614356565b5092915050565b600080821161445c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401611807565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b606083156144d6575081612d9d565b8251156144e65782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161180791906152fb565b606061232861452883614c4d565b614cba565b60008060008360000151600003614570576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020840151805160001a607f81116145955760006001600094509450945050506149c4565b60b781116146ab5760006145aa60808361556e565b9050808760000151116145e9576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001838101517fff0000000000000000000000000000000000000000000000000000000000000016908214801561466157507f80000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000008216105b15614698576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50600195509350600092506149c4915050565b60bf81116148095760006146c060b78361556e565b9050808760000151116146ff576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614761576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c603781116147a9576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6147b3818461553d565b8951116147ec576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6147f783600161553d565b97509550600094506149c49350505050565b60f7811161486e57600061481e60c08361556e565b90508087600001511161485d576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001955093508492506149c4915050565b600061487b60f78361556e565b9050808760000151116148ba576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff0000000000000000000000000000000000000000000000000000000000000016600081900361491c576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c60378111614964576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61496e818461553d565b8951116149a7576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6149b283600161553d565b97509550600194506149c49350505050565b9193909250565b60608167ffffffffffffffff8111156149e6576149e6614eb6565b6040519080825280601f01601f191660200182016040528015614a10576020820181803683370190505b5090508115612d9d576000614a25848661553d565b90506020820160005b84811015614a46578281015182820152602001614a2e565b84811115614a55576000858301525b5050509392505050565b60606123288260200151600084600001516149cb565b60608182601f011015614ae4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401611807565b828284011015614b50576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401611807565b81830184511015614bbd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401611807565b606082158015614bdc5760405191506000825260208201604052614c44565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015614c15578051835260209283019201614bfd565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b60408051808201909152600080825260208201528151600003614c9c576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50604080518082019091528151815260209182019181019190915290565b60606000806000614cca8561452d565b919450925090506001816001811115614ce557614ce5615655565b14614d1c576040517f4b9c6abe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8451614d28838561553d565b14614d5f576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516020808252610420820190925290816020015b6040805180820190915260008082526020820152815260200190600190039081614d765790505093506000835b8651811015614e6457600080614de96040518060400160405280858c60000151614dcd919061556e565b8152602001858c60200151614de2919061553d565b905261452d565b509150915060405180604001604052808383614e05919061553d565b8152602001848b60200151614e1a919061553d565b815250888581518110614e2f57614e2f615c2d565b6020908102919091010152614e4560018561553d565b9350614e51818361553d565b614e5b908461553d565b92505050614da3565b50845250919392505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461205757600080fd5b67ffffffffffffffff8116811461205757600080fd5b801515811461205757600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160c0810167ffffffffffffffff81118282101715614f0857614f08614eb6565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614f5557614f55614eb6565b604052919050565b600082601f830112614f6e57600080fd5b813567ffffffffffffffff811115614f8857614f88614eb6565b614fb960207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601614f0e565b818152846020838601011115614fce57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060008060c0878903121561500457600080fd5b863561500f81614e70565b95506020870135945060408701359350606087013561502d81614e92565b9250608087013561503d81614ea8565b915060a087013567ffffffffffffffff81111561505957600080fd5b61506589828a01614f5d565b9150509295509295509295565b600060c0828403121561508457600080fd5b60405160c0810167ffffffffffffffff82821081831117156150a8576150a8614eb6565b8160405282935084358352602085013591506150c382614e70565b816020840152604085013591506150d982614e70565b816040840152606085013560608401526080850135608084015260a085013591508082111561510757600080fd5b5061511485828601614f5d565b60a0830152505092915050565b6000806040838503121561513457600080fd5b823567ffffffffffffffff81111561514b57600080fd5b61515785828601615072565b925050602083013561516881614e70565b809150509250929050565b60006020828403121561518557600080fd5b8135612d9d81614e70565b600080600080600085870360e08112156151a957600080fd5b863567ffffffffffffffff808211156151c157600080fd5b6151cd8a838b01615072565b97506020890135965060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08401121561520657600080fd5b60408901955060c089013592508083111561522057600080fd5b828901925089601f84011261523457600080fd5b823591508082111561524557600080fd5b508860208260051b840101111561525b57600080fd5b959894975092955050506020019190565b60006020828403121561527e57600080fd5b5035919050565b60005b838110156152a0578181015183820152602001615288565b838111156129db5750506000910152565b600081518084526152c9816020860160208601615285565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000612d9d60208301846152b1565b6000806040838503121561532157600080fd5b82359150602083013561516881614e70565b60ff8116811461205757600080fd5b6000806000806080858703121561535857600080fd5b843561536381614e70565b9350602085013561537381615333565b93969395505050506040820135916060013590565b63ffffffff8116811461205757600080fd5b6000602082840312156153ac57600080fd5b8135612d9d81615388565b6000602082840312156153c957600080fd5b813567ffffffffffffffff8111156153e057600080fd5b6153ec84828501615072565b949350505050565b6000806000806080858703121561540a57600080fd5b843561541581614e70565b9350602085013561542581614e70565b9250604085013561543581614e70565b9150606085013561544581615388565b939692955090935050565b60006020828403121561546257600080fd5b8135612d9d81614e92565b6000806040838503121561548057600080fd5b50508035926020909101359150565b600080600080600060a086880312156154a757600080fd5b85356154b281614e70565b94506020860135935060408601356154c981614e92565b925060608601356154d981614ea8565b9150608086013567ffffffffffffffff8111156154f557600080fd5b61550188828901614f5d565b9150509295509295909350565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156155505761555061550e565b500190565b60006020828403121561556757600080fd5b5051919050565b6000828210156155805761558061550e565b500390565b60006020828403121561559757600080fd5b8151612d9d81614e70565b6000806000606084860312156155b757600080fd5b83516155c281615388565b60208501519093506155d381614e92565b60408501519092506155e481614e70565b809150509250925092565b60006080828403121561560157600080fd5b6040516080810181811067ffffffffffffffff8211171561562457615624614eb6565b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60006020828403121561569657600080fd5b815160038110612d9d57600080fd5b600067ffffffffffffffff808411156156c0576156c0614eb6565b8360051b60206156d1818301614f0e565b8681529185019181810190368411156156e957600080fd5b865b8481101561571d578035868111156157035760008081fd5b61570f36828b01614f5d565b8452509183019183016156eb565b50979650505050505050565b60006020828403121561573b57600080fd5b8151612d9d81614ea8565b60006020828403121561575857600080fd5b8151612d9d81614e92565b60006020828403121561577557600080fd5b8151612d9d81615388565b8581528460208201527fffffffffffffffff0000000000000000000000000000000000000000000000008460c01b16604082015282151560f81b6048820152600082516157d4816049850160208701615285565b919091016049019695505050505050565b600067ffffffffffffffff8083168185168183048111821515161561580c5761580c61550e565b02949350505050565b600067ffffffffffffffff8083168185168083038211156158385761583861550e565b01949350505050565b6000806040838503121561585457600080fd5b825161585f81614e70565b602084015190925061516881615333565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826158ae576158ae615870565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f8000000000000000000000000000000000000000000000000000000000000000831416156159025761590261550e565b500590565b6000808312837f8000000000000000000000000000000000000000000000000000000000000000018312811516156159415761594161550e565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0183138116156159755761597561550e565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6000841360008413858304851182821616156159bc576159bc61550e565b7f800000000000000000000000000000000000000000000000000000000000000060008712868205881281841616156159f7576159f761550e565b60008712925087820587128484161615615a1357615a1361550e565b87850587128184161615615a2957615a2961550e565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03841381151615615a7157615a7161550e565b827f8000000000000000000000000000000000000000000000000000000000000000038412811615615aa557615aa561550e565b50500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615ae357615ae361550e565b500290565b600082615af757615af7615870565b500490565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a0830152615b4760c08301846152b1565b98975050505050505050565b600060c08284031215615b6557600080fd5b615b6d614ee5565b8251615b7881615388565b81526020830151615b8881615333565b60208201526040830151615b9b81615333565b60408201526060830151615bae81615388565b60608201526080830151615bc181615388565b608082015260a08301516fffffffffffffffffffffffffffffffff81168114615be957600080fd5b60a08201529392505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203615c2657615c2661550e565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060ff831680615c6f57615c6f615870565b8060ff84160691505092915050565b600060ff821660ff841680821015615c9857615c9861550e565b90039392505050565b60008251615cb3818460208701615285565b919091019291505056fea164736f6c634300080f000a"; + bytes internal constant disputeGameFactoryCode = +- hex"6080604052600436106100e85760003560e01c80636593dc6e1161008a57806396cd97201161005957806396cd972014610313578063bb8aa1fc14610333578063c4d66de814610394578063f2fde38b146103b457600080fd5b80636593dc6e14610293578063715018a6146102c057806382ecf2f6146102d55780638da5cb5b146102e857600080fd5b8063254bd683116100c6578063254bd6831461019c5780634d1975b4146101c957806354fd4d50146101e85780635f0150cb1461023e57600080fd5b806314f6b1a3146100ed5780631b685b9e1461010f5780631e3342401461017c575b600080fd5b3480156100f957600080fd5b5061010d6101083660046110c6565b6103d4565b005b34801561011b57600080fd5b5061015261012a3660046110fd565b60656020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561018857600080fd5b5061010d610197366004611118565b61045e565b3480156101a857600080fd5b506101bc6101b7366004611142565b6104aa565b60405161017391906111ef565b3480156101d557600080fd5b506068545b604051908152602001610173565b3480156101f457600080fd5b506102316040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b60405161017391906112ac565b34801561024a57600080fd5b5061025e6102593660046112bf565b6106ee565b6040805173ffffffffffffffffffffffffffffffffffffffff909316835267ffffffffffffffff909116602083015201610173565b34801561029f57600080fd5b506101da6102ae3660046110fd565b60666020526000908152604090205481565b3480156102cc57600080fd5b5061010d610741565b6101526102e33660046112bf565b610755565b3480156102f457600080fd5b5060335473ffffffffffffffffffffffffffffffffffffffff16610152565b34801561031f57600080fd5b506101da61032e3660046112bf565b6109ef565b34801561033f57600080fd5b5061035361034e366004611346565b610a28565b6040805163ffffffff909416845267ffffffffffffffff909216602084015273ffffffffffffffffffffffffffffffffffffffff1690820152606001610173565b3480156103a057600080fd5b5061010d6103af36600461135f565b610a91565b3480156103c057600080fd5b5061010d6103cf36600461135f565b610c2d565b6103dc610d00565b63ffffffff821660008181526065602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8616908117909155905190917fff513d80e2c7fa487608f70a618dfbc0cf415699dc69588c747e8c71566c88de91a35050565b610466610d00565b63ffffffff8216600081815260666020526040808220849055518392917f74d6665c4b26d5596a5aa13d3014e0c06af4d322075a797f87b03cd4c5bc91ca91a35050565b606854606090831015806104bc575081155b6106e7575060408051600583901b8101602001909152825b8381116106e5576000606882815481106104f0576104f061137c565b600091825260209091200154905060e081901c60a082901c67ffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff831663ffffffff891683036106b6576001865101865260008173ffffffffffffffffffffffffffffffffffffffff1663609d33346040518163ffffffff1660e01b8152600401600060405180830381865afa15801561058a573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526105d091908101906113da565b905060008273ffffffffffffffffffffffffffffffffffffffff1663bcef3b556040518163ffffffff1660e01b8152600401602060405180830381865afa15801561061f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064391906114a5565b90506040518060a001604052808881526020018781526020018567ffffffffffffffff168152602001828152602001838152508860018a5161068591906114be565b815181106106955761069561137c565b6020026020010181905250888851106106b3575050505050506106e5565b50505b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90920191506104d49050565b505b9392505050565b60008060006106ff878787876109ef565b60009081526067602052604090205473ffffffffffffffffffffffffffffffffffffffff81169860a09190911c67ffffffffffffffff16975095505050505050565b610749610d00565b6107536000610d81565b565b63ffffffff841660009081526065602052604081205473ffffffffffffffffffffffffffffffffffffffff16806107c5576040517f031c6de400000000000000000000000000000000000000000000000000000000815263ffffffff871660048201526024015b60405180910390fd5b63ffffffff86166000908152606660205260409020543414610813576040517f8620aa1900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006108206001436114be565b40905061088a338783888860405160200161083f9594939291906114fc565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905273ffffffffffffffffffffffffffffffffffffffff841690610df8565b92508273ffffffffffffffffffffffffffffffffffffffff16638129fc1c346040518263ffffffff1660e01b81526004016000604051808303818588803b1580156108d457600080fd5b505af11580156108e8573d6000803e3d6000fd5b505050505060006108fb888888886109ef565b60008181526067602052604090205490915015610947576040517f014f6fe5000000000000000000000000000000000000000000000000000000008152600481018290526024016107bc565b60004260a01b60e08a901b178517600083815260676020526040808220839055606880546001810182559083527fa2153420d844928b4421650203c77babc8b33d7f2e7b450e2966db0c220977530183905551919250899163ffffffff8c169173ffffffffffffffffffffffffffffffffffffffff8916917f5b565efe82411da98814f356d0e7bcb8f0219b8d970307c5afb4a6903a8b2e359190a450505050949350505050565b600084848484604051602001610a089493929190611549565b604051602081830303815290604052805190602001209050949350505050565b600080600080600080610a8160688881548110610a4757610a4761137c565b906000526020600020015460e081901c9160a082901c67ffffffffffffffff169173ffffffffffffffffffffffffffffffffffffffff1690565b9199909850909650945050505050565b600054610100900460ff1615808015610ab15750600054600160ff909116105b80610acb5750303b158015610acb575060005460ff166001145b610b57576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016107bc565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610bb557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610bbd610e06565b610bc682610d81565b8015610c2957600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b610c35610d00565b73ffffffffffffffffffffffffffffffffffffffff8116610cd8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016107bc565b610ce181610d81565b50565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b60335473ffffffffffffffffffffffffffffffffffffffff163314610753576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016107bc565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60006106e760008484610ea5565b600054610100900460ff16610e9d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016107bc565b610753610feb565b600060608203516040830351602084035184518060208701018051600283016c5af43d3d93803e606057fd5bf3895289600d8a035278593da1005b363d3d373d3d3d3d610000806062363936013d738160481b1760218a03527f9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff603a8a035272fd6100003d81600a3d39f336602c57343d527f6062820160781b1761ff9e82106059018a03528060f01b8352606c8101604c8a038cf097505086610f715763301164256000526004601cfd5b905285527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08501527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08401527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa09092019190915292915050565b600054610100900460ff16611082576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016107bc565b61075333610d81565b803563ffffffff8116811461109f57600080fd5b919050565b73ffffffffffffffffffffffffffffffffffffffff81168114610ce157600080fd5b600080604083850312156110d957600080fd5b6110e28361108b565b915060208301356110f2816110a4565b809150509250929050565b60006020828403121561110f57600080fd5b6106e78261108b565b6000806040838503121561112b57600080fd5b6111348361108b565b946020939093013593505050565b60008060006060848603121561115757600080fd5b6111608461108b565b95602085013595506040909401359392505050565b60005b83811015611190578181015183820152602001611178565b8381111561119f576000848401525b50505050565b600081518084526111bd816020860160208601611175565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b8381101561129e578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc001855281518051845287810151888501528681015167ffffffffffffffff16878501526060808201519085015260809081015160a09185018290529061128a818601836111a5565b968901969450505090860190600101611216565b509098975050505050505050565b6020815260006106e760208301846111a5565b600080600080606085870312156112d557600080fd5b6112de8561108b565b935060208501359250604085013567ffffffffffffffff8082111561130257600080fd5b818701915087601f83011261131657600080fd5b81358181111561132557600080fd5b88602082850101111561133757600080fd5b95989497505060200194505050565b60006020828403121561135857600080fd5b5035919050565b60006020828403121561137157600080fd5b81356106e7816110a4565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156113ec57600080fd5b815167ffffffffffffffff8082111561140457600080fd5b818401915084601f83011261141857600080fd5b81518181111561142a5761142a6113ab565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611470576114706113ab565b8160405282815287602084870101111561148957600080fd5b61149a836020830160208801611175565b979650505050505050565b6000602082840312156114b757600080fd5b5051919050565b6000828210156114f7577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b500390565b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008660601b1681528460148201528360348201528183605483013760009101605401908152949350505050565b63ffffffff8516815283602082015260606040820152816060820152818360808301376000818301608090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101939250505056fea164736f6c634300080f000a"; ++ hex"6080604052600436106100e85760003560e01c80636593dc6e1161008a57806396cd97201161005957806396cd972014610313578063bb8aa1fc14610333578063c4d66de814610394578063f2fde38b146103b457600080fd5b80636593dc6e14610293578063715018a6146102c057806382ecf2f6146102d55780638da5cb5b146102e857600080fd5b8063254bd683116100c6578063254bd6831461019c5780634d1975b4146101c957806354fd4d50146101e85780635f0150cb1461023e57600080fd5b806314f6b1a3146100ed5780631b685b9e1461010f5780631e3342401461017c575b600080fd5b3480156100f957600080fd5b5061010d6101083660046110c6565b6103d4565b005b34801561011b57600080fd5b5061015261012a3660046110fd565b60656020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561018857600080fd5b5061010d610197366004611118565b61045e565b3480156101a857600080fd5b506101bc6101b7366004611142565b6104aa565b60405161017391906111ef565b3480156101d557600080fd5b506068545b604051908152602001610173565b3480156101f457600080fd5b506102316040518060400160405280600c81526020017f312e302e312d626574612e31000000000000000000000000000000000000000081525081565b60405161017391906112ac565b34801561024a57600080fd5b5061025e6102593660046112bf565b6106ee565b6040805173ffffffffffffffffffffffffffffffffffffffff909316835267ffffffffffffffff909116602083015201610173565b34801561029f57600080fd5b506101da6102ae3660046110fd565b60666020526000908152604090205481565b3480156102cc57600080fd5b5061010d610741565b6101526102e33660046112bf565b610755565b3480156102f457600080fd5b5060335473ffffffffffffffffffffffffffffffffffffffff16610152565b34801561031f57600080fd5b506101da61032e3660046112bf565b6109ef565b34801561033f57600080fd5b5061035361034e366004611346565b610a28565b6040805163ffffffff909416845267ffffffffffffffff909216602084015273ffffffffffffffffffffffffffffffffffffffff1690820152606001610173565b3480156103a057600080fd5b5061010d6103af36600461135f565b610a91565b3480156103c057600080fd5b5061010d6103cf36600461135f565b610c2d565b6103dc610d00565b63ffffffff821660008181526065602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8616908117909155905190917fff513d80e2c7fa487608f70a618dfbc0cf415699dc69588c747e8c71566c88de91a35050565b610466610d00565b63ffffffff8216600081815260666020526040808220849055518392917f74d6665c4b26d5596a5aa13d3014e0c06af4d322075a797f87b03cd4c5bc91ca91a35050565b606854606090831015806104bc575081155b6106e7575060408051600583901b8101602001909152825b8381116106e5576000606882815481106104f0576104f061137c565b600091825260209091200154905060e081901c60a082901c67ffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff831663ffffffff891683036106b6576001865101865260008173ffffffffffffffffffffffffffffffffffffffff1663609d33346040518163ffffffff1660e01b8152600401600060405180830381865afa15801561058a573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526105d091908101906113da565b905060008273ffffffffffffffffffffffffffffffffffffffff1663bcef3b556040518163ffffffff1660e01b8152600401602060405180830381865afa15801561061f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064391906114a5565b90506040518060a001604052808881526020018781526020018567ffffffffffffffff168152602001828152602001838152508860018a5161068591906114be565b815181106106955761069561137c565b6020026020010181905250888851106106b3575050505050506106e5565b50505b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90920191506104d49050565b505b9392505050565b60008060006106ff878787876109ef565b60009081526067602052604090205473ffffffffffffffffffffffffffffffffffffffff81169860a09190911c67ffffffffffffffff16975095505050505050565b610749610d00565b6107536000610d81565b565b63ffffffff841660009081526065602052604081205473ffffffffffffffffffffffffffffffffffffffff16806107c5576040517f031c6de400000000000000000000000000000000000000000000000000000000815263ffffffff871660048201526024015b60405180910390fd5b63ffffffff86166000908152606660205260409020543414610813576040517f8620aa1900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006108206001436114be565b40905061088a338783888860405160200161083f9594939291906114fc565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905273ffffffffffffffffffffffffffffffffffffffff841690610df8565b92508273ffffffffffffffffffffffffffffffffffffffff16638129fc1c346040518263ffffffff1660e01b81526004016000604051808303818588803b1580156108d457600080fd5b505af11580156108e8573d6000803e3d6000fd5b505050505060006108fb888888886109ef565b60008181526067602052604090205490915015610947576040517f014f6fe5000000000000000000000000000000000000000000000000000000008152600481018290526024016107bc565b60004260a01b60e08a901b178517600083815260676020526040808220839055606880546001810182559083527fa2153420d844928b4421650203c77babc8b33d7f2e7b450e2966db0c220977530183905551919250899163ffffffff8c169173ffffffffffffffffffffffffffffffffffffffff8916917f5b565efe82411da98814f356d0e7bcb8f0219b8d970307c5afb4a6903a8b2e359190a450505050949350505050565b600084848484604051602001610a089493929190611549565b604051602081830303815290604052805190602001209050949350505050565b600080600080600080610a8160688881548110610a4757610a4761137c565b906000526020600020015460e081901c9160a082901c67ffffffffffffffff169173ffffffffffffffffffffffffffffffffffffffff1690565b9199909850909650945050505050565b600054610100900460ff1615808015610ab15750600054600160ff909116105b80610acb5750303b158015610acb575060005460ff166001145b610b57576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016107bc565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610bb557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610bbd610e06565b610bc682610d81565b8015610c2957600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b610c35610d00565b73ffffffffffffffffffffffffffffffffffffffff8116610cd8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016107bc565b610ce181610d81565b50565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b60335473ffffffffffffffffffffffffffffffffffffffff163314610753576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016107bc565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60006106e760008484610ea5565b600054610100900460ff16610e9d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016107bc565b610753610feb565b600060608203516040830351602084035184518060208701018051600283016c5af43d3d93803e606057fd5bf3895289600d8a035278593da1005b363d3d373d3d3d3d610000806062363936013d738160481b1760218a03527f9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff603a8a035272fd6100003d81600a3d39f336602c57343d527f6062820160781b1761ff9e82106059018a03528060f01b8352606c8101604c8a038cf097505086610f715763301164256000526004601cfd5b905285527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08501527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08401527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa09092019190915292915050565b600054610100900460ff16611082576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016107bc565b61075333610d81565b803563ffffffff8116811461109f57600080fd5b919050565b73ffffffffffffffffffffffffffffffffffffffff81168114610ce157600080fd5b600080604083850312156110d957600080fd5b6110e28361108b565b915060208301356110f2816110a4565b809150509250929050565b60006020828403121561110f57600080fd5b6106e78261108b565b6000806040838503121561112b57600080fd5b6111348361108b565b946020939093013593505050565b60008060006060848603121561115757600080fd5b6111608461108b565b95602085013595506040909401359392505050565b60005b83811015611190578181015183820152602001611178565b8381111561119f576000848401525b50505050565b600081518084526111bd816020860160208601611175565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b8381101561129e578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc001855281518051845287810151888501528681015167ffffffffffffffff16878501526060808201519085015260809081015160a09185018290529061128a818601836111a5565b968901969450505090860190600101611216565b509098975050505050505050565b6020815260006106e760208301846111a5565b600080600080606085870312156112d557600080fd5b6112de8561108b565b935060208501359250604085013567ffffffffffffffff8082111561130257600080fd5b818701915087601f83011261131657600080fd5b81358181111561132557600080fd5b88602082850101111561133757600080fd5b95989497505060200194505050565b60006020828403121561135857600080fd5b5035919050565b60006020828403121561137157600080fd5b81356106e7816110a4565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156113ec57600080fd5b815167ffffffffffffffff8082111561140457600080fd5b818401915084601f83011261141857600080fd5b81518181111561142a5761142a6113ab565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611470576114706113ab565b8160405282815287602084870101111561148957600080fd5b61149a836020830160208801611175565b979650505050505050565b6000602082840312156114b757600080fd5b5051919050565b6000828210156114f7577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b500390565b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008660601b1681528460148201528360348201528183605483013760009101605401908152949350505050565b63ffffffff8516815283602082015260606040820152816060820152818360808301376000818301608090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101939250505056fea164736f6c634300080f000a"; + bytes internal constant delayedWETHCode = +- hex"6080604052600436106101845760003560e01c8063715018a6116100d6578063a9059cbb1161007f578063dd62ed3e11610059578063dd62ed3e1461051c578063f2fde38b14610554578063f3fef3a31461057457610193565b8063a9059cbb146104a8578063cd47bde1146104c8578063d0e30db01461019357610193565b80638da5cb5b116100b05780638da5cb5b1461041757806395d89b4114610442578063977a5ec51461048857610193565b8063715018a61461039057806379502c55146103a55780637eee288d146103f757610193565b80632e1a7d4d1161013857806354fd4d501161011257806354fd4d50146102e75780636a42b8f81461033057806370a082311461036357610193565b80632e1a7d4d14610280578063313ce567146102a0578063485cc955146102c757610193565b80630ca35682116101695780630ca356821461022357806318160ddd1461024357806323b872dd1461026057610193565b806306fdde031461019b578063095ea7b3146101f357610193565b3661019357610191610594565b005b610191610594565b3480156101a757600080fd5b5060408051808201909152600d81527f577261707065642045746865720000000000000000000000000000000000000060208201525b6040516101ea91906113fd565b60405180910390f35b3480156101ff57600080fd5b5061021361020e366004611492565b6105ef565b60405190151581526020016101ea565b34801561022f57600080fd5b5061019161023e3660046114be565b610668565b34801561024f57600080fd5b50475b6040519081526020016101ea565b34801561026c57600080fd5b5061021361027b3660046114d7565b6107b9565b34801561028c57600080fd5b5061019161029b3660046114be565b6109d0565b3480156102ac57600080fd5b506102b5601281565b60405160ff90911681526020016101ea565b3480156102d357600080fd5b506101916102e2366004611518565b6109dd565b3480156102f357600080fd5b506101dd6040518060400160405280600a81526020017f312e312e302d72632e310000000000000000000000000000000000000000000081525081565b34801561033c57600080fd5b507f0000000000000000000000000000000000000000000000000000000000093a80610252565b34801561036f57600080fd5b5061025261037e366004611551565b60656020526000908152604090205481565b34801561039c57600080fd5b50610191610bb9565b3480156103b157600080fd5b506068546103d29073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101ea565b34801561040357600080fd5b50610191610412366004611492565b610bcd565b34801561042357600080fd5b5060335473ffffffffffffffffffffffffffffffffffffffff166103d2565b34801561044e57600080fd5b5060408051808201909152600481527f574554480000000000000000000000000000000000000000000000000000000060208201526101dd565b34801561049457600080fd5b506101916104a3366004611492565b610c21565b3480156104b457600080fd5b506102136104c3366004611492565b610d0e565b3480156104d457600080fd5b506105076104e3366004611518565b60676020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152016101ea565b34801561052857600080fd5b50610252610537366004611518565b606660209081526000928352604080842090915290825290205481565b34801561056057600080fd5b5061019161056f366004611551565b610d22565b34801561058057600080fd5b5061019161058f366004611492565b610dd6565b33600090815260656020526040812080543492906105b390849061159d565b909155505060405134815233907fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9060200160405180910390a2565b33600081815260666020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906106579086815260200190565b60405180910390a350600192915050565b60335473ffffffffffffffffffffffffffffffffffffffff1633146106ee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f44656c61796564574554483a206e6f74206f776e65720000000000000000000060448201526064015b60405180910390fd5b60004782106106fd57476106ff565b815b604051909150600090339083908381818185875af1925050503d8060008114610744576040519150601f19603f3d011682016040523d82523d6000602084013e610749565b606091505b50509050806107b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f44656c61796564574554483a207265636f766572206661696c6564000000000060448201526064016106e5565b505050565b73ffffffffffffffffffffffffffffffffffffffff83166000908152606560205260408120548211156107eb57600080fd5b73ffffffffffffffffffffffffffffffffffffffff84163314801590610861575073ffffffffffffffffffffffffffffffffffffffff841660009081526066602090815260408083203384529091529020547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14155b156108e95773ffffffffffffffffffffffffffffffffffffffff841660009081526066602090815260408083203384529091529020548211156108a357600080fd5b73ffffffffffffffffffffffffffffffffffffffff84166000908152606660209081526040808320338452909152812080548492906108e39084906115b5565b90915550505b73ffffffffffffffffffffffffffffffffffffffff84166000908152606560205260408120805484929061091e9084906115b5565b909155505073ffffffffffffffffffffffffffffffffffffffff83166000908152606560205260408120805484929061095890849061159d565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516109be91815260200190565b60405180910390a35060019392505050565b6109da3382610dd6565b50565b600054610100900460ff16158080156109fd5750600054600160ff909116105b80610a175750303b158015610a17575060005460ff166001145b610aa3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016106e5565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610b0157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610b09611120565b610b12836111bf565b606880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff841617905580156107b457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a1505050565b610bc1611236565b610bcb60006111bf565b565b33600090815260676020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091528120426001820155805490918391839190610c1790849061159d565b9091555050505050565b60335473ffffffffffffffffffffffffffffffffffffffff163314610ca2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f44656c61796564574554483a206e6f74206f776e65720000000000000000000060448201526064016106e5565b73ffffffffffffffffffffffffffffffffffffffff821660008181526066602090815260408083203380855290835292819020859055518481529192917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a35050565b6000610d1b3384846107b9565b9392505050565b610d2a611236565b73ffffffffffffffffffffffffffffffffffffffff8116610dcd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016106e5565b6109da816111bf565b606860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e6791906115cc565b15610ece576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f44656c61796564574554483a20636f6e7472616374206973207061757365640060448201526064016106e5565b33600090815260676020908152604080832073ffffffffffffffffffffffffffffffffffffffff8616845290915290208054821115610f8f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f44656c61796564574554483a20696e73756666696369656e7420756e6c6f636b60448201527f6564207769746864726177616c0000000000000000000000000000000000000060648201526084016106e5565b6000816001015411611022576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f44656c61796564574554483a207769746864726177616c206e6f7420756e6c6f60448201527f636b65640000000000000000000000000000000000000000000000000000000060648201526084016106e5565b427f0000000000000000000000000000000000000000000000000000000000093a808260010154611053919061159d565b11156110e1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f44656c61796564574554483a207769746864726177616c2064656c6179206e6f60448201527f74206d657400000000000000000000000000000000000000000000000000000060648201526084016106e5565b818160000160008282546110f591906115b5565b909155506107b49050826112b7565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b600054610100900460ff166111b7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016106e5565b610bcb61135d565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60335473ffffffffffffffffffffffffffffffffffffffff163314610bcb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106e5565b336000908152606560205260409020548111156112d357600080fd5b33600090815260656020526040812080548392906112f29084906115b5565b9091555050604051339082156108fc029083906000818181858888f19350505050158015611324573d6000803e3d6000fd5b5060405181815233907f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b659060200160405180910390a250565b600054610100900460ff166113f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016106e5565b610bcb336111bf565b600060208083528351808285015260005b8181101561142a5785810183015185820160400152820161140e565b8181111561143c576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b73ffffffffffffffffffffffffffffffffffffffff811681146109da57600080fd5b600080604083850312156114a557600080fd5b82356114b081611470565b946020939093013593505050565b6000602082840312156114d057600080fd5b5035919050565b6000806000606084860312156114ec57600080fd5b83356114f781611470565b9250602084013561150781611470565b929592945050506040919091013590565b6000806040838503121561152b57600080fd5b823561153681611470565b9150602083013561154681611470565b809150509250929050565b60006020828403121561156357600080fd5b8135610d1b81611470565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156115b0576115b061156e565b500190565b6000828210156115c7576115c761156e565b500390565b6000602082840312156115de57600080fd5b81518015158114610d1b57600080fdfea164736f6c634300080f000a"; ++ hex"6080604052600436106101845760003560e01c8063715018a6116100d6578063a9059cbb1161007f578063dd62ed3e11610059578063dd62ed3e1461051c578063f2fde38b14610554578063f3fef3a31461057457610193565b8063a9059cbb146104a8578063cd47bde1146104c8578063d0e30db01461019357610193565b80638da5cb5b116100b05780638da5cb5b1461041757806395d89b4114610442578063977a5ec51461048857610193565b8063715018a61461039057806379502c55146103a55780637eee288d146103f757610193565b80632e1a7d4d1161013857806354fd4d501161011257806354fd4d50146102e75780636a42b8f81461033057806370a082311461036357610193565b80632e1a7d4d14610280578063313ce567146102a0578063485cc955146102c757610193565b80630ca35682116101695780630ca356821461022357806318160ddd1461024357806323b872dd1461026057610193565b806306fdde031461019b578063095ea7b3146101f357610193565b3661019357610191610594565b005b610191610594565b3480156101a757600080fd5b5060408051808201909152600d81527f577261707065642045746865720000000000000000000000000000000000000060208201525b6040516101ea91906113fd565b60405180910390f35b3480156101ff57600080fd5b5061021361020e366004611492565b6105ef565b60405190151581526020016101ea565b34801561022f57600080fd5b5061019161023e3660046114be565b610668565b34801561024f57600080fd5b50475b6040519081526020016101ea565b34801561026c57600080fd5b5061021361027b3660046114d7565b6107b9565b34801561028c57600080fd5b5061019161029b3660046114be565b6109d0565b3480156102ac57600080fd5b506102b5601281565b60405160ff90911681526020016101ea565b3480156102d357600080fd5b506101916102e2366004611518565b6109dd565b3480156102f357600080fd5b506101dd6040518060400160405280600c81526020017f312e312e312d626574612e32000000000000000000000000000000000000000081525081565b34801561033c57600080fd5b507f0000000000000000000000000000000000000000000000000000000000093a80610252565b34801561036f57600080fd5b5061025261037e366004611551565b60656020526000908152604090205481565b34801561039c57600080fd5b50610191610bb9565b3480156103b157600080fd5b506068546103d29073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101ea565b34801561040357600080fd5b50610191610412366004611492565b610bcd565b34801561042357600080fd5b5060335473ffffffffffffffffffffffffffffffffffffffff166103d2565b34801561044e57600080fd5b5060408051808201909152600481527f574554480000000000000000000000000000000000000000000000000000000060208201526101dd565b34801561049457600080fd5b506101916104a3366004611492565b610c21565b3480156104b457600080fd5b506102136104c3366004611492565b610d0e565b3480156104d457600080fd5b506105076104e3366004611518565b60676020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152016101ea565b34801561052857600080fd5b50610252610537366004611518565b606660209081526000928352604080842090915290825290205481565b34801561056057600080fd5b5061019161056f366004611551565b610d22565b34801561058057600080fd5b5061019161058f366004611492565b610dd6565b33600090815260656020526040812080543492906105b390849061159d565b909155505060405134815233907fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9060200160405180910390a2565b33600081815260666020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906106579086815260200190565b60405180910390a350600192915050565b60335473ffffffffffffffffffffffffffffffffffffffff1633146106ee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f44656c61796564574554483a206e6f74206f776e65720000000000000000000060448201526064015b60405180910390fd5b60004782106106fd57476106ff565b815b604051909150600090339083908381818185875af1925050503d8060008114610744576040519150601f19603f3d011682016040523d82523d6000602084013e610749565b606091505b50509050806107b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f44656c61796564574554483a207265636f766572206661696c6564000000000060448201526064016106e5565b505050565b73ffffffffffffffffffffffffffffffffffffffff83166000908152606560205260408120548211156107eb57600080fd5b73ffffffffffffffffffffffffffffffffffffffff84163314801590610861575073ffffffffffffffffffffffffffffffffffffffff841660009081526066602090815260408083203384529091529020547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14155b156108e95773ffffffffffffffffffffffffffffffffffffffff841660009081526066602090815260408083203384529091529020548211156108a357600080fd5b73ffffffffffffffffffffffffffffffffffffffff84166000908152606660209081526040808320338452909152812080548492906108e39084906115b5565b90915550505b73ffffffffffffffffffffffffffffffffffffffff84166000908152606560205260408120805484929061091e9084906115b5565b909155505073ffffffffffffffffffffffffffffffffffffffff83166000908152606560205260408120805484929061095890849061159d565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516109be91815260200190565b60405180910390a35060019392505050565b6109da3382610dd6565b50565b600054610100900460ff16158080156109fd5750600054600160ff909116105b80610a175750303b158015610a17575060005460ff166001145b610aa3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016106e5565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610b0157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610b09611120565b610b12836111bf565b606880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff841617905580156107b457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a1505050565b610bc1611236565b610bcb60006111bf565b565b33600090815260676020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091528120426001820155805490918391839190610c1790849061159d565b9091555050505050565b60335473ffffffffffffffffffffffffffffffffffffffff163314610ca2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f44656c61796564574554483a206e6f74206f776e65720000000000000000000060448201526064016106e5565b73ffffffffffffffffffffffffffffffffffffffff821660008181526066602090815260408083203380855290835292819020859055518481529192917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a35050565b6000610d1b3384846107b9565b9392505050565b610d2a611236565b73ffffffffffffffffffffffffffffffffffffffff8116610dcd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016106e5565b6109da816111bf565b606860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e6791906115cc565b15610ece576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f44656c61796564574554483a20636f6e7472616374206973207061757365640060448201526064016106e5565b33600090815260676020908152604080832073ffffffffffffffffffffffffffffffffffffffff8616845290915290208054821115610f8f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f44656c61796564574554483a20696e73756666696369656e7420756e6c6f636b60448201527f6564207769746864726177616c0000000000000000000000000000000000000060648201526084016106e5565b6000816001015411611022576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f44656c61796564574554483a207769746864726177616c206e6f7420756e6c6f60448201527f636b65640000000000000000000000000000000000000000000000000000000060648201526084016106e5565b427f0000000000000000000000000000000000000000000000000000000000093a808260010154611053919061159d565b11156110e1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f44656c61796564574554483a207769746864726177616c2064656c6179206e6f60448201527f74206d657400000000000000000000000000000000000000000000000000000060648201526084016106e5565b818160000160008282546110f591906115b5565b909155506107b49050826112b7565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b600054610100900460ff166111b7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016106e5565b610bcb61135d565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60335473ffffffffffffffffffffffffffffffffffffffff163314610bcb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106e5565b336000908152606560205260409020548111156112d357600080fd5b33600090815260656020526040812080548392906112f29084906115b5565b9091555050604051339082156108fc029083906000818181858888f19350505050158015611324573d6000803e3d6000fd5b5060405181815233907f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b659060200160405180910390a250565b600054610100900460ff166113f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016106e5565b610bcb336111bf565b600060208083528351808285015260005b8181101561142a5785810183015185820160400152820161140e565b8181111561143c576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b73ffffffffffffffffffffffffffffffffffffffff811681146109da57600080fd5b600080604083850312156114a557600080fd5b82356114b081611470565b946020939093013593505050565b6000602082840312156114d057600080fd5b5035919050565b6000806000606084860312156114ec57600080fd5b83356114f781611470565b9250602084013561150781611470565b929592945050506040919091013590565b6000806040838503121561152b57600080fd5b823561153681611470565b9150602083013561154681611470565b809150509250929050565b60006020828403121561156357600080fd5b8135610d1b81611470565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156115b0576115b061156e565b500190565b6000828210156115c7576115c761156e565b500390565b6000602082840312156115de57600080fd5b81518015158114610d1b57600080fdfea164736f6c634300080f000a"; + bytes internal constant preimageOracleCode = +- hex"6080604052600436106101d85760003560e01c80639d53a64811610102578063ddcd58de11610095578063ec5efcbc11610064578063ec5efcbc14610681578063f3f480d9146106a1578063faf37bc7146106d4578063fef2b4ed146106e757600080fd5b8063ddcd58de146105d4578063e03110e11461060c578063e159261114610641578063ea7139501461066157600080fd5b8063b5e7154c116100d1578063b5e7154c14610555578063d18534b51461056c578063da35c6641461058c578063dd24f9bf146105a157600080fd5b80639d53a6481461048e5780639d7e8769146104dd578063b2e67ba8146104fd578063b4801e611461053557600080fd5b806361238bde1161017a5780637ac54767116101495780637ac54767146103ca5780638542cf50146103ea578063882856ef146104355780638dc4be111461046e57600080fd5b806361238bde1461031e5780636551927b146103565780637051472e1461038e5780637917de1d146103aa57600080fd5b80633909af5c116101b65780633909af5c146102715780634d52b4c91461029357806352f0f3ad146102a857806354fd4d50146102c857600080fd5b8063013cf08b146101dd5780630359a5631461022e5780632055b36b1461025c575b600080fd5b3480156101e957600080fd5b506101fd6101f8366004612e29565b610714565b6040805173ffffffffffffffffffffffffffffffffffffffff90931683526020830191909152015b60405180910390f35b34801561023a57600080fd5b5061024e610249366004612e6b565b610759565b604051908152602001610225565b34801561026857600080fd5b5061024e601081565b34801561027d57600080fd5b5061029161028c366004613073565b610891565b005b34801561029f57600080fd5b5061024e610ae8565b3480156102b457600080fd5b5061024e6102c336600461315f565b610b03565b3480156102d457600080fd5b506103116040518060400160405280600a81526020017f312e312e322d72632e310000000000000000000000000000000000000000000081525081565b60405161022591906131c6565b34801561032a57600080fd5b5061024e610339366004613217565b600160209081526000928352604080842090915290825290205481565b34801561036257600080fd5b5061024e610371366004612e6b565b601560209081526000928352604080842090915290825290205481565b34801561039a57600080fd5b5061024e6703782dace9d9000081565b3480156103b657600080fd5b506102916103c536600461327b565b610bd9565b3480156103d657600080fd5b5061024e6103e5366004612e29565b6110dc565b3480156103f657600080fd5b50610425610405366004613217565b600260209081526000928352604080842090915290825290205460ff1681565b6040519015158152602001610225565b34801561044157600080fd5b50610455610450366004613317565b6110f3565b60405167ffffffffffffffff9091168152602001610225565b34801561047a57600080fd5b5061029161048936600461334a565b61114d565b34801561049a57600080fd5b5061024e6104a9366004612e6b565b73ffffffffffffffffffffffffffffffffffffffff9091166000908152601860209081526040808320938352929052205490565b3480156104e957600080fd5b506102916104f8366004613396565b611248565b34801561050957600080fd5b5061024e610518366004612e6b565b601760209081526000928352604080842090915290825290205481565b34801561054157600080fd5b5061024e610550366004613317565b6113ff565b34801561056157600080fd5b5061024e620186a081565b34801561057857600080fd5b50610291610587366004613073565b611431565b34801561059857600080fd5b5060135461024e565b3480156105ad57600080fd5b507f000000000000000000000000000000000000000000000000000000000000271061024e565b3480156105e057600080fd5b5061024e6105ef366004612e6b565b601660209081526000928352604080842090915290825290205481565b34801561061857600080fd5b5061062c610627366004613217565b611840565b60408051928352602083019190915201610225565b34801561064d57600080fd5b5061029161065c36600461334a565b611931565b34801561066d57600080fd5b5061029161067c366004613422565b611a39565b34801561068d57600080fd5b5061029161069c366004613491565b611b98565b3480156106ad57600080fd5b507f000000000000000000000000000000000000000000000000000000000000007861024e565b6102916106e2366004613519565b611d1e565b3480156106f357600080fd5b5061024e610702366004612e29565b60006020819052908152604090205481565b6013818154811061072457600080fd5b60009182526020909120600290910201805460019091015473ffffffffffffffffffffffffffffffffffffffff909116915082565b73ffffffffffffffffffffffffffffffffffffffff82166000908152601560209081526040808320848452909152812054819061079c9060601c63ffffffff1690565b63ffffffff16905060005b6010811015610889578160011660010361082f5773ffffffffffffffffffffffffffffffffffffffff85166000908152601460209081526040808320878452909152902081601081106107fc576107fc613555565b01546040805160208101929092528101849052606001604051602081830303815290604052805190602001209250610870565b826003826010811061084357610843613555565b01546040805160208101939093528201526060016040516020818303038152906040528051906020012092505b60019190911c9080610881816135b3565b9150506107a7565b505092915050565b600061089d8a8a610759565b90506108c086868360208b01356108bb6108b68d6135eb565b611fea565b61202a565b80156108de57506108de83838360208801356108bb6108b68a6135eb565b610914576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b86604001358860405160200161092a91906136ba565b6040516020818303038152906040528051906020012014610977576040517f1968a90200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83602001358760200135600161098d91906136f8565b146109c4576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a0c886109d28680613710565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061208b92505050565b610a15886121e6565b836040013588604051602001610a2b91906136ba565b6040516020818303038152906040528051906020012003610a78576040517f9843145b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8a1660009081526015602090815260408083208c8452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000166001179055610adc8a8a3361298e565b50505050505050505050565b6001610af660106002613897565b610b0091906138a3565b81565b6000610b0f8686612a47565b9050610b1c8360086136f8565b82101580610b2a5750602083115b15610b61576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000602081815260c085901b82526008959095528251828252600286526040808320858452875280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558484528752808320948352938652838220558181529384905292205592915050565b60608115610bf257610beb8686612af4565b9050610c2c565b85858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050505b3360009081526014602090815260408083208b845290915280822081516102008101928390529160109082845b815481526020019060010190808311610c5957505050505090506000601560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008b81526020019081526020016000205490506000610cda8260601c63ffffffff1690565b63ffffffff169050333214610d1b576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d2b8260801c63ffffffff1690565b63ffffffff16600003610d6a576040517f87138d5c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d748260c01c90565b67ffffffffffffffff1615610db5576040517f475a253500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b898114610dee576040517f60f95d5a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610dfb89898d8886612b6d565b83516020850160888204881415608883061715610e20576307b1daf16000526004601cfd5b60405160c8810160405260005b83811015610ed0578083018051835260208101516020840152604081015160408401526060810151606084015260808101516080840152508460888301526088810460051b8b013560a883015260c882206001860195508560005b610200811015610ec5576001821615610ea55782818b0152610ec5565b8981015160009081526020938452604090209260019290921c9101610e88565b505050608801610e2d565b50505050600160106002610ee49190613897565b610eee91906138a3565b811115610f27576040517f6229572300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f9c610f3a8360401c63ffffffff1690565b610f4a9063ffffffff168a6136f8565b60401b7fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff606084901b167fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff8516171790565b915084156110295777ffffffffffffffffffffffffffffffffffffffffffffffff82164260c01b179150610fd68260801c63ffffffff1690565b63ffffffff16610fec8360401c63ffffffff1690565b63ffffffff1614611029576040517f7b1dafd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360009081526014602090815260408083208e8452909152902061104f90846010612d9f565b503360008181526018602090815260408083208f8452825280832080546001810182559084528284206004820401805460039092166008026101000a67ffffffffffffffff818102199093164390931602919091179055838352601582528083208f8452909152812084905560609190911b81523690601437366014016000a05050505050505050505050565b600381601081106110ec57600080fd5b0154905081565b6018602052826000526040600020602052816000526040600020818154811061111b57600080fd5b906000526020600020906004918282040191900660080292509250509054906101000a900467ffffffffffffffff1681565b60443560008060088301861061116b5763fe2549876000526004601cfd5b60c083901b60805260888386823786600882030151915060206000858360025afa90508061119857600080fd5b50600080517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0400000000000000000000000000000000000000000000000000000000000000178082526002602090815260408084208a8552825280842080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558385528252808420998452988152888320939093558152908190529490942055505050565b600080603087600037602060006030600060025afa806112705763f91129696000526004601cfd5b6000517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f010000000000000000000000000000000000000000000000000000000000000017608081815260a08c905260c08b905260308a60e037603088609083013760008060c083600a5afa9250826112f2576309bde3396000526004601cfd5b602886106113085763fe2549876000526004601cfd5b6000602882015278200000000000000000000000000000000000000000000000008152600881018b905285810151935060308a8237603081019b909b52505060509098207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0500000000000000000000000000000000000000000000000000000000000000176000818152600260209081526040808320868452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915584845282528083209583529481528482209a909a559081528089529190912096909655505050505050565b6014602052826000526040600020602052816000526040600020816010811061142757600080fd5b0154925083915050565b73ffffffffffffffffffffffffffffffffffffffff891660009081526015602090815260408083208b845290915290205467ffffffffffffffff8116156114a4576040517fc334f06900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6114ae8160c01c90565b67ffffffffffffffff166000036114f1576040517f55d4cbf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000007861151c8260c01c90565b6115309067ffffffffffffffff16426138a3565b11611567576040517f55d4cbf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006115738b8b610759565b905061158c87878360208c01356108bb6108b68e6135eb565b80156115aa57506115aa84848360208901356108bb6108b68b6135eb565b6115e0576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8760400135896040516020016115f691906136ba565b6040516020818303038152906040528051906020012014611643576040517f1968a90200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84602001358860200135600161165991906136f8565b14158061168b575060016116738360601c63ffffffff1690565b61167d91906138ba565b63ffffffff16856020013514155b156116c2576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6116d0896109d28780613710565b6116d9896121e6565b60006116e48a612cc0565b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0200000000000000000000000000000000000000000000000000000000000000179050600061173b8460a01c63ffffffff1690565b67ffffffffffffffff169050600160026000848152602001908152602001600020600083815260200190815260200160002060006101000a81548160ff021916908315150217905550601760008e73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008d8152602001908152602001600020546001600084815260200190815260200160002060008381526020019081526020016000208190555061180d8460801c63ffffffff1690565b600083815260208190526040902063ffffffff9190911690556118318d8d8161298e565b50505050505050505050505050565b6000828152600260209081526040808320848452909152812054819060ff166118c9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f7072652d696d616765206d757374206578697374000000000000000000000000604482015260640160405180910390fd5b50600083815260208181526040909120546118e58160086136f8565b6118f08560206136f8565b1061190e57836119018260086136f8565b61190b91906138a3565b91505b506000938452600160209081526040808620948652939052919092205492909150565b60443560008060088301861061194f5763fe2549876000526004601cfd5b60c083901b6080526088838682378087017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80151908490207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f02000000000000000000000000000000000000000000000000000000000000001760008181526002602090815260408083208b8452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915584845282528083209a83529981528982209390935590815290819052959095209190915550505050565b60008060008060808860601b81528760c01b6014820152858782601c0137601c860181207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0600000000000000000000000000000000000000000000000000000000000000179350604088026260216001603f5a021015611ac35763dd629f866000526004601cfd5b6000808783601c018c5afa94503d6001019150600882018a10611aee5763fe2549876000526004601cfd5b60c082901b81526008018481533d6000600183013e89017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8015160008481526002602090815260408083208d8452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915587845282528083209c83529b81528b8220929092559384528390529790912096909655505050505050565b6000611ba48686610759565b9050611bbd83838360208801356108bb6108b68a6135eb565b611bf3576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602084013515611c2f576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611c37612ddd565b611c45816109d28780613710565b611c4e816121e6565b846040013581604051602001611c6491906136ba565b6040516020818303038152906040528051906020012003611cb1576040517f9843145b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff87166000908152601560209081526040808320898452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000166001179055611d1587873361298e565b50505050505050565b6703782dace9d90000341015611d60576040517fe92c469f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b333214611d99576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611da48160086138df565b63ffffffff168263ffffffff1610611de8576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000027108163ffffffff161015611e48576040517f7b1dafd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000908152601560209081526040808320868452909152902054611e738160801c63ffffffff1690565b63ffffffff1615611eb0576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b608082901b7fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff60a085901b167fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff83161717336000818152601560209081526040808320898452825280832094909455835180850185528381528082018981526013805460018101825590855291517f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a090600290930292830180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909216919091179055517f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a0919091015591815260168252828120968152959052909320349055505050565b600081600001518260200151836040015160405160200161200d93929190613907565b604051602081830303815290604052805190602001209050919050565b60008160005b601081101561207e578060051b880135600186831c16600181146120635760008481526020839052604090209350612074565b600082815260208590526040902093505b5050600101612030565b5090931495945050505050565b608881511461209957600080fd5b602081016020830161211a565b8260031b8201518060001a8160011a60081b178160021a60101b8260031a60181b17178160041a60201b8260051a60281b178260061a60301b8360071a60381b1717179050612114816120ff868560059190911b015190565b1867ffffffffffffffff16600586901b840152565b50505050565b612126600083836120a6565b612132600183836120a6565b61213e600283836120a6565b61214a600383836120a6565b612156600483836120a6565b612162600583836120a6565b61216e600683836120a6565b61217a600783836120a6565b612186600883836120a6565b612192600983836120a6565b61219e600a83836120a6565b6121aa600b83836120a6565b6121b6600c83836120a6565b6121c2600d83836120a6565b6121ce600e83836120a6565b6121da600f83836120a6565b612114601083836120a6565b6040805178010000000000008082800000000000808a8000000080008000602082015279808b00000000800000018000000080008081800000000000800991810191909152788a00000000000000880000000080008009000000008000000a60608201527b8000808b800000000000008b8000000000008089800000000000800360808201527f80000000000080028000000000000080000000000000800a800000008000000a60a08201527f800000008000808180000000000080800000000080000001800000008000800860c082015260009060e0016040516020818303038152906040529050602082016020820161286e565b6102808101516101e082015161014083015160a0840151845118189118186102a082015161020083015161016084015160c0850151602086015118189118186102c083015161022084015161018085015160e0860151604087015118189118186102e08401516102408501516101a0860151610100870151606088015118189118186103008501516102608601516101c0870151610120880151608089015118189118188084603f1c6123998660011b67ffffffffffffffff1690565b18188584603f1c6123b48660011b67ffffffffffffffff1690565b18188584603f1c6123cf8660011b67ffffffffffffffff1690565b181895508483603f1c6123ec8560011b67ffffffffffffffff1690565b181894508387603f1c6124098960011b67ffffffffffffffff1690565b60208b01518b51861867ffffffffffffffff168c5291189190911897508118600181901b603f9190911c18935060c08801518118601481901c602c9190911b1867ffffffffffffffff1660208901526101208801518718602c81901c60149190911b1867ffffffffffffffff1660c08901526102c08801518618600381901c603d9190911b1867ffffffffffffffff166101208901526101c08801518718601981901c60279190911b1867ffffffffffffffff166102c08901526102808801518218602e81901c60129190911b1867ffffffffffffffff166101c089015260408801518618600281901c603e9190911b1867ffffffffffffffff166102808901526101808801518618601581901c602b9190911b1867ffffffffffffffff1660408901526101a08801518518602781901c60199190911b1867ffffffffffffffff166101808901526102608801518718603881901c60089190911b1867ffffffffffffffff166101a08901526102e08801518518600881901c60389190911b1867ffffffffffffffff166102608901526101e08801518218601781901c60299190911b1867ffffffffffffffff166102e089015260808801518718602581901c601b9190911b1867ffffffffffffffff166101e08901526103008801518718603281901c600e9190911b1867ffffffffffffffff1660808901526102a08801518118603e81901c60029190911b1867ffffffffffffffff166103008901526101008801518518600981901c60379190911b1867ffffffffffffffff166102a08901526102008801518118601381901c602d9190911b1867ffffffffffffffff1661010089015260a08801518218601c81901c60249190911b1867ffffffffffffffff1661020089015260608801518518602481901c601c9190911b1867ffffffffffffffff1660a08901526102408801518518602b81901c60159190911b1867ffffffffffffffff1660608901526102208801518618603181901c600f9190911b1867ffffffffffffffff166102408901526101608801518118603681901c600a9190911b1867ffffffffffffffff166102208901525060e08701518518603a81901c60069190911b1867ffffffffffffffff166101608801526101408701518118603d81901c60039190911b1867ffffffffffffffff1660e0880152505067ffffffffffffffff81166101408601525b5050505050565b600582811b8201805160018501831b8401805160028701851b8601805160038901871b8801805160048b0190981b8901805167ffffffffffffffff861985168918811690995283198a16861889169096528819861683188816909352841986168818871690528419831684189095169052919391929190611d15565b612808600082612781565b612813600582612781565b61281e600a82612781565b612829600f82612781565b612834601482612781565b50565b612840816122dc565b612849816127fd565b600383901b820151815160c09190911c9061211490821867ffffffffffffffff168352565b61287a60008284612837565b61288660018284612837565b61289260028284612837565b61289e60038284612837565b6128aa60048284612837565b6128b660058284612837565b6128c260068284612837565b6128ce60078284612837565b6128da60088284612837565b6128e660098284612837565b6128f2600a8284612837565b6128fe600b8284612837565b61290a600c8284612837565b612916600d8284612837565b612922600e8284612837565b61292e600f8284612837565b61293a60108284612837565b61294660118284612837565b61295260128284612837565b61295e60138284612837565b61296a60148284612837565b61297660158284612837565b61298260168284612837565b61211460178284612837565b73ffffffffffffffffffffffffffffffffffffffff83811660009081526016602090815260408083208684529091528082208054908390559051909284169083908381818185875af1925050503d8060008114612a07576040519150601f19603f3d011682016040523d82523d6000602084013e612a0c565b606091505b505090508061277a576040517f83e6cc6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f01000000000000000000000000000000000000000000000000000000000000007effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831617612aed818360408051600093845233602052918152606090922091527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001790565b9392505050565b6060604051905081602082018181018286833760888306808015612b3d5760888290038501848101848103803687375060806001820353506001845160001a1784538652612b54565b608836843760018353608060878401536088850186525b5050505050601f19603f82510116810160405292915050565b6000612b7f8260a01c63ffffffff1690565b67ffffffffffffffff1690506000612b9d8360801c63ffffffff1690565b63ffffffff1690506000612bb78460401c63ffffffff1690565b63ffffffff169050600883108015612bcd575080155b15612c015760c082901b6000908152883560085283513382526017602090815260408084208a855290915290912055612cb6565b60088310158015612c1f575080612c196008856138a3565b93508310155b8015612c335750612c3087826136f8565b83105b15612cb6576000612c4482856138a3565b905087612c528260206136f8565b10158015612c5e575085155b15612c95576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360009081526017602090815260408083208a845290915290209089013590555b5050505050505050565b6000612d43565b66ff00ff00ff00ff8160081c1667ff00ff00ff00ff00612cf18360081b67ffffffffffffffff1690565b1617905065ffff0000ffff8160101c1667ffff0000ffff0000612d1e8360101b67ffffffffffffffff1690565b1617905060008160201c612d3c8360201b67ffffffffffffffff1690565b1792915050565b60808201516020830190612d5b90612cc7565b612cc7565b6040820151612d6990612cc7565b60401b17612d81612d5660018460059190911b015190565b825160809190911b90612d9390612cc7565b60c01b17179392505050565b8260108101928215612dcd579160200282015b82811115612dcd578251825591602001919060010190612db2565b50612dd9929150612df5565b5090565b6040518060200160405280612df0612e0a565b905290565b5b80821115612dd95760008155600101612df6565b6040518061032001604052806019906020820280368337509192915050565b600060208284031215612e3b57600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114612e6657600080fd5b919050565b60008060408385031215612e7e57600080fd5b612e8783612e42565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610320810167ffffffffffffffff81118282101715612ee857612ee8612e95565b60405290565b6040516060810167ffffffffffffffff81118282101715612ee857612ee8612e95565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715612f5857612f58612e95565b604052919050565b803567ffffffffffffffff81168114612e6657600080fd5b6000610320808385031215612f8c57600080fd5b604051602080820182811067ffffffffffffffff82111715612fb057612fb0612e95565b806040525081935085601f860112612fc757600080fd5b612fcf612ec4565b928501928087851115612fe157600080fd5b865b8581101561300157612ff481612f60565b8352918301918301612fe3565b509092525091949350505050565b60006060828403121561302157600080fd5b50919050565b60008083601f84011261303957600080fd5b50813567ffffffffffffffff81111561305157600080fd5b6020830191508360208260051b850101111561306c57600080fd5b9250929050565b60008060008060008060008060006103e08a8c03121561309257600080fd5b61309b8a612e42565b985060208a013597506130b18b60408c01612f78565b96506103608a013567ffffffffffffffff808211156130cf57600080fd5b6130db8d838e0161300f565b97506103808c01359150808211156130f257600080fd5b6130fe8d838e01613027565b90975095506103a08c013591508082111561311857600080fd5b6131248d838e0161300f565b94506103c08c013591508082111561313b57600080fd5b506131488c828d01613027565b915080935050809150509295985092959850929598565b600080600080600060a0868803121561317757600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b60005b838110156131b557818101518382015260200161319d565b838111156121145750506000910152565b60208152600082518060208401526131e581604085016020870161319a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b6000806040838503121561322a57600080fd5b50508035926020909101359150565b60008083601f84011261324b57600080fd5b50813567ffffffffffffffff81111561326357600080fd5b60208301915083602082850101111561306c57600080fd5b600080600080600080600060a0888a03121561329657600080fd5b8735965060208801359550604088013567ffffffffffffffff808211156132bc57600080fd5b6132c88b838c01613239565b909750955060608a01359150808211156132e157600080fd5b506132ee8a828b01613027565b9094509250506080880135801515811461330757600080fd5b8091505092959891949750929550565b60008060006060848603121561332c57600080fd5b61333584612e42565b95602085013595506040909401359392505050565b60008060006040848603121561335f57600080fd5b83359250602084013567ffffffffffffffff81111561337d57600080fd5b61338986828701613239565b9497909650939450505050565b600080600080600080600060a0888a0312156133b157600080fd5b8735965060208801359550604088013567ffffffffffffffff808211156133d757600080fd5b6133e38b838c01613239565b909750955060608a01359150808211156133fc57600080fd5b506134098a828b01613239565b989b979a50959894979596608090950135949350505050565b60008060008060006080868803121561343a57600080fd5b8535945061344a60208701612e42565b935061345860408701612f60565b9250606086013567ffffffffffffffff81111561347457600080fd5b61348088828901613239565b969995985093965092949392505050565b6000806000806000608086880312156134a957600080fd5b6134b286612e42565b945060208601359350604086013567ffffffffffffffff808211156134d657600080fd5b6134e289838a0161300f565b945060608801359150808211156134f857600080fd5b5061348088828901613027565b803563ffffffff81168114612e6657600080fd5b60008060006060848603121561352e57600080fd5b8335925061353e60208501613505565b915061354c60408501613505565b90509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036135e4576135e4613584565b5060010190565b6000606082360312156135fd57600080fd5b613605612eee565b823567ffffffffffffffff8082111561361d57600080fd5b9084019036601f83011261363057600080fd5b813560208282111561364457613644612e95565b613674817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f85011601612f11565b9250818352368183860101111561368a57600080fd5b81818501828501376000918301810191909152908352848101359083015250604092830135928101929092525090565b81516103208201908260005b60198110156136ef57825167ffffffffffffffff168252602092830192909101906001016136c6565b50505092915050565b6000821982111561370b5761370b613584565b500190565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261374557600080fd5b83018035915067ffffffffffffffff82111561376057600080fd5b60200191503681900382131561306c57600080fd5b600181815b808511156137ce57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156137b4576137b4613584565b808516156137c157918102915b93841c939080029061377a565b509250929050565b6000826137e557506001613891565b816137f257506000613891565b816001811461380857600281146138125761382e565b6001915050613891565b60ff84111561382357613823613584565b50506001821b613891565b5060208310610133831016604e8410600b8410161715613851575081810a613891565b61385b8383613775565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561388d5761388d613584565b0290505b92915050565b6000612aed83836137d6565b6000828210156138b5576138b5613584565b500390565b600063ffffffff838116908316818110156138d7576138d7613584565b039392505050565b600063ffffffff8083168185168083038211156138fe576138fe613584565b01949350505050565b6000845161391981846020890161319a565b9190910192835250602082015260400191905056fea164736f6c634300080f000a"; ++ hex"6080604052600436106101d85760003560e01c80639d53a64811610102578063ddcd58de11610095578063ec5efcbc11610064578063ec5efcbc14610681578063f3f480d9146106a1578063faf37bc7146106d4578063fef2b4ed146106e757600080fd5b8063ddcd58de146105d4578063e03110e11461060c578063e159261114610641578063ea7139501461066157600080fd5b8063b5e7154c116100d1578063b5e7154c14610555578063d18534b51461056c578063da35c6641461058c578063dd24f9bf146105a157600080fd5b80639d53a6481461048e5780639d7e8769146104dd578063b2e67ba8146104fd578063b4801e611461053557600080fd5b806361238bde1161017a5780637ac54767116101495780637ac54767146103ca5780638542cf50146103ea578063882856ef146104355780638dc4be111461046e57600080fd5b806361238bde1461031e5780636551927b146103565780637051472e1461038e5780637917de1d146103aa57600080fd5b80633909af5c116101b65780633909af5c146102715780634d52b4c91461029357806352f0f3ad146102a857806354fd4d50146102c857600080fd5b8063013cf08b146101dd5780630359a5631461022e5780632055b36b1461025c575b600080fd5b3480156101e957600080fd5b506101fd6101f8366004612e29565b610714565b6040805173ffffffffffffffffffffffffffffffffffffffff90931683526020830191909152015b60405180910390f35b34801561023a57600080fd5b5061024e610249366004612e6b565b610759565b604051908152602001610225565b34801561026857600080fd5b5061024e601081565b34801561027d57600080fd5b5061029161028c366004613073565b610891565b005b34801561029f57600080fd5b5061024e610ae8565b3480156102b457600080fd5b5061024e6102c336600461315f565b610b03565b3480156102d457600080fd5b506103116040518060400160405280600c81526020017f312e312e332d626574612e32000000000000000000000000000000000000000081525081565b60405161022591906131c6565b34801561032a57600080fd5b5061024e610339366004613217565b600160209081526000928352604080842090915290825290205481565b34801561036257600080fd5b5061024e610371366004612e6b565b601560209081526000928352604080842090915290825290205481565b34801561039a57600080fd5b5061024e6703782dace9d9000081565b3480156103b657600080fd5b506102916103c536600461327b565b610bd9565b3480156103d657600080fd5b5061024e6103e5366004612e29565b6110dc565b3480156103f657600080fd5b50610425610405366004613217565b600260209081526000928352604080842090915290825290205460ff1681565b6040519015158152602001610225565b34801561044157600080fd5b50610455610450366004613317565b6110f3565b60405167ffffffffffffffff9091168152602001610225565b34801561047a57600080fd5b5061029161048936600461334a565b61114d565b34801561049a57600080fd5b5061024e6104a9366004612e6b565b73ffffffffffffffffffffffffffffffffffffffff9091166000908152601860209081526040808320938352929052205490565b3480156104e957600080fd5b506102916104f8366004613396565b611248565b34801561050957600080fd5b5061024e610518366004612e6b565b601760209081526000928352604080842090915290825290205481565b34801561054157600080fd5b5061024e610550366004613317565b6113ff565b34801561056157600080fd5b5061024e620186a081565b34801561057857600080fd5b50610291610587366004613073565b611431565b34801561059857600080fd5b5060135461024e565b3480156105ad57600080fd5b507f000000000000000000000000000000000000000000000000000000000000271061024e565b3480156105e057600080fd5b5061024e6105ef366004612e6b565b601660209081526000928352604080842090915290825290205481565b34801561061857600080fd5b5061062c610627366004613217565b611840565b60408051928352602083019190915201610225565b34801561064d57600080fd5b5061029161065c36600461334a565b611931565b34801561066d57600080fd5b5061029161067c366004613422565b611a39565b34801561068d57600080fd5b5061029161069c366004613491565b611b98565b3480156106ad57600080fd5b507f000000000000000000000000000000000000000000000000000000000000007861024e565b6102916106e2366004613519565b611d1e565b3480156106f357600080fd5b5061024e610702366004612e29565b60006020819052908152604090205481565b6013818154811061072457600080fd5b60009182526020909120600290910201805460019091015473ffffffffffffffffffffffffffffffffffffffff909116915082565b73ffffffffffffffffffffffffffffffffffffffff82166000908152601560209081526040808320848452909152812054819061079c9060601c63ffffffff1690565b63ffffffff16905060005b6010811015610889578160011660010361082f5773ffffffffffffffffffffffffffffffffffffffff85166000908152601460209081526040808320878452909152902081601081106107fc576107fc613555565b01546040805160208101929092528101849052606001604051602081830303815290604052805190602001209250610870565b826003826010811061084357610843613555565b01546040805160208101939093528201526060016040516020818303038152906040528051906020012092505b60019190911c9080610881816135b3565b9150506107a7565b505092915050565b600061089d8a8a610759565b90506108c086868360208b01356108bb6108b68d6135eb565b611fea565b61202a565b80156108de57506108de83838360208801356108bb6108b68a6135eb565b610914576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b86604001358860405160200161092a91906136ba565b6040516020818303038152906040528051906020012014610977576040517f1968a90200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83602001358760200135600161098d91906136f8565b146109c4576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a0c886109d28680613710565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061208b92505050565b610a15886121e6565b836040013588604051602001610a2b91906136ba565b6040516020818303038152906040528051906020012003610a78576040517f9843145b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8a1660009081526015602090815260408083208c8452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000166001179055610adc8a8a3361298e565b50505050505050505050565b6001610af660106002613897565b610b0091906138a3565b81565b6000610b0f8686612a47565b9050610b1c8360086136f8565b82101580610b2a5750602083115b15610b61576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000602081815260c085901b82526008959095528251828252600286526040808320858452875280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558484528752808320948352938652838220558181529384905292205592915050565b60608115610bf257610beb8686612af4565b9050610c2c565b85858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050505b3360009081526014602090815260408083208b845290915280822081516102008101928390529160109082845b815481526020019060010190808311610c5957505050505090506000601560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008b81526020019081526020016000205490506000610cda8260601c63ffffffff1690565b63ffffffff169050333214610d1b576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d2b8260801c63ffffffff1690565b63ffffffff16600003610d6a576040517f87138d5c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d748260c01c90565b67ffffffffffffffff1615610db5576040517f475a253500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b898114610dee576040517f60f95d5a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610dfb89898d8886612b6d565b83516020850160888204881415608883061715610e20576307b1daf16000526004601cfd5b60405160c8810160405260005b83811015610ed0578083018051835260208101516020840152604081015160408401526060810151606084015260808101516080840152508460888301526088810460051b8b013560a883015260c882206001860195508560005b610200811015610ec5576001821615610ea55782818b0152610ec5565b8981015160009081526020938452604090209260019290921c9101610e88565b505050608801610e2d565b50505050600160106002610ee49190613897565b610eee91906138a3565b811115610f27576040517f6229572300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f9c610f3a8360401c63ffffffff1690565b610f4a9063ffffffff168a6136f8565b60401b7fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff606084901b167fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff8516171790565b915084156110295777ffffffffffffffffffffffffffffffffffffffffffffffff82164260c01b179150610fd68260801c63ffffffff1690565b63ffffffff16610fec8360401c63ffffffff1690565b63ffffffff1614611029576040517f7b1dafd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360009081526014602090815260408083208e8452909152902061104f90846010612d9f565b503360008181526018602090815260408083208f8452825280832080546001810182559084528284206004820401805460039092166008026101000a67ffffffffffffffff818102199093164390931602919091179055838352601582528083208f8452909152812084905560609190911b81523690601437366014016000a05050505050505050505050565b600381601081106110ec57600080fd5b0154905081565b6018602052826000526040600020602052816000526040600020818154811061111b57600080fd5b906000526020600020906004918282040191900660080292509250509054906101000a900467ffffffffffffffff1681565b60443560008060088301861061116b5763fe2549876000526004601cfd5b60c083901b60805260888386823786600882030151915060206000858360025afa90508061119857600080fd5b50600080517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0400000000000000000000000000000000000000000000000000000000000000178082526002602090815260408084208a8552825280842080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558385528252808420998452988152888320939093558152908190529490942055505050565b600080603087600037602060006030600060025afa806112705763f91129696000526004601cfd5b6000517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f010000000000000000000000000000000000000000000000000000000000000017608081815260a08c905260c08b905260308a60e037603088609083013760008060c083600a5afa9250826112f2576309bde3396000526004601cfd5b602886106113085763fe2549876000526004601cfd5b6000602882015278200000000000000000000000000000000000000000000000008152600881018b905285810151935060308a8237603081019b909b52505060509098207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0500000000000000000000000000000000000000000000000000000000000000176000818152600260209081526040808320868452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915584845282528083209583529481528482209a909a559081528089529190912096909655505050505050565b6014602052826000526040600020602052816000526040600020816010811061142757600080fd5b0154925083915050565b73ffffffffffffffffffffffffffffffffffffffff891660009081526015602090815260408083208b845290915290205467ffffffffffffffff8116156114a4576040517fc334f06900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6114ae8160c01c90565b67ffffffffffffffff166000036114f1576040517f55d4cbf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000007861151c8260c01c90565b6115309067ffffffffffffffff16426138a3565b11611567576040517f55d4cbf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006115738b8b610759565b905061158c87878360208c01356108bb6108b68e6135eb565b80156115aa57506115aa84848360208901356108bb6108b68b6135eb565b6115e0576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8760400135896040516020016115f691906136ba565b6040516020818303038152906040528051906020012014611643576040517f1968a90200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84602001358860200135600161165991906136f8565b14158061168b575060016116738360601c63ffffffff1690565b61167d91906138ba565b63ffffffff16856020013514155b156116c2576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6116d0896109d28780613710565b6116d9896121e6565b60006116e48a612cc0565b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0200000000000000000000000000000000000000000000000000000000000000179050600061173b8460a01c63ffffffff1690565b67ffffffffffffffff169050600160026000848152602001908152602001600020600083815260200190815260200160002060006101000a81548160ff021916908315150217905550601760008e73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008d8152602001908152602001600020546001600084815260200190815260200160002060008381526020019081526020016000208190555061180d8460801c63ffffffff1690565b600083815260208190526040902063ffffffff9190911690556118318d8d8161298e565b50505050505050505050505050565b6000828152600260209081526040808320848452909152812054819060ff166118c9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f7072652d696d616765206d757374206578697374000000000000000000000000604482015260640160405180910390fd5b50600083815260208181526040909120546118e58160086136f8565b6118f08560206136f8565b1061190e57836119018260086136f8565b61190b91906138a3565b91505b506000938452600160209081526040808620948652939052919092205492909150565b60443560008060088301861061194f5763fe2549876000526004601cfd5b60c083901b6080526088838682378087017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80151908490207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f02000000000000000000000000000000000000000000000000000000000000001760008181526002602090815260408083208b8452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915584845282528083209a83529981528982209390935590815290819052959095209190915550505050565b60008060008060808860601b81528760c01b6014820152858782601c0137601c860181207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0600000000000000000000000000000000000000000000000000000000000000179350604088026260216001603f5a021015611ac35763dd629f866000526004601cfd5b6000808783601c018c5afa94503d6001019150600882018a10611aee5763fe2549876000526004601cfd5b60c082901b81526008018481533d6000600183013e89017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8015160008481526002602090815260408083208d8452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915587845282528083209c83529b81528b8220929092559384528390529790912096909655505050505050565b6000611ba48686610759565b9050611bbd83838360208801356108bb6108b68a6135eb565b611bf3576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602084013515611c2f576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611c37612ddd565b611c45816109d28780613710565b611c4e816121e6565b846040013581604051602001611c6491906136ba565b6040516020818303038152906040528051906020012003611cb1576040517f9843145b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff87166000908152601560209081526040808320898452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000166001179055611d1587873361298e565b50505050505050565b6703782dace9d90000341015611d60576040517fe92c469f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b333214611d99576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611da48160086138df565b63ffffffff168263ffffffff1610611de8576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000027108163ffffffff161015611e48576040517f7b1dafd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000908152601560209081526040808320868452909152902054611e738160801c63ffffffff1690565b63ffffffff1615611eb0576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b608082901b7fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff60a085901b167fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff83161717336000818152601560209081526040808320898452825280832094909455835180850185528381528082018981526013805460018101825590855291517f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a090600290930292830180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909216919091179055517f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a0919091015591815260168252828120968152959052909320349055505050565b600081600001518260200151836040015160405160200161200d93929190613907565b604051602081830303815290604052805190602001209050919050565b60008160005b601081101561207e578060051b880135600186831c16600181146120635760008481526020839052604090209350612074565b600082815260208590526040902093505b5050600101612030565b5090931495945050505050565b608881511461209957600080fd5b602081016020830161211a565b8260031b8201518060001a8160011a60081b178160021a60101b8260031a60181b17178160041a60201b8260051a60281b178260061a60301b8360071a60381b1717179050612114816120ff868560059190911b015190565b1867ffffffffffffffff16600586901b840152565b50505050565b612126600083836120a6565b612132600183836120a6565b61213e600283836120a6565b61214a600383836120a6565b612156600483836120a6565b612162600583836120a6565b61216e600683836120a6565b61217a600783836120a6565b612186600883836120a6565b612192600983836120a6565b61219e600a83836120a6565b6121aa600b83836120a6565b6121b6600c83836120a6565b6121c2600d83836120a6565b6121ce600e83836120a6565b6121da600f83836120a6565b612114601083836120a6565b6040805178010000000000008082800000000000808a8000000080008000602082015279808b00000000800000018000000080008081800000000000800991810191909152788a00000000000000880000000080008009000000008000000a60608201527b8000808b800000000000008b8000000000008089800000000000800360808201527f80000000000080028000000000000080000000000000800a800000008000000a60a08201527f800000008000808180000000000080800000000080000001800000008000800860c082015260009060e0016040516020818303038152906040529050602082016020820161286e565b6102808101516101e082015161014083015160a0840151845118189118186102a082015161020083015161016084015160c0850151602086015118189118186102c083015161022084015161018085015160e0860151604087015118189118186102e08401516102408501516101a0860151610100870151606088015118189118186103008501516102608601516101c0870151610120880151608089015118189118188084603f1c6123998660011b67ffffffffffffffff1690565b18188584603f1c6123b48660011b67ffffffffffffffff1690565b18188584603f1c6123cf8660011b67ffffffffffffffff1690565b181895508483603f1c6123ec8560011b67ffffffffffffffff1690565b181894508387603f1c6124098960011b67ffffffffffffffff1690565b60208b01518b51861867ffffffffffffffff168c5291189190911897508118600181901b603f9190911c18935060c08801518118601481901c602c9190911b1867ffffffffffffffff1660208901526101208801518718602c81901c60149190911b1867ffffffffffffffff1660c08901526102c08801518618600381901c603d9190911b1867ffffffffffffffff166101208901526101c08801518718601981901c60279190911b1867ffffffffffffffff166102c08901526102808801518218602e81901c60129190911b1867ffffffffffffffff166101c089015260408801518618600281901c603e9190911b1867ffffffffffffffff166102808901526101808801518618601581901c602b9190911b1867ffffffffffffffff1660408901526101a08801518518602781901c60199190911b1867ffffffffffffffff166101808901526102608801518718603881901c60089190911b1867ffffffffffffffff166101a08901526102e08801518518600881901c60389190911b1867ffffffffffffffff166102608901526101e08801518218601781901c60299190911b1867ffffffffffffffff166102e089015260808801518718602581901c601b9190911b1867ffffffffffffffff166101e08901526103008801518718603281901c600e9190911b1867ffffffffffffffff1660808901526102a08801518118603e81901c60029190911b1867ffffffffffffffff166103008901526101008801518518600981901c60379190911b1867ffffffffffffffff166102a08901526102008801518118601381901c602d9190911b1867ffffffffffffffff1661010089015260a08801518218601c81901c60249190911b1867ffffffffffffffff1661020089015260608801518518602481901c601c9190911b1867ffffffffffffffff1660a08901526102408801518518602b81901c60159190911b1867ffffffffffffffff1660608901526102208801518618603181901c600f9190911b1867ffffffffffffffff166102408901526101608801518118603681901c600a9190911b1867ffffffffffffffff166102208901525060e08701518518603a81901c60069190911b1867ffffffffffffffff166101608801526101408701518118603d81901c60039190911b1867ffffffffffffffff1660e0880152505067ffffffffffffffff81166101408601525b5050505050565b600582811b8201805160018501831b8401805160028701851b8601805160038901871b8801805160048b0190981b8901805167ffffffffffffffff861985168918811690995283198a16861889169096528819861683188816909352841986168818871690528419831684189095169052919391929190611d15565b612808600082612781565b612813600582612781565b61281e600a82612781565b612829600f82612781565b612834601482612781565b50565b612840816122dc565b612849816127fd565b600383901b820151815160c09190911c9061211490821867ffffffffffffffff168352565b61287a60008284612837565b61288660018284612837565b61289260028284612837565b61289e60038284612837565b6128aa60048284612837565b6128b660058284612837565b6128c260068284612837565b6128ce60078284612837565b6128da60088284612837565b6128e660098284612837565b6128f2600a8284612837565b6128fe600b8284612837565b61290a600c8284612837565b612916600d8284612837565b612922600e8284612837565b61292e600f8284612837565b61293a60108284612837565b61294660118284612837565b61295260128284612837565b61295e60138284612837565b61296a60148284612837565b61297660158284612837565b61298260168284612837565b61211460178284612837565b73ffffffffffffffffffffffffffffffffffffffff83811660009081526016602090815260408083208684529091528082208054908390559051909284169083908381818185875af1925050503d8060008114612a07576040519150601f19603f3d011682016040523d82523d6000602084013e612a0c565b606091505b505090508061277a576040517f83e6cc6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f01000000000000000000000000000000000000000000000000000000000000007effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831617612aed818360408051600093845233602052918152606090922091527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001790565b9392505050565b6060604051905081602082018181018286833760888306808015612b3d5760888290038501848101848103803687375060806001820353506001845160001a1784538652612b54565b608836843760018353608060878401536088850186525b5050505050601f19603f82510116810160405292915050565b6000612b7f8260a01c63ffffffff1690565b67ffffffffffffffff1690506000612b9d8360801c63ffffffff1690565b63ffffffff1690506000612bb78460401c63ffffffff1690565b63ffffffff169050600883108015612bcd575080155b15612c015760c082901b6000908152883560085283513382526017602090815260408084208a855290915290912055612cb6565b60088310158015612c1f575080612c196008856138a3565b93508310155b8015612c335750612c3087826136f8565b83105b15612cb6576000612c4482856138a3565b905087612c528260206136f8565b10158015612c5e575085155b15612c95576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360009081526017602090815260408083208a845290915290209089013590555b5050505050505050565b6000612d43565b66ff00ff00ff00ff8160081c1667ff00ff00ff00ff00612cf18360081b67ffffffffffffffff1690565b1617905065ffff0000ffff8160101c1667ffff0000ffff0000612d1e8360101b67ffffffffffffffff1690565b1617905060008160201c612d3c8360201b67ffffffffffffffff1690565b1792915050565b60808201516020830190612d5b90612cc7565b612cc7565b6040820151612d6990612cc7565b60401b17612d81612d5660018460059190911b015190565b825160809190911b90612d9390612cc7565b60c01b17179392505050565b8260108101928215612dcd579160200282015b82811115612dcd578251825591602001919060010190612db2565b50612dd9929150612df5565b5090565b6040518060200160405280612df0612e0a565b905290565b5b80821115612dd95760008155600101612df6565b6040518061032001604052806019906020820280368337509192915050565b600060208284031215612e3b57600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114612e6657600080fd5b919050565b60008060408385031215612e7e57600080fd5b612e8783612e42565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610320810167ffffffffffffffff81118282101715612ee857612ee8612e95565b60405290565b6040516060810167ffffffffffffffff81118282101715612ee857612ee8612e95565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715612f5857612f58612e95565b604052919050565b803567ffffffffffffffff81168114612e6657600080fd5b6000610320808385031215612f8c57600080fd5b604051602080820182811067ffffffffffffffff82111715612fb057612fb0612e95565b806040525081935085601f860112612fc757600080fd5b612fcf612ec4565b928501928087851115612fe157600080fd5b865b8581101561300157612ff481612f60565b8352918301918301612fe3565b509092525091949350505050565b60006060828403121561302157600080fd5b50919050565b60008083601f84011261303957600080fd5b50813567ffffffffffffffff81111561305157600080fd5b6020830191508360208260051b850101111561306c57600080fd5b9250929050565b60008060008060008060008060006103e08a8c03121561309257600080fd5b61309b8a612e42565b985060208a013597506130b18b60408c01612f78565b96506103608a013567ffffffffffffffff808211156130cf57600080fd5b6130db8d838e0161300f565b97506103808c01359150808211156130f257600080fd5b6130fe8d838e01613027565b90975095506103a08c013591508082111561311857600080fd5b6131248d838e0161300f565b94506103c08c013591508082111561313b57600080fd5b506131488c828d01613027565b915080935050809150509295985092959850929598565b600080600080600060a0868803121561317757600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b60005b838110156131b557818101518382015260200161319d565b838111156121145750506000910152565b60208152600082518060208401526131e581604085016020870161319a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b6000806040838503121561322a57600080fd5b50508035926020909101359150565b60008083601f84011261324b57600080fd5b50813567ffffffffffffffff81111561326357600080fd5b60208301915083602082850101111561306c57600080fd5b600080600080600080600060a0888a03121561329657600080fd5b8735965060208801359550604088013567ffffffffffffffff808211156132bc57600080fd5b6132c88b838c01613239565b909750955060608a01359150808211156132e157600080fd5b506132ee8a828b01613027565b9094509250506080880135801515811461330757600080fd5b8091505092959891949750929550565b60008060006060848603121561332c57600080fd5b61333584612e42565b95602085013595506040909401359392505050565b60008060006040848603121561335f57600080fd5b83359250602084013567ffffffffffffffff81111561337d57600080fd5b61338986828701613239565b9497909650939450505050565b600080600080600080600060a0888a0312156133b157600080fd5b8735965060208801359550604088013567ffffffffffffffff808211156133d757600080fd5b6133e38b838c01613239565b909750955060608a01359150808211156133fc57600080fd5b506134098a828b01613239565b989b979a50959894979596608090950135949350505050565b60008060008060006080868803121561343a57600080fd5b8535945061344a60208701612e42565b935061345860408701612f60565b9250606086013567ffffffffffffffff81111561347457600080fd5b61348088828901613239565b969995985093965092949392505050565b6000806000806000608086880312156134a957600080fd5b6134b286612e42565b945060208601359350604086013567ffffffffffffffff808211156134d657600080fd5b6134e289838a0161300f565b945060608801359150808211156134f857600080fd5b5061348088828901613027565b803563ffffffff81168114612e6657600080fd5b60008060006060848603121561352e57600080fd5b8335925061353e60208501613505565b915061354c60408501613505565b90509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036135e4576135e4613584565b5060010190565b6000606082360312156135fd57600080fd5b613605612eee565b823567ffffffffffffffff8082111561361d57600080fd5b9084019036601f83011261363057600080fd5b813560208282111561364457613644612e95565b613674817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f85011601612f11565b9250818352368183860101111561368a57600080fd5b81818501828501376000918301810191909152908352848101359083015250604092830135928101929092525090565b81516103208201908260005b60198110156136ef57825167ffffffffffffffff168252602092830192909101906001016136c6565b50505092915050565b6000821982111561370b5761370b613584565b500190565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261374557600080fd5b83018035915067ffffffffffffffff82111561376057600080fd5b60200191503681900382131561306c57600080fd5b600181815b808511156137ce57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156137b4576137b4613584565b808516156137c157918102915b93841c939080029061377a565b509250929050565b6000826137e557506001613891565b816137f257506000613891565b816001811461380857600281146138125761382e565b6001915050613891565b60ff84111561382357613823613584565b50506001821b613891565b5060208310610133831016604e8410600b8410161715613851575081810a613891565b61385b8383613775565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561388d5761388d613584565b0290505b92915050565b6000612aed83836137d6565b6000828210156138b5576138b5613584565b500390565b600063ffffffff838116908316818110156138d7576138d7613584565b039392505050565b600063ffffffff8083168185168083038211156138fe576138fe613584565b01949350505050565b6000845161391981846020890161319a565b9190910192835250602082015260400191905056fea164736f6c634300080f000a"; + bytes internal constant mipsCode = +- hex"608060405234801561001057600080fd5b50600436106100415760003560e01c806354fd4d50146100465780637dc0d1d014610098578063e14ced32146100dc575b600080fd5b6100826040518060400160405280600a81526020017f312e312e302d72632e310000000000000000000000000000000000000000000081525081565b60405161008f91906121ee565b60405180910390f35b60405173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000373d916d11cce55b548f7051002e76bcfbd7a85d16815260200161008f565b6100ef6100ea3660046122a3565b6100fd565b60405190815260200161008f565b6000610107612164565b6080811461011457600080fd5b6040516106001461012457600080fd5b6084871461013157600080fd5b6101a4851461013f57600080fd5b8635608052602087013560a052604087013560e090811c60c09081526044890135821c82526048890135821c61010052604c890135821c610120526050890135821c61014052605489013590911c61016052605888013560f890811c610180526059890135901c6101a0819052605a89013590911c6101c05260628801906101e09060018111156101f5576040517f0136cc76000000000000000000000000000000000000000000000000000000008152600481fd5b506020810181511461020657600080fd5b60200160005b602081101561023057823560e01c825260049092019160209091019060010161020c565b5050508061012001511561024e576102466103a6565b91505061039d565b6101408101805160010167ffffffffffffffff16905260006101a49050600080600061028385606001518660000151866104f7565b9250925092508163ffffffff1660001480156102a557508063ffffffff16600c145b156102bf576102b387610521565b9550505050505061039d565b6000610339866040805160808101825260008082526020820181905291810182905260608101919091526040518060800160405280836060015163ffffffff168152602001836080015163ffffffff1681526020018360a0015163ffffffff1681526020018360c0015163ffffffff168152509050919050565b6101608701518751919250610356918391906105248888886108f9565b8652805163ffffffff9081166060808901919091526020830151821660808901526040830151821660a08901528201511660c08701526103946103a6565b96505050505050505b95945050505050565b60408051608051815260a051602082015260dc519181019190915260fc51604482015261011c51604882015261013c51604c82015261015c51605082015261017c5160548201526101805161019f5160588301526101a0516101bf5160598401526101d851605a8401526000926102009290916062830191906001811115610453576040517f0136cc76000000000000000000000000000000000000000000000000000000008152600481fd5b60005b602081101561047a57601c8601518452602090950194600490930192600101610456565b506000835283830384a060009450806001811461049a57600395506104c2565b8280156104b257600181146104bb57600296506104c0565b600096506104c0565b600196505b505b50505081900390207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1660f89190911b17919050565b6000806000610507858786610cdf565b925050603f601a83901c8116915082165b93509350939050565b600061052b612164565b608090506000806000806105628561016001516040810151608082015160a083015160c084015160e0909401519294919390929091565b509350935093509350600080610ffa63ffffffff168663ffffffff16036105a75761059285858960e00151610d93565b63ffffffff1660e08a01529092509050610808565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03363ffffffff8716016105e05763400000009150610808565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefe863ffffffff8716016106165760019150610808565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffef6a63ffffffff87160161066a57600161012088015260ff851661010088015261065d6103a6565b9998505050505050505050565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff05d63ffffffff8716016107665760006040518061012001604052808763ffffffff1681526020018663ffffffff1681526020018563ffffffff16815260200189602001518152602001896040015163ffffffff1681526020018b81526020017f000000000000000000000000373d916d11cce55b548f7051002e76bcfbd7a85d73ffffffffffffffffffffffffffffffffffffffff1681526020016107386101a4600160ff16610380020190565b81528951602090910152905061074d81610e27565b8b5263ffffffff1660408b015290935091506108089050565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff05c63ffffffff8716016107cb57602087015160408801516107b1918791879187916105248d5161109f565b63ffffffff1660408b015260208a01529092509050610808565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff02963ffffffff871601610808576108028585611195565b90925090505b6000610882886040805160808101825260008082526020820181905291810182905260608101919091526040518060800160405280836060015163ffffffff168152602001836080015163ffffffff1681526020018360a0015163ffffffff1681526020018360c0015163ffffffff168152509050919050565b61016089015163ffffffff85811660408084019190915285821660e0909301929092526020830180518083168086526004909101831682526060808e01919091529051821660808d015291830151811660a08c0152908201511660c08a015290506108eb6103a6565b9a9950505050505050505050565b84600263ffffffff8416148061091557508263ffffffff166003145b156109675760006002856303ffffff1663ffffffff16901b896020015163f00000001617905061096189898663ffffffff1660021461095557601f610958565b60005b60ff168461124a565b50610cd4565b600080601f601087901c8116908a90601589901c166020811061098c5761098c612317565b602002015192508063ffffffff871615806109ad57508663ffffffff16601c145b156109df578a8263ffffffff16602081106109ca576109ca612317565b6020020151925050601f600b88901c16610a96565b60208763ffffffff161015610a41578663ffffffff16600c1480610a0957508663ffffffff16600d145b80610a1a57508663ffffffff16600e145b15610a2b578761ffff169250610a96565b610a3a8861ffff166010611322565b9250610a96565b60288763ffffffff16101580610a5d57508663ffffffff166022145b80610a6e57508663ffffffff166026145b15610a96578a8263ffffffff1660208110610a8b57610a8b612317565b602002015192508190505b60048763ffffffff1610158015610ab3575060088763ffffffff16105b80610ac457508663ffffffff166001145b15610ae057610ad78c8c898b8689611395565b50505050610cd4565b63ffffffff6000602089831610610b4557610b008a61ffff166010611322565b9095019463fffffffc8616610b168d828e610cdf565b915060288a63ffffffff1610158015610b3657508963ffffffff16603014155b15610b4357809250600093505b505b6000610b558b8b8b8a8a87611583565b63ffffffff1690508963ffffffff166000148015610b7a575060088963ffffffff1610155b8015610b8c5750601c8963ffffffff16105b15610c54578863ffffffff1660081480610bac57508863ffffffff166009145b15610bdf57610bd38f8f8b63ffffffff16600814610bca5786610bcd565b60005b8a61124a565b50505050505050610cd4565b8863ffffffff16600a03610c0157610bd38f8f868a63ffffffff8b1615611ca0565b8863ffffffff16600b03610c2457610bd38f8f868a63ffffffff8b161515611ca0565b60108963ffffffff1610158015610c415750601c8963ffffffff16105b15610c5457610bd38f8f8b8a8a89611d70565b8963ffffffff166038148015610c6f575063ffffffff851615155b15610c9f5760018e8663ffffffff1660208110610c8e57610c8e612317565b63ffffffff90921660209290920201525b8263ffffffff1663ffffffff14610cbe57610cbb838d83612029565b97505b610ccc8f8f86846001611ca0565b505050505050505b979650505050505050565b6000610cea826120cb565b6003831615610cf857600080fd5b6020820191358360051c8160005b601b811015610d5e5760208601953583821c6001168015610d2e5760018114610d4357610d54565b60008481526020839052604090209350610d54565b600082815260208590526040902093505b5050600101610d06565b50868114610d7457630badf00d60005260206000fd5b5050601f93909316601c0360031b9290921c63ffffffff169392505050565b6000808284610fff811615610dad57610fff811661100003015b8663ffffffff16600003610e195784935090810190636000000063ffffffff83161180610de557508463ffffffff168263ffffffff16105b80610dfb57508563ffffffff168163ffffffff16105b15610e14575063ffffffff925060169150839050610518565b610e1d565b8693505b5093509350939050565b6101008101516080820151825160009283929163ffffffff161561109857845163ffffffff167ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb01611052576000610e93866101000151876020015163fffffffc168860e00151610cdf565b606087015190915060001a600103610f1557610f0f86606001518760a0015160408051600093845233602052918152606090922091527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001790565b60608701525b6000808760c0015173ffffffffffffffffffffffffffffffffffffffff1663e03110e189606001518a608001516040518363ffffffff1660e01b8152600401610f6e92919091825263ffffffff16602082015260400190565b6040805180830381865afa158015610f8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fae9190612346565b60208a015160408b01519294509092509060038216600481900384811015610fd4578094505b5083821015610fe1578193505b8460088502610100031c9450846008828660040303021b9450600180600883600403021b036001806008878560040303021b0391508119811690508581198816179650505061103f8a6020015163fffffffc168b60e0015187612029565b9298505050938601939250611098915050565b845163ffffffff167ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd0161108c5784604001519350611098565b63ffffffff9350600992505b9193509193565b600080858563ffffffff8b16600114806110bf575063ffffffff8b166002145b806110d0575063ffffffff8b166004145b156110dd57889350611187565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa63ffffffff8c160161117b57600061111d868c63fffffffc1689610cdf565b90508860038c166004038b81101561113357809b505b8b965086900360089081029290921c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600193880293841b0116911b17915060009050611187565b63ffffffff9350600992505b975097509750979350505050565b60008063ffffffff83166003036112385763ffffffff841615806111bf575063ffffffff84166005145b806111d0575063ffffffff84166003145b156111de5760009150611243565b63ffffffff8416600114806111f9575063ffffffff84166002145b8061120a575063ffffffff84166006145b8061121b575063ffffffff84166004145b156112295760019150611243565b5063ffffffff90506009611243565b5063ffffffff905060165b9250929050565b836000015160040163ffffffff16846020015163ffffffff16146112cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6a756d7020696e2064656c617920736c6f74000000000000000000000000000060448201526064015b60405180910390fd5b835160208501805163ffffffff908116875283811690915283161561131b5780600801848463ffffffff166020811061130a5761130a612317565b63ffffffff90921660209290920201525b5050505050565b600063ffffffff8381167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80850183169190911c821615159160016020869003821681901b830191861691821b92911b018261137f576000611381565b815b90861663ffffffff16179250505092915050565b6000866000015160040163ffffffff16876020015163ffffffff1614611417576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f6272616e636820696e2064656c617920736c6f7400000000000000000000000060448201526064016112c6565b8463ffffffff166004148061143257508463ffffffff166005145b156114a9576000868463ffffffff166020811061145157611451612317565b602002015190508063ffffffff168363ffffffff1614801561147957508563ffffffff166004145b806114a157508063ffffffff168363ffffffff16141580156114a157508563ffffffff166005145b915050611526565b8463ffffffff166006036114c65760008260030b13159050611526565b8463ffffffff166007036114e25760008260030b139050611526565b8463ffffffff1660010361152657601f601085901c16600081900361150b5760008360030b1291505b8063ffffffff166001036115245760008360030b121591505b505b8651602088015163ffffffff168852811561156757600261154c8661ffff166010611322565b63ffffffff90811690911b8201600401166020890152611579565b60208801805160040163ffffffff1690525b5050505050505050565b600063ffffffff861615806115b0575060088663ffffffff16101580156115b05750600f8663ffffffff16105b156119b05785600881146115f357600981146115fc57600a811461160557600b811461160e57600c811461161757600d811461162057600e81146116295761162e565b6020955061162e565b6021955061162e565b602a955061162e565b602b955061162e565b6024955061162e565b6025955061162e565b602695505b508463ffffffff16600003611653575063ffffffff8216601f600688901c161b611c96565b8463ffffffff16600203611677575063ffffffff8216601f600688901c161c611c96565b8463ffffffff166003036116ab57601f600688901c166116a363ffffffff8516821c6020839003611322565b915050611c96565b8463ffffffff166004036116cb575063ffffffff8216601f84161b611c96565b8463ffffffff166006036116eb575063ffffffff8216601f84161c611c96565b8463ffffffff1660070361171357601f84166116a363ffffffff8516821c6020839003611322565b8463ffffffff16600803611728575082611c96565b8463ffffffff1660090361173d575082611c96565b8463ffffffff16600a03611752575082611c96565b8463ffffffff16600b03611767575082611c96565b8463ffffffff16600c0361177c575082611c96565b8463ffffffff16600f03611791575082611c96565b8463ffffffff166010036117a6575082611c96565b8463ffffffff166011036117bb575082611c96565b8463ffffffff166012036117d0575082611c96565b8463ffffffff166013036117e5575082611c96565b8463ffffffff166018036117fa575082611c96565b8463ffffffff1660190361180f575082611c96565b8463ffffffff16601a03611824575082611c96565b8463ffffffff16601b03611839575082611c96565b8463ffffffff166020036118505750828201611c96565b8463ffffffff166021036118675750828201611c96565b8463ffffffff1660220361187e5750818303611c96565b8463ffffffff166023036118955750818303611c96565b8463ffffffff166024036118ac5750828216611c96565b8463ffffffff166025036118c35750828217611c96565b8463ffffffff166026036118da5750828218611c96565b8463ffffffff166027036118f2575082821719611c96565b8463ffffffff16602a03611921578260030b8460030b12611914576000611917565b60015b60ff169050611c96565b8463ffffffff16602b03611949578263ffffffff168463ffffffff1610611914576000611917565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f696e76616c696420696e737472756374696f6e0000000000000000000000000060448201526064016112c6565b611949565b8563ffffffff16601c03611a30578463ffffffff166002036119d55750828202611c96565b8463ffffffff16602014806119f057508463ffffffff166021145b156119ab578463ffffffff16602003611a07579219925b60005b6380000000851615611a29576401fffffffe600195861b169401611a0a565b9050611c96565b8563ffffffff16600f03611a51575065ffffffff0000601083901b16611c96565b8563ffffffff16602003611a8557611a298460031660080260180363ffffffff168363ffffffff16901c60ff166008611322565b8563ffffffff16602103611aba57611a298460021660080260100363ffffffff168363ffffffff16901c61ffff166010611322565b8563ffffffff16602203611ae8575063ffffffff60086003851602811681811b198416918316901b17611c96565b8563ffffffff16602303611afd575080611c96565b8563ffffffff16602403611b2e578360031660080260180363ffffffff168263ffffffff16901c60ff169050611c96565b8563ffffffff16602503611b60578360021660080260100363ffffffff168263ffffffff16901c61ffff169050611c96565b8563ffffffff16602603611b91575063ffffffff60086003851602601803811681811c198416918316901c17611c96565b8563ffffffff16602803611bc6575060ff63ffffffff60086003861602601803811682811b9091188316918416901b17611c96565b8563ffffffff16602903611bfc575061ffff63ffffffff60086002861602601003811682811b9091188316918416901b17611c96565b8563ffffffff16602a03611c2a575063ffffffff60086003851602811681811c198316918416901c17611c96565b8563ffffffff16602b03611c3f575081611c96565b8563ffffffff16602e03611c70575063ffffffff60086003851602601803811681811b198316918416901b17611c96565b8563ffffffff16603003611c85575080611c96565b8563ffffffff166038036119495750815b9695505050505050565b60208363ffffffff1610611d10576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f76616c696420726567697374657200000000000000000000000000000000000060448201526064016112c6565b63ffffffff831615801590611d225750805b15611d515781848463ffffffff1660208110611d4057611d40612317565b63ffffffff90921660209290920201525b5050505060208101805163ffffffff8082169093526004019091169052565b60008463ffffffff16601003611d8b57506060860151611fd1565b8463ffffffff16601103611daa5763ffffffff84166060880152611fd1565b8463ffffffff16601203611dc357506040860151611fd1565b8463ffffffff16601303611de25763ffffffff84166040880152611fd1565b8463ffffffff16601803611e165763ffffffff600385810b9085900b02602081901c821660608a0152166040880152611fd1565b8463ffffffff16601903611e475763ffffffff84811681851602602081901c821660608a0152166040880152611fd1565b8463ffffffff16601a03611f0a578260030b600003611ec2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d4950533a206469766973696f6e206279207a65726f0000000000000000000060448201526064016112c6565b8260030b8460030b81611ed757611ed761236a565b0763ffffffff166060880152600383810b9085900b81611ef957611ef961236a565b0563ffffffff166040880152611fd1565b8463ffffffff16601b03611fd1578263ffffffff16600003611f88576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d4950533a206469766973696f6e206279207a65726f0000000000000000000060448201526064016112c6565b8263ffffffff168463ffffffff1681611fa357611fa361236a565b0663ffffffff908116606089015283811690851681611fc457611fc461236a565b0463ffffffff1660408801525b63ffffffff8216156120075780868363ffffffff1660208110611ff657611ff6612317565b63ffffffff90921660209290920201525b50505060208401805163ffffffff808216909652600401909416909352505050565b6000612034836120cb565b600384161561204257600080fd5b6020830192601f8516601c0360031b83811b913563ffffffff90911b1916178460051c60005b601b8110156120c05760208601953582821c600116801561209057600181146120a5576120b6565b600085815260208390526040902094506120b6565b600082815260208690526040902094505b5050600101612068565b509095945050505050565b366103808201811015612160576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f636865636b207468617420746865726520697320656e6f7567682063616c6c6460448201527f617461000000000000000000000000000000000000000000000000000000000060648201526084016112c6565b5050565b6040805161018081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081018290526101008101829052610120810182905261014081019190915261016081016121ca6121cf565b905290565b6040518061040001604052806020906020820280368337509192915050565b600060208083528351808285015260005b8181101561221b578581018301518582016040015282016121ff565b8181111561222d576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b60008083601f84011261227357600080fd5b50813567ffffffffffffffff81111561228b57600080fd5b60208301915083602082850101111561124357600080fd5b6000806000806000606086880312156122bb57600080fd5b853567ffffffffffffffff808211156122d357600080fd5b6122df89838a01612261565b909750955060208801359150808211156122f857600080fd5b5061230588828901612261565b96999598509660400135949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000806040838503121561235957600080fd5b505080516020909101519092909150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fdfea164736f6c634300080f000a"; ++ hex"608060405234801561001057600080fd5b50600436106100415760003560e01c806354fd4d50146100465780637dc0d1d014610098578063e14ced32146100dc575b600080fd5b6100826040518060400160405280600c81526020017f312e312e312d626574612e33000000000000000000000000000000000000000081525081565b60405161008f9190612237565b60405180910390f35b60405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000007a9eab4ce99d157aee7a02e95b366e972a2d5b0b16815260200161008f565b6100ef6100ea3660046122ec565b6100fd565b60405190815260200161008f565b60006101076121ad565b6080811461011457600080fd5b6040516106001461012457600080fd5b6084871461013157600080fd5b6101a4851461013f57600080fd5b8635608052602087013560a052604087013560e090811c60c09081526044890135821c82526048890135821c61010052604c890135821c610120526050890135821c61014052605489013590911c61016052605888013560f890811c610180526059890135901c6101a0819052605a89013590911c6101c05260628801906101e09060018111156101f5576040517f0136cc76000000000000000000000000000000000000000000000000000000008152600481fd5b506020810181511461020657600080fd5b60200160005b602081101561023057823560e01c825260049092019160209091019060010161020c565b5050508061012001511561024e576102466103a6565b91505061039d565b6101408101805160010167ffffffffffffffff16905260006101a49050600080600061028385606001518660000151866104f7565b9250925092508163ffffffff1660001480156102a557508063ffffffff16600c145b156102bf576102b387610521565b9550505050505061039d565b6000610339866040805160808101825260008082526020820181905291810182905260608101919091526040518060800160405280836060015163ffffffff168152602001836080015163ffffffff1681526020018360a0015163ffffffff1681526020018360c0015163ffffffff168152509050919050565b6101608701518751919250610356918391906105248888886108f9565b8652805163ffffffff9081166060808901919091526020830151821660808901526040830151821660a08901528201511660c08701526103946103a6565b96505050505050505b95945050505050565b60408051608051815260a051602082015260dc519181019190915260fc51604482015261011c51604882015261013c51604c82015261015c51605082015261017c5160548201526101805161019f5160588301526101a0516101bf5160598401526101d851605a8401526000926102009290916062830191906001811115610453576040517f0136cc76000000000000000000000000000000000000000000000000000000008152600481fd5b60005b602081101561047a57601c8601518452602090950194600490930192600101610456565b506000835283830384a060009450806001811461049a57600395506104c2565b8280156104b257600181146104bb57600296506104c0565b600096506104c0565b600196505b505b50505081900390207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1660f89190911b17919050565b6000806000610507858786610cdf565b925050603f601a83901c8116915082165b93509350939050565b600061052b6121ad565b608090506000806000806105628561016001516040810151608082015160a083015160c084015160e0909401519294919390929091565b509350935093509350600080610ffa63ffffffff168663ffffffff16036105a75761059285858960e00151610d31565b63ffffffff1660e08a01529092509050610808565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03363ffffffff8716016105e05763400000009150610808565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefe863ffffffff8716016106165760019150610808565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffef6a63ffffffff87160161066a57600161012088015260ff851661010088015261065d6103a6565b9998505050505050505050565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff05d63ffffffff8716016107665760006040518061012001604052808763ffffffff1681526020018663ffffffff1681526020018563ffffffff16815260200189602001518152602001896040015163ffffffff1681526020018b81526020017f0000000000000000000000007a9eab4ce99d157aee7a02e95b366e972a2d5b0b73ffffffffffffffffffffffffffffffffffffffff1681526020016107386101a4600160ff16610380020190565b81528951602090910152905061074d81610dc5565b8b5263ffffffff1660408b015290935091506108089050565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff05c63ffffffff8716016107cb57602087015160408801516107b1918791879187916105248d5161103d565b63ffffffff1660408b015260208a01529092509050610808565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff02963ffffffff871601610808576108028585611133565b90925090505b6000610882886040805160808101825260008082526020820181905291810182905260608101919091526040518060800160405280836060015163ffffffff168152602001836080015163ffffffff1681526020018360a0015163ffffffff1681526020018360c0015163ffffffff168152509050919050565b61016089015163ffffffff85811660408084019190915285821660e0909301929092526020830180518083168086526004909101831682526060808e01919091529051821660808d015291830151811660a08c0152908201511660c08a015290506108eb6103a6565b9a9950505050505050505050565b84600263ffffffff8416148061091557508263ffffffff166003145b156109675760006002856303ffffff1663ffffffff16901b896020015163f00000001617905061096189898663ffffffff1660021461095557601f610958565b60005b60ff16846111e8565b50610cd4565b600080601f601087901c8116908a90601589901c166020811061098c5761098c612360565b602002015192508063ffffffff871615806109ad57508663ffffffff16601c145b156109df578a8263ffffffff16602081106109ca576109ca612360565b6020020151925050601f600b88901c16610a96565b60208763ffffffff161015610a41578663ffffffff16600c1480610a0957508663ffffffff16600d145b80610a1a57508663ffffffff16600e145b15610a2b578761ffff169250610a96565b610a3a8861ffff1660106112c0565b9250610a96565b60288763ffffffff16101580610a5d57508663ffffffff166022145b80610a6e57508663ffffffff166026145b15610a96578a8263ffffffff1660208110610a8b57610a8b612360565b602002015192508190505b60048763ffffffff1610158015610ab3575060088763ffffffff16105b80610ac457508663ffffffff166001145b15610ae057610ad78c8c898b8689611333565b50505050610cd4565b63ffffffff6000602089831610610b4557610b008a61ffff1660106112c0565b9095019463fffffffc8616610b168d828e610cdf565b915060288a63ffffffff1610158015610b3657508963ffffffff16603014155b15610b4357809250600093505b505b6000610b558b8b8b8a8a87611521565b63ffffffff1690508963ffffffff166000148015610b7a575060088963ffffffff1610155b8015610b8c5750601c8963ffffffff16105b15610c54578863ffffffff1660081480610bac57508863ffffffff166009145b15610bdf57610bd38f8f8b63ffffffff16600814610bca5786610bcd565b60005b8a6111e8565b50505050505050610cd4565b8863ffffffff16600a03610c0157610bd38f8f868a63ffffffff8b1615611c3e565b8863ffffffff16600b03610c2457610bd38f8f868a63ffffffff8b161515611c3e565b60108963ffffffff1610158015610c415750601c8963ffffffff16105b15610c5457610bd38f8f8b8a8a89611d0e565b8963ffffffff166038148015610c6f575063ffffffff851615155b15610c9f5760018e8663ffffffff1660208110610c8e57610c8e612360565b63ffffffff90921660209290920201525b8263ffffffff1663ffffffff14610cbe57610cbb838d83611fc7565b97505b610ccc8f8f86846001611c3e565b505050505050505b979650505050505050565b600080610ced858585612069565b909250905080610d29576040517f8e77b2b700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b509392505050565b6000808284610fff811615610d4b57610fff811661100003015b8663ffffffff16600003610db75784935090810190636000000063ffffffff83161180610d8357508463ffffffff168263ffffffff16105b80610d9957508563ffffffff168163ffffffff16105b15610db2575063ffffffff925060169150839050610518565b610dbb565b8693505b5093509350939050565b6101008101516080820151825160009283929163ffffffff161561103657845163ffffffff167ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb01610ff0576000610e31866101000151876020015163fffffffc168860e00151610cdf565b606087015190915060001a600103610eb357610ead86606001518760a0015160408051600093845233602052918152606090922091527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001790565b60608701525b6000808760c0015173ffffffffffffffffffffffffffffffffffffffff1663e03110e189606001518a608001516040518363ffffffff1660e01b8152600401610f0c92919091825263ffffffff16602082015260400190565b6040805180830381865afa158015610f28573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4c919061238f565b60208a015160408b01519294509092509060038216600481900384811015610f72578094505b5083821015610f7f578193505b8460088502610100031c9450846008828660040303021b9450600180600883600403021b036001806008878560040303021b03915081198116905085811988161796505050610fdd8a6020015163fffffffc168b60e0015187611fc7565b9298505050938601939250611036915050565b845163ffffffff167ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd0161102a5784604001519350611036565b63ffffffff9350600992505b9193509193565b600080858563ffffffff8b166001148061105d575063ffffffff8b166002145b8061106e575063ffffffff8b166004145b1561107b57889350611125565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa63ffffffff8c16016111195760006110bb868c63fffffffc1689610cdf565b90508860038c166004038b8110156110d157809b505b8b965086900360089081029290921c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600193880293841b0116911b17915060009050611125565b63ffffffff9350600992505b975097509750979350505050565b60008063ffffffff83166003036111d65763ffffffff8416158061115d575063ffffffff84166005145b8061116e575063ffffffff84166003145b1561117c57600091506111e1565b63ffffffff841660011480611197575063ffffffff84166002145b806111a8575063ffffffff84166006145b806111b9575063ffffffff84166004145b156111c757600191506111e1565b5063ffffffff905060096111e1565b5063ffffffff905060165b9250929050565b836000015160040163ffffffff16846020015163ffffffff161461126d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6a756d7020696e2064656c617920736c6f74000000000000000000000000000060448201526064015b60405180910390fd5b835160208501805163ffffffff90811687528381169091528316156112b95780600801848463ffffffff16602081106112a8576112a8612360565b63ffffffff90921660209290920201525b5050505050565b600063ffffffff8381167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80850183169190911c821615159160016020869003821681901b830191861691821b92911b018261131d57600061131f565b815b90861663ffffffff16179250505092915050565b6000866000015160040163ffffffff16876020015163ffffffff16146113b5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f6272616e636820696e2064656c617920736c6f740000000000000000000000006044820152606401611264565b8463ffffffff16600414806113d057508463ffffffff166005145b15611447576000868463ffffffff16602081106113ef576113ef612360565b602002015190508063ffffffff168363ffffffff1614801561141757508563ffffffff166004145b8061143f57508063ffffffff168363ffffffff161415801561143f57508563ffffffff166005145b9150506114c4565b8463ffffffff166006036114645760008260030b131590506114c4565b8463ffffffff166007036114805760008260030b1390506114c4565b8463ffffffff166001036114c457601f601085901c1660008190036114a95760008360030b1291505b8063ffffffff166001036114c25760008360030b121591505b505b8651602088015163ffffffff16885281156115055760026114ea8661ffff1660106112c0565b63ffffffff90811690911b8201600401166020890152611517565b60208801805160040163ffffffff1690525b5050505050505050565b600063ffffffff8616158061154e575060088663ffffffff161015801561154e5750600f8663ffffffff16105b1561194e578560088114611591576009811461159a57600a81146115a357600b81146115ac57600c81146115b557600d81146115be57600e81146115c7576115cc565b602095506115cc565b602195506115cc565b602a95506115cc565b602b95506115cc565b602495506115cc565b602595506115cc565b602695505b508463ffffffff166000036115f1575063ffffffff8216601f600688901c161b611c34565b8463ffffffff16600203611615575063ffffffff8216601f600688901c161c611c34565b8463ffffffff1660030361164957601f600688901c1661164163ffffffff8516821c60208390036112c0565b915050611c34565b8463ffffffff16600403611669575063ffffffff8216601f84161b611c34565b8463ffffffff16600603611689575063ffffffff8216601f84161c611c34565b8463ffffffff166007036116b157601f841661164163ffffffff8516821c60208390036112c0565b8463ffffffff166008036116c6575082611c34565b8463ffffffff166009036116db575082611c34565b8463ffffffff16600a036116f0575082611c34565b8463ffffffff16600b03611705575082611c34565b8463ffffffff16600c0361171a575082611c34565b8463ffffffff16600f0361172f575082611c34565b8463ffffffff16601003611744575082611c34565b8463ffffffff16601103611759575082611c34565b8463ffffffff1660120361176e575082611c34565b8463ffffffff16601303611783575082611c34565b8463ffffffff16601803611798575082611c34565b8463ffffffff166019036117ad575082611c34565b8463ffffffff16601a036117c2575082611c34565b8463ffffffff16601b036117d7575082611c34565b8463ffffffff166020036117ee5750828201611c34565b8463ffffffff166021036118055750828201611c34565b8463ffffffff1660220361181c5750818303611c34565b8463ffffffff166023036118335750818303611c34565b8463ffffffff1660240361184a5750828216611c34565b8463ffffffff166025036118615750828217611c34565b8463ffffffff166026036118785750828218611c34565b8463ffffffff16602703611890575082821719611c34565b8463ffffffff16602a036118bf578260030b8460030b126118b25760006118b5565b60015b60ff169050611c34565b8463ffffffff16602b036118e7578263ffffffff168463ffffffff16106118b25760006118b5565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f696e76616c696420696e737472756374696f6e000000000000000000000000006044820152606401611264565b6118e7565b8563ffffffff16601c036119ce578463ffffffff166002036119735750828202611c34565b8463ffffffff166020148061198e57508463ffffffff166021145b15611949578463ffffffff166020036119a5579219925b60005b63800000008516156119c7576401fffffffe600195861b1694016119a8565b9050611c34565b8563ffffffff16600f036119ef575065ffffffff0000601083901b16611c34565b8563ffffffff16602003611a23576119c78460031660080260180363ffffffff168363ffffffff16901c60ff1660086112c0565b8563ffffffff16602103611a58576119c78460021660080260100363ffffffff168363ffffffff16901c61ffff1660106112c0565b8563ffffffff16602203611a86575063ffffffff60086003851602811681811b198416918316901b17611c34565b8563ffffffff16602303611a9b575080611c34565b8563ffffffff16602403611acc578360031660080260180363ffffffff168263ffffffff16901c60ff169050611c34565b8563ffffffff16602503611afe578360021660080260100363ffffffff168263ffffffff16901c61ffff169050611c34565b8563ffffffff16602603611b2f575063ffffffff60086003851602601803811681811c198416918316901c17611c34565b8563ffffffff16602803611b64575060ff63ffffffff60086003861602601803811682811b9091188316918416901b17611c34565b8563ffffffff16602903611b9a575061ffff63ffffffff60086002861602601003811682811b9091188316918416901b17611c34565b8563ffffffff16602a03611bc8575063ffffffff60086003851602811681811c198316918416901c17611c34565b8563ffffffff16602b03611bdd575081611c34565b8563ffffffff16602e03611c0e575063ffffffff60086003851602601803811681811b198316918416901b17611c34565b8563ffffffff16603003611c23575080611c34565b8563ffffffff166038036118e75750815b9695505050505050565b60208363ffffffff1610611cae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f76616c69642072656769737465720000000000000000000000000000000000006044820152606401611264565b63ffffffff831615801590611cc05750805b15611cef5781848463ffffffff1660208110611cde57611cde612360565b63ffffffff90921660209290920201525b5050505060208101805163ffffffff8082169093526004019091169052565b60008463ffffffff16601003611d2957506060860151611f6f565b8463ffffffff16601103611d485763ffffffff84166060880152611f6f565b8463ffffffff16601203611d6157506040860151611f6f565b8463ffffffff16601303611d805763ffffffff84166040880152611f6f565b8463ffffffff16601803611db45763ffffffff600385810b9085900b02602081901c821660608a0152166040880152611f6f565b8463ffffffff16601903611de55763ffffffff84811681851602602081901c821660608a0152166040880152611f6f565b8463ffffffff16601a03611ea8578260030b600003611e60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d4950533a206469766973696f6e206279207a65726f000000000000000000006044820152606401611264565b8260030b8460030b81611e7557611e756123b3565b0763ffffffff166060880152600383810b9085900b81611e9757611e976123b3565b0563ffffffff166040880152611f6f565b8463ffffffff16601b03611f6f578263ffffffff16600003611f26576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d4950533a206469766973696f6e206279207a65726f000000000000000000006044820152606401611264565b8263ffffffff168463ffffffff1681611f4157611f416123b3565b0663ffffffff908116606089015283811690851681611f6257611f626123b3565b0463ffffffff1660408801525b63ffffffff821615611fa55780868363ffffffff1660208110611f9457611f94612360565b63ffffffff90921660209290920201525b50505060208401805163ffffffff808216909652600401909416909352505050565b6000611fd283612114565b6003841615611fe057600080fd5b6020830192601f8516601c0360031b83811b913563ffffffff90911b1916178460051c60005b601b81101561205e5760208601953582821c600116801561202e576001811461204357612054565b60008581526020839052604090209450612054565b600082815260208690526040902094505b5050600101612006565b509095945050505050565b60008061207583612114565b600384161561208357600080fd5b6020830192358460051c8160005b601b8110156120e95760208701963583821c60011680156120b957600181146120ce576120df565b600084815260208390526040902093506120df565b600082815260208590526040902093505b5050600101612091565b508714925050811561210b57601f8516601c0360031b81901c63ffffffff1692505b50935093915050565b3661038082018110156121a9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f636865636b207468617420746865726520697320656e6f7567682063616c6c6460448201527f61746100000000000000000000000000000000000000000000000000000000006064820152608401611264565b5050565b6040805161018081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101919091526101608101612213612218565b905290565b6040518061040001604052806020906020820280368337509192915050565b600060208083528351808285015260005b8181101561226457858101830151858201604001528201612248565b81811115612276576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b60008083601f8401126122bc57600080fd5b50813567ffffffffffffffff8111156122d457600080fd5b6020830191508360208285010111156111e157600080fd5b60008060008060006060868803121561230457600080fd5b853567ffffffffffffffff8082111561231c57600080fd5b61232889838a016122aa565b9097509550602088013591508082111561234157600080fd5b5061234e888289016122aa565b96999598509660400135949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600080604083850312156123a257600080fd5b505080516020909101519092909150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fdfea164736f6c634300080f000a"; + bytes internal constant anchorStateRegistryCode = +- hex"608060405234801561001057600080fd5b506004361061007d5760003560e01c80635e05fbd01161005b5780635e05fbd01461012a5780637258a8071461013d578063838c2d1e14610179578063f2b4e6171461018157600080fd5b806317cf21a91461008257806335e80ab31461009757806354fd4d50146100e1575b600080fd5b610095610090366004610b4c565b6101a7565b005b6002546100b79073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b61011d6040518060400160405280600a81526020017f322e302e302d72632e310000000000000000000000000000000000000000000081525081565b6040516100d89190610bea565b610095610138366004610cc6565b61061c565b61016461014b366004610df0565b6001602081905260009182526040909120805491015482565b604080519283526020830191909152016100d8565b610095610853565b7f0000000000000000000000005207cfa0166e8de0fcdfd78b4d17b68587be306d6100b7565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa158015610214573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102389190610e0d565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461029c576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060008373ffffffffffffffffffffffffffffffffffffffff1663fa24f7436040518163ffffffff1660e01b8152600401600060405180830381865afa1580156102ec573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526103329190810190610e2a565b92509250925060007f0000000000000000000000005207cfa0166e8de0fcdfd78b4d17b68587be306d73ffffffffffffffffffffffffffffffffffffffff16635f0150cb8585856040518463ffffffff1660e01b815260040161039793929190610efb565b6040805180830381865afa1580156103b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103d79190610f29565b5090508473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461043f576040517f6b0f689100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60028573ffffffffffffffffffffffffffffffffffffffff1663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa15801561048c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104b09190610f9f565b60028111156104c1576104c1610f70565b146104f8576040517f8f8af25f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052806105788773ffffffffffffffffffffffffffffffffffffffff1663bcef3b556040518163ffffffff1660e01b8152600401602060405180830381865afa158015610551573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105759190610fc0565b90565b81526020018673ffffffffffffffffffffffffffffffffffffffff16638b85902b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ec9190610fc0565b905263ffffffff909416600090815260016020818152604090922086518155959091015194019390935550505050565b600054610100900460ff161580801561063c5750600054600160ff909116105b806106565750303b158015610656575060005460ff166001145b6106e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561074457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b60005b83518110156107aa57600084828151811061076457610764610fd9565b60209081029190910181015180820151905163ffffffff1660009081526001808452604090912082518155919092015191015550806107a281611008565b915050610747565b50600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8416179055801561084e57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b600033905060008060008373ffffffffffffffffffffffffffffffffffffffff1663fa24f7436040518163ffffffff1660e01b8152600401600060405180830381865afa1580156108a8573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526108ee9190810190610e2a565b92509250925060007f0000000000000000000000005207cfa0166e8de0fcdfd78b4d17b68587be306d73ffffffffffffffffffffffffffffffffffffffff16635f0150cb8585856040518463ffffffff1660e01b815260040161095393929190610efb565b6040805180830381865afa15801561096f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109939190610f29565b5090508473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146109fb576040517f6b0f689100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160008563ffffffff1663ffffffff168152602001908152602001600020600101548573ffffffffffffffffffffffffffffffffffffffff16638b85902b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8d9190610fc0565b11610a99575050505050565b60028573ffffffffffffffffffffffffffffffffffffffff1663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ae6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b0a9190610f9f565b6002811115610b1b57610b1b610f70565b146104f8575050505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610b4957600080fd5b50565b600060208284031215610b5e57600080fd5b8135610b6981610b27565b9392505050565b60005b83811015610b8b578181015183820152602001610b73565b83811115610b9a576000848401525b50505050565b60008151808452610bb8816020860160208601610b70565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610b696020830184610ba0565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715610c4f57610c4f610bfd565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715610c9c57610c9c610bfd565b604052919050565b63ffffffff81168114610b4957600080fd5b8035610cc181610b27565b919050565b6000806040808486031215610cda57600080fd5b833567ffffffffffffffff80821115610cf257600080fd5b818601915086601f830112610d0657600080fd5b8135602082821115610d1a57610d1a610bfd565b610d28818360051b01610c55565b8281528181019350606092830285018201928a841115610d4757600080fd5b948201945b83861015610dd457858b0381811215610d655760008081fd5b610d6d610c2c565b8735610d7881610ca4565b81527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08201891315610daa5760008081fd5b610db2610c2c565b8886013581528989013586820152818601528652509485019493820193610d4c565b509650610de2888201610cb6565b955050505050509250929050565b600060208284031215610e0257600080fd5b8135610b6981610ca4565b600060208284031215610e1f57600080fd5b8151610b6981610b27565b600080600060608486031215610e3f57600080fd5b8351610e4a81610ca4565b60208501516040860151919450925067ffffffffffffffff80821115610e6f57600080fd5b818601915086601f830112610e8357600080fd5b815181811115610e9557610e95610bfd565b610ec660207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601610c55565b9150808252876020828501011115610edd57600080fd5b610eee816020840160208601610b70565b5080925050509250925092565b63ffffffff84168152826020820152606060408201526000610f206060830184610ba0565b95945050505050565b60008060408385031215610f3c57600080fd5b8251610f4781610b27565b602084015190925067ffffffffffffffff81168114610f6557600080fd5b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600060208284031215610fb157600080fd5b815160038110610b6957600080fd5b600060208284031215610fd257600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611060577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b506001019056fea164736f6c634300080f000a"; ++ hex"608060405234801561001057600080fd5b506004361061007d5760003560e01c80635e05fbd01161005b5780635e05fbd01461012a5780637258a8071461013d578063838c2d1e14610179578063f2b4e6171461018157600080fd5b806317cf21a91461008257806335e80ab31461009757806354fd4d50146100e1575b600080fd5b610095610090366004610b4c565b6101a7565b005b6002546100b79073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b61011d6040518060400160405280600c81526020017f322e302e312d626574612e32000000000000000000000000000000000000000081525081565b6040516100d89190610bea565b610095610138366004610cc6565b61061c565b61016461014b366004610df0565b6001602081905260009182526040909120805491015482565b604080519283526020830191909152016100d8565b610095610853565b7f0000000000000000000000005207cfa0166e8de0fcdfd78b4d17b68587be306d6100b7565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa158015610214573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102389190610e0d565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461029c576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060008373ffffffffffffffffffffffffffffffffffffffff1663fa24f7436040518163ffffffff1660e01b8152600401600060405180830381865afa1580156102ec573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526103329190810190610e2a565b92509250925060007f0000000000000000000000005207cfa0166e8de0fcdfd78b4d17b68587be306d73ffffffffffffffffffffffffffffffffffffffff16635f0150cb8585856040518463ffffffff1660e01b815260040161039793929190610efb565b6040805180830381865afa1580156103b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103d79190610f29565b5090508473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461043f576040517f6b0f689100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60028573ffffffffffffffffffffffffffffffffffffffff1663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa15801561048c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104b09190610f9f565b60028111156104c1576104c1610f70565b146104f8576040517f8f8af25f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052806105788773ffffffffffffffffffffffffffffffffffffffff1663bcef3b556040518163ffffffff1660e01b8152600401602060405180830381865afa158015610551573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105759190610fc0565b90565b81526020018673ffffffffffffffffffffffffffffffffffffffff16638b85902b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ec9190610fc0565b905263ffffffff909416600090815260016020818152604090922086518155959091015194019390935550505050565b600054610100900460ff161580801561063c5750600054600160ff909116105b806106565750303b158015610656575060005460ff166001145b6106e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561074457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b60005b83518110156107aa57600084828151811061076457610764610fd9565b60209081029190910181015180820151905163ffffffff1660009081526001808452604090912082518155919092015191015550806107a281611008565b915050610747565b50600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8416179055801561084e57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b600033905060008060008373ffffffffffffffffffffffffffffffffffffffff1663fa24f7436040518163ffffffff1660e01b8152600401600060405180830381865afa1580156108a8573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526108ee9190810190610e2a565b92509250925060007f0000000000000000000000005207cfa0166e8de0fcdfd78b4d17b68587be306d73ffffffffffffffffffffffffffffffffffffffff16635f0150cb8585856040518463ffffffff1660e01b815260040161095393929190610efb565b6040805180830381865afa15801561096f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109939190610f29565b5090508473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146109fb576040517f6b0f689100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160008563ffffffff1663ffffffff168152602001908152602001600020600101548573ffffffffffffffffffffffffffffffffffffffff16638b85902b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8d9190610fc0565b11610a99575050505050565b60028573ffffffffffffffffffffffffffffffffffffffff1663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ae6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b0a9190610f9f565b6002811115610b1b57610b1b610f70565b146104f8575050505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610b4957600080fd5b50565b600060208284031215610b5e57600080fd5b8135610b6981610b27565b9392505050565b60005b83811015610b8b578181015183820152602001610b73565b83811115610b9a576000848401525b50505050565b60008151808452610bb8816020860160208601610b70565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610b696020830184610ba0565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715610c4f57610c4f610bfd565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715610c9c57610c9c610bfd565b604052919050565b63ffffffff81168114610b4957600080fd5b8035610cc181610b27565b919050565b6000806040808486031215610cda57600080fd5b833567ffffffffffffffff80821115610cf257600080fd5b818601915086601f830112610d0657600080fd5b8135602082821115610d1a57610d1a610bfd565b610d28818360051b01610c55565b8281528181019350606092830285018201928a841115610d4757600080fd5b948201945b83861015610dd457858b0381811215610d655760008081fd5b610d6d610c2c565b8735610d7881610ca4565b81527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08201891315610daa5760008081fd5b610db2610c2c565b8886013581528989013586820152818601528652509485019493820193610d4c565b509650610de2888201610cb6565b955050505050509250929050565b600060208284031215610e0257600080fd5b8135610b6981610ca4565b600060208284031215610e1f57600080fd5b8151610b6981610b27565b600080600060608486031215610e3f57600080fd5b8351610e4a81610ca4565b60208501516040860151919450925067ffffffffffffffff80821115610e6f57600080fd5b818601915086601f830112610e8357600080fd5b815181811115610e9557610e95610bfd565b610ec660207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601610c55565b9150808252876020828501011115610edd57600080fd5b610eee816020840160208601610b70565b5080925050509250925092565b63ffffffff84168152826020820152606060408201526000610f206060830184610ba0565b95945050505050565b60008060408385031215610f3c57600080fd5b8251610f4781610b27565b602084015190925067ffffffffffffffff81168114610f6557600080fd5b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600060208284031215610fb157600080fd5b815160038110610b6957600080fd5b600060208284031215610fd257600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611060577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b506001019056fea164736f6c634300080f000a"; + bytes internal constant acc33Code = +- hex"6080604052600436106102f25760003560e01c806370872aa51161018f578063c6f0308c116100e1578063ec5e63081161008a578063fa24f74311610064578063fa24f74314610b18578063fa315aa914610b3c578063fe2bbeb214610b6f57600080fd5b8063ec5e630814610a95578063eff0f59214610ac8578063f8f43ff614610af857600080fd5b8063d6ae3cd5116100bb578063d6ae3cd514610a0f578063d8cc1a3c14610a42578063dabd396d14610a6257600080fd5b8063c6f0308c14610937578063cf09e0d0146109c1578063d5d44d80146109e257600080fd5b80638d450a9511610143578063bcef3b551161011d578063bcef3b55146108b7578063bd8da956146108f7578063c395e1ca1461091757600080fd5b80638d450a9514610777578063a445ece6146107aa578063bbdc02db1461087657600080fd5b80638129fc1c116101745780638129fc1c1461071a5780638980e0cc146107225780638b85902b1461073757600080fd5b806370872aa5146106f25780637b0f0adc1461070757600080fd5b80633fc8cef3116102485780635c0cba33116101fc5780636361506d116101d65780636361506d1461066c5780636b6716c0146106ac5780636f034409146106df57600080fd5b80635c0cba3314610604578063609d33341461063757806360e274641461064c57600080fd5b806354fd4d501161022d57806354fd4d501461055e57806357da950e146105b45780635a5fa2d9146105e457600080fd5b80633fc8cef314610518578063472777c61461054b57600080fd5b80632810e1d6116102aa57806337b1b2291161028457806337b1b229146104655780633a768463146104a55780633e3ac912146104d857600080fd5b80632810e1d6146103de5780632ad69aeb146103f357806330dbe5701461041357600080fd5b806319effeb4116102db57806319effeb414610339578063200d2ed21461038457806325fc2ace146103bf57600080fd5b806301935130146102f757806303c2924d14610319575b600080fd5b34801561030357600080fd5b506103176103123660046154e2565b610b9f565b005b34801561032557600080fd5b5061031761033436600461553d565b610ec0565b34801561034557600080fd5b506000546103669068010000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020015b60405180910390f35b34801561039057600080fd5b506000546103b290700100000000000000000000000000000000900460ff1681565b60405161037b919061558e565b3480156103cb57600080fd5b506008545b60405190815260200161037b565b3480156103ea57600080fd5b506103b2611566565b3480156103ff57600080fd5b506103d061040e36600461553d565b61180b565b34801561041f57600080fd5b506001546104409073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161037b565b34801561047157600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90033560601c610440565b3480156104b157600080fd5b507f000000000000000000000000444e09fe6d839273316a87002ab0efbea6fe7806610440565b3480156104e457600080fd5b50600054610508907201000000000000000000000000000000000000900460ff1681565b604051901515815260200161037b565b34801561052457600080fd5b507f000000000000000000000000ef179756ea6525afade217ca5ab0b1b5cfe0fd92610440565b6103176105593660046155cf565b611841565b34801561056a57600080fd5b506105a76040518060400160405280600a81526020017f312e332e302d72632e310000000000000000000000000000000000000000000081525081565b60405161037b9190615666565b3480156105c057600080fd5b506008546009546105cf919082565b6040805192835260208301919091520161037b565b3480156105f057600080fd5b506103d06105ff366004615679565b611853565b34801561061057600080fd5b507f000000000000000000000000970670459734a83899773a0fd45941b5afc1200e610440565b34801561064357600080fd5b506105a761188d565b34801561065857600080fd5b506103176106673660046156b7565b61189b565b34801561067857600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003603401356103d0565b3480156106b857600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610366565b6103176106ed3660046156e9565b611a42565b3480156106fe57600080fd5b506009546103d0565b6103176107153660046155cf565b61251b565b610317612528565b34801561072e57600080fd5b506002546103d0565b34801561074357600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401356103d0565b34801561078357600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006103d0565b3480156107b657600080fd5b506108226107c5366004615679565b6007602052600090815260409020805460019091015460ff821691610100810463ffffffff1691650100000000009091046fffffffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff1684565b60408051941515855263ffffffff90931660208501526fffffffffffffffffffffffffffffffff9091169183019190915273ffffffffffffffffffffffffffffffffffffffff16606082015260800161037b565b34801561088257600080fd5b5060405163ffffffff7f000000000000000000000000000000000000000000000000000000000000000016815260200161037b565b3480156108c357600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003601401356103d0565b34801561090357600080fd5b50610366610912366004615679565b612a81565b34801561092357600080fd5b506103d0610932366004615728565b612c60565b34801561094357600080fd5b50610957610952366004615679565b612e43565b6040805163ffffffff909816885273ffffffffffffffffffffffffffffffffffffffff968716602089015295909416948601949094526fffffffffffffffffffffffffffffffff9182166060860152608085015291821660a08401521660c082015260e00161037b565b3480156109cd57600080fd5b506000546103669067ffffffffffffffff1681565b3480156109ee57600080fd5b506103d06109fd3660046156b7565b60036020526000908152604090205481565b348015610a1b57600080fd5b507f00000000000000000000000000000000000000000000000000000000000003856103d0565b348015610a4e57600080fd5b50610317610a5d36600461575a565b612eda565b348015610a6e57600080fd5b507f00000000000000000000000000000000000000000000000000000000000004b0610366565b348015610aa157600080fd5b507f00000000000000000000000000000000000000000000000000000000000000046103d0565b348015610ad457600080fd5b50610508610ae3366004615679565b60046020526000908152604090205460ff1681565b348015610b0457600080fd5b50610317610b133660046155cf565b613509565b348015610b2457600080fd5b50610b2d6139c6565b60405161037b939291906157e4565b348015610b4857600080fd5b507f00000000000000000000000000000000000000000000000000000000000000086103d0565b348015610b7b57600080fd5b50610508610b8a366004615679565b60066020526000908152604090205460ff1681565b60008054700100000000000000000000000000000000900460ff166002811115610bcb57610bcb61555f565b14610c02576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000547201000000000000000000000000000000000000900460ff1615610c55576040517f0ea2e75200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610c8c367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013590565b90565b610ca3610c9e36869003860186615838565b613a41565b14610cda576040517f9cc00b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82606001358282604051610cef9291906158c5565b604051809103902014610d2e576040517fd81d583b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610d77610d7284848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613a9d92505050565b613b0a565b90506000610d9e82600881518110610d9157610d916158d5565b6020026020010151613cc0565b9050602081511115610ddc576040517fd81d583b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602081810151825190910360031b1c367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401358103610e51576040517fb8ed883000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050600180547fffffffffffffffffffffffff000000000000000000000000000000000000000016331790555050600080547fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff1672010000000000000000000000000000000000001790555050565b60008054700100000000000000000000000000000000900460ff166002811115610eec57610eec61555f565b14610f23576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028381548110610f3857610f386158d5565b906000526020600020906005020190506000610f5384612a81565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b081169082161015610fbc576040517ff2440b5300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008481526006602052604090205460ff1615611005576040517ff1a9458100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600084815260056020526040902080548015801561102257508515155b156110bd578354640100000000900473ffffffffffffffffffffffffffffffffffffffff16600081156110555781611071565b600186015473ffffffffffffffffffffffffffffffffffffffff165b905061107d8187613d74565b50505060009485525050600660205250506040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b6000868152600760209081526040918290208251608081018452815460ff81161515808352610100820463ffffffff16948301949094526501000000000090046fffffffffffffffffffffffffffffffff16938101939093526001015473ffffffffffffffffffffffffffffffffffffffff166060830152611160576fffffffffffffffffffffffffffffffff6040820152600181526000869003611160578195505b600086826020015163ffffffff166111789190615933565b90506000838211611189578161118b565b835b602084015190915063ffffffff165b818110156112d75760008682815481106111b6576111b66158d5565b6000918252602080832090910154808352600690915260409091205490915060ff1661120e576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028281548110611223576112236158d5565b600091825260209091206005909102018054909150640100000000900473ffffffffffffffffffffffffffffffffffffffff161580156112805750600481015460408701516fffffffffffffffffffffffffffffffff9182169116115b156112c257600181015473ffffffffffffffffffffffffffffffffffffffff16606087015260048101546fffffffffffffffffffffffffffffffff1660408701525b505080806112cf9061594b565b91505061119a565b5063ffffffff818116602085810191825260008c81526007909152604090819020865181549351928801517fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009094169015157fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ff161761010092909416918202939093177fffffffffffffffffffffff00000000000000000000000000000000ffffffffff16650100000000006fffffffffffffffffffffffffffffffff909316929092029190911782556060850151600190920180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9093169290921790915584900361155b57606083015160008a815260066020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558915801561145757506000547201000000000000000000000000000000000000900460ff165b156114cc5760015473ffffffffffffffffffffffffffffffffffffffff1661147f818a613d74565b885473ffffffffffffffffffffffffffffffffffffffff909116640100000000027fffffffffffffffff0000000000000000000000000000000000000000ffffffff909116178855611559565b61151373ffffffffffffffffffffffffffffffffffffffff8216156114f1578161150d565b600189015473ffffffffffffffffffffffffffffffffffffffff165b89613d74565b87547fffffffffffffffff0000000000000000000000000000000000000000ffffffff1664010000000073ffffffffffffffffffffffffffffffffffffffff8316021788555b505b505050505050505050565b600080600054700100000000000000000000000000000000900460ff1660028111156115945761159461555f565b146115cb576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000805260066020527f54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4f85460ff1661162f576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600260008154811061165b5761165b6158d5565b6000918252602090912060059091020154640100000000900473ffffffffffffffffffffffffffffffffffffffff1614611696576001611699565b60025b6000805467ffffffffffffffff421668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff82168117835592935083927fffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffff000000000000000000ffffffffffffffff9091161770010000000000000000000000000000000083600281111561174a5761174a61555f565b02179055600281111561175f5761175f61555f565b6040517f5e186f09b9c93491f14e277eea7faa5de6a2d4bda75a79af7a3684fbfb42da6090600090a27f000000000000000000000000970670459734a83899773a0fd45941b5afc1200e73ffffffffffffffffffffffffffffffffffffffff1663838c2d1e6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156117f057600080fd5b505af1158015611804573d6000803e3d6000fd5b5050505090565b6005602052816000526040600020818154811061182757600080fd5b90600052602060002001600091509150505481565b905090565b61184e8383836001611a42565b505050565b6000818152600760209081526040808320600590925282208054825461188490610100900463ffffffff1682615983565b95945050505050565b606061183c60546020613e75565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260036020526040812080549082905590819003611900576040517f17bfe5f700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517ff3fef3a300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152602482018390527f000000000000000000000000ef179756ea6525afade217ca5ab0b1b5cfe0fd92169063f3fef3a390604401600060405180830381600087803b15801561199057600080fd5b505af11580156119a4573d6000803e3d6000fd5b5050505060008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114611a02576040519150601f19603f3d011682016040523d82523d6000602084013e611a07565b606091505b505090508061184e576040517f83e6cc6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008054700100000000000000000000000000000000900460ff166002811115611a6e57611a6e61555f565b14611aa5576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028481548110611aba57611aba6158d5565b60009182526020918290206040805160e0810182526005909302909101805463ffffffff8116845273ffffffffffffffffffffffffffffffffffffffff64010000000090910481169484019490945260018101549093169082015260028201546fffffffffffffffffffffffffffffffff908116606083015260038301546080830181905260049093015480821660a084015270010000000000000000000000000000000090041660c082015291508514611ba1576040517f3014033200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60a0810151600083156fffffffffffffffffffffffffffffffff83161760011b90506000611c61826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169050861580611c9c5750611c997f00000000000000000000000000000000000000000000000000000000000000046002615933565b81145b8015611ca6575084155b15611cdd576040517fa42637bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000547201000000000000000000000000000000000000900460ff168015611d03575086155b15611d3a576040517f0ea2e75200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000008811115611d94576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611dbf7f00000000000000000000000000000000000000000000000000000000000000046001615933565b8103611dd157611dd186888588613ec7565b34611ddb83612c60565b14611e12576040517f8620aa1900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611e1d88612a81565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b0811690821603611e85576040517f3381d11400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611eb260017f0000000000000000000000000000000000000000000000000000000000000008615983565b8303611ff0577f000000000000000000000000444e09fe6d839273316a87002ab0efbea6fe780673ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f47919061599a565b73ffffffffffffffffffffffffffffffffffffffff1663f3f480d96040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f91573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fb591906159b7565b611fe9907f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff166159d0565b9050612083565b61201b60017f0000000000000000000000000000000000000000000000000000000000000004615983565b830361205657611fe97f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1660026159fc565b507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff165b6120b7817f00000000000000000000000000000000000000000000000000000000000004b067ffffffffffffffff16615a2c565b67ffffffffffffffff166120d28367ffffffffffffffff1690565b67ffffffffffffffff16111561211957612116817f00000000000000000000000000000000000000000000000000000000000004b067ffffffffffffffff16615a2c565b91505b6000604083901b421760008a8152608087901b6fffffffffffffffffffffffffffffffff8d1617602052604081209192509060008181526004602052604090205490915060ff1615612197576040517f80497e3b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60016004600083815260200190815260200160002060006101000a81548160ff02191690831515021790555060026040518060e001604052808d63ffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020013373ffffffffffffffffffffffffffffffffffffffff168152602001346fffffffffffffffffffffffffffffffff1681526020018c8152602001886fffffffffffffffffffffffffffffffff168152602001846fffffffffffffffffffffffffffffffff16815250908060018154018082558091505060019003906000526020600020906005020160009091909190915060008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060608201518160020160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055506080820151816003015560a08201518160040160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555060c08201518160040160106101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055505050600560008c8152602001908152602001600020600160028054905061242d9190615983565b81546001810183556000928352602083200155604080517fd0e30db0000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ef179756ea6525afade217ca5ab0b1b5cfe0fd92169263d0e30db09234926004808301939282900301818588803b1580156124c557600080fd5b505af11580156124d9573d6000803e3d6000fd5b50506040513393508d92508e91507f9b3245740ec3b155098a55be84957a4da13eaf7f14a8bc6f53126c0b9350f2be90600090a4505050505050505050505050565b61184e8383836000611a42565b60005471010000000000000000000000000000000000900460ff161561257a576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f7258a80700000000000000000000000000000000000000000000000000000000815263ffffffff7f0000000000000000000000000000000000000000000000000000000000000000166004820152600090819073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000970670459734a83899773a0fd45941b5afc1200e1690637258a807906024016040805180830381865afa15801561262e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126529190615a55565b90925090508161268e576040517f6a6bc3b200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080518082019091528281526020018190526008829055600981905536607a146126c157639824bdab6000526004601cfd5b80367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401351161275b576040517ff40239db000000000000000000000000000000000000000000000000000000008152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013560048201526024015b60405180910390fd5b6040805160e08101825263ffffffff8082526000602083018181527ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe369081013560f01c90038035606090811c868801908152346fffffffffffffffffffffffffffffffff81811693890193845260149094013560808901908152600160a08a0181815242871660c08c019081526002805493840181558a529a5160059092027f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace81018054995173ffffffffffffffffffffffffffffffffffffffff908116640100000000027fffffffffffffffff000000000000000000000000000000000000000000000000909b1694909c16939093179890981790915592517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5acf87018054918a167fffffffffffffffffffffffff000000000000000000000000000000000000000090921691909117905592517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad0860180549186167fffffffffffffffffffffffffffffffff0000000000000000000000000000000090921691909117905591517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad185015551955182167001000000000000000000000000000000000295909116949094177f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad29091015580547fffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffff167101000000000000000000000000000000000017815583517fd0e30db000000000000000000000000000000000000000000000000000000000815293517f000000000000000000000000ef179756ea6525afade217ca5ab0b1b5cfe0fd929092169363d0e30db093926004828101939282900301818588803b158015612a3057600080fd5b505af1158015612a44573d6000803e3d6000fd5b5050600080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000164267ffffffffffffffff161790555050505050565b600080600054700100000000000000000000000000000000900460ff166002811115612aaf57612aaf61555f565b14612ae6576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028381548110612afb57612afb6158d5565b600091825260208220600590910201805490925063ffffffff90811614612b6a57815460028054909163ffffffff16908110612b3957612b396158d5565b906000526020600020906005020160040160109054906101000a90046fffffffffffffffffffffffffffffffff1690505b6004820154600090612ba290700100000000000000000000000000000000900467ffffffffffffffff165b67ffffffffffffffff1690565b612bb69067ffffffffffffffff1642615983565b612bd5612b95846fffffffffffffffffffffffffffffffff1660401c90565b67ffffffffffffffff16612be99190615933565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b01667ffffffffffffffff168167ffffffffffffffff1611612c365780611884565b7f00000000000000000000000000000000000000000000000000000000000004b095945050505050565b600080612cff836fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1690507f0000000000000000000000000000000000000000000000000000000000000008811115612d5e576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b642e90edd00062061a806311e1a3006000612d798383615aa8565b9050670de0b6b3a76400006000612db0827f0000000000000000000000000000000000000000000000000000000000000008615abc565b90506000612dce612dc9670de0b6b3a764000086615abc565b614078565b90506000612ddc84846142d3565b90506000612dea8383614322565b90506000612df782614350565b90506000612e1682612e11670de0b6b3a76400008f615abc565b614538565b90506000612e248b83614322565b9050612e30818d615abc565b9f9e505050505050505050505050505050565b60028181548110612e5357600080fd5b60009182526020909120600590910201805460018201546002830154600384015460049094015463ffffffff8416955064010000000090930473ffffffffffffffffffffffffffffffffffffffff908116949216926fffffffffffffffffffffffffffffffff91821692918082169170010000000000000000000000000000000090041687565b60008054700100000000000000000000000000000000900460ff166002811115612f0657612f0661555f565b14612f3d576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028781548110612f5257612f526158d5565b6000918252602082206005919091020160048101549092506fffffffffffffffffffffffffffffffff16908715821760011b9050612fb17f00000000000000000000000000000000000000000000000000000000000000086001615933565b61304d826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1614613087576040517f5f53dd9800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080891561317e576130da7f00000000000000000000000000000000000000000000000000000000000000047f0000000000000000000000000000000000000000000000000000000000000008615983565b6001901b6130f9846fffffffffffffffffffffffffffffffff16614569565b6fffffffffffffffffffffffffffffffff166131159190615af9565b156131525761314961313a60016fffffffffffffffffffffffffffffffff8716615b0d565b865463ffffffff166000614608565b60030154613174565b7f00000000000000000000000000000000000000000000000000000000000000005b91508490506131a8565b600385015491506131a561313a6fffffffffffffffffffffffffffffffff86166001615b36565b90505b600882901b60088a8a6040516131bf9291906158c5565b6040518091039020901b14613200576040517f696550ff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061320b8c6146ec565b9050600061321a836003015490565b6040517fe14ced320000000000000000000000000000000000000000000000000000000081527f000000000000000000000000444e09fe6d839273316a87002ab0efbea6fe780673ffffffffffffffffffffffffffffffffffffffff169063e14ced3290613294908f908f908f908f908a90600401615baa565b6020604051808303816000875af11580156132b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132d791906159b7565b600485015491149150600090600290613382906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b61341e896fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b6134289190615be4565b6134329190615c07565b60ff161590508115158103613473576040517ffb4e40dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8754640100000000900473ffffffffffffffffffffffffffffffffffffffff16156134ca576040517f9071e6af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505085547fffffffffffffffff0000000000000000000000000000000000000000ffffffff163364010000000002179095555050505050505050505050565b60008054700100000000000000000000000000000000900460ff1660028111156135355761353561555f565b1461356c576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060008061357b8661471b565b9350935093509350600061359185858585614b24565b905060007f000000000000000000000000444e09fe6d839273316a87002ab0efbea6fe780673ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015613600573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613624919061599a565b90506001890361371c5773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a84613680367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036034013590565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815260048101939093526024830191909152604482015260206064820152608481018a905260a4015b6020604051808303816000875af11580156136f2573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061371691906159b7565b5061155b565b600289036137485773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a8489613680565b600389036137745773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a8487613680565b600489036138fb5760006137ba6fffffffffffffffffffffffffffffffff85167f0000000000000000000000000000000000000000000000000000000000000004614bde565b6009546137c79190615933565b6137d2906001615933565b9050367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900360540135811061383b57367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036054013561383d565b805b905073ffffffffffffffffffffffffffffffffffffffff82166352f0f3ad8b8560405160e084901b7fffffffff000000000000000000000000000000000000000000000000000000001681526004810192909252602482015260c084901b604482015260086064820152608481018b905260a4016020604051808303816000875af11580156138d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138f491906159b7565b505061155b565b60058903613994576040517f52f0f3ad000000000000000000000000000000000000000000000000000000008152600481018a9052602481018390527f000000000000000000000000000000000000000000000000000000000000038560c01b6044820152600860648201526084810188905273ffffffffffffffffffffffffffffffffffffffff8216906352f0f3ad9060a4016136d3565b6040517fff137e6500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000000367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003601401356060613a1f61188d565b9050909192565b600081831015613a365781613a38565b825b90505b92915050565b60008160000151826020015183604001518460600151604051602001613a80949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b60408051808201909152600080825260208201528151600003613aec576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50604080518082019091528151815260209182019181019190915290565b60606000806000613b1a85614c8c565b919450925090506001816001811115613b3557613b3561555f565b14613b6c576040517f4b9c6abe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8451613b788385615933565b14613baf576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516020808252610420820190925290816020015b6040805180820190915260008082526020820152815260200190600190039081613bc65790505093506000835b8651811015613cb457600080613c396040518060400160405280858c60000151613c1d9190615983565b8152602001858c60200151613c329190615933565b9052614c8c565b509150915060405180604001604052808383613c559190615933565b8152602001848b60200151613c6a9190615933565b815250888581518110613c7f57613c7f6158d5565b6020908102919091010152613c95600185615933565b9350613ca18183615933565b613cab9084615933565b92505050613bf3565b50845250919392505050565b60606000806000613cd085614c8c565b919450925090506000816001811115613ceb57613ceb61555f565b14613d22576040517f1ff9b2e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613d2c8284615933565b855114613d65576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6118848560200151848461512a565b600281015473ffffffffffffffffffffffffffffffffffffffff8316600090815260036020526040812080546fffffffffffffffffffffffffffffffff90931692839290613dc3908490615933565b90915550506040517f7eee288d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152602482018390527f000000000000000000000000ef179756ea6525afade217ca5ab0b1b5cfe0fd921690637eee288d90604401600060405180830381600087803b158015613e5857600080fd5b505af1158015613e6c573d6000803e3d6000fd5b50505050505050565b604051818152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90038284820160208401378260208301016000815260208101604052505092915050565b6000613ee66fffffffffffffffffffffffffffffffff84166001615b36565b90506000613ef682866001614608565b9050600086901a8380613fe25750613f2f60027f0000000000000000000000000000000000000000000000000000000000000004615af9565b6004830154600290613fd3906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b613fdd9190615c07565b60ff16145b1561403a5760ff811660011480613ffc575060ff81166002145b614035576040517ff40239db00000000000000000000000000000000000000000000000000000000815260048101889052602401612752565b613e6c565b60ff811615613e6c576040517ff40239db00000000000000000000000000000000000000000000000000000000815260048101889052602401612752565b6fffffffffffffffffffffffffffffffff811160071b81811c67ffffffffffffffff1060061b1781811c63ffffffff1060051b1781811c61ffff1060041b1781811c60ff1060031b17600082136140d757631615e6386000526004601cfd5b7ff8f9f9faf9fdfafbf9fdfcfdfafbfcfef9fafdfafcfcfbfefafafcfbffffffff6f8421084210842108cc6318c6db6d54be83831c1c601f161a1890811b609f90811c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506029190037d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b302017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d90565b60007812725dd1d243aba0e75fe645cc4873f9e65afe688c928e1f218311670de0b6b3a76400000215820261431057637c5f487d6000526004601cfd5b50670de0b6b3a7640000919091020490565b6000816000190483118202156143405763bac65e5b6000526004601cfd5b50670de0b6b3a764000091020490565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdc0d0570925a462d7821361437e57919050565b680755bf798b4a1bf1e5821261439c5763a37bfec96000526004601cfd5b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b6000613a38670de0b6b3a76400008361455086614078565b61455a9190615c29565b6145649190615ce5565b614350565b6000806145f6837e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b600160ff919091161b90920392915050565b600080826146515761464c6fffffffffffffffffffffffffffffffff86167f00000000000000000000000000000000000000000000000000000000000000046151bf565b61466c565b61466c856fffffffffffffffffffffffffffffffff1661534b565b905060028481548110614681576146816158d5565b906000526020600020906005020191505b60048201546fffffffffffffffffffffffffffffffff8281169116146146e457815460028054909163ffffffff169081106146cf576146cf6158d5565b90600052602060002090600502019150614692565b509392505050565b60008060008060006146fd8661471b565b935093509350935061471184848484614b24565b9695505050505050565b600080600080600085905060006002828154811061473b5761473b6158d5565b600091825260209091206004600590920201908101549091507f000000000000000000000000000000000000000000000000000000000000000490614812906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff161161484c576040517fb34b5c2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000815b60048301547f000000000000000000000000000000000000000000000000000000000000000490614913906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff16925082111561498857825463ffffffff166149527f00000000000000000000000000000000000000000000000000000000000000046001615933565b830361495c578391505b6002818154811061496f5761496f6158d5565b9060005260206000209060050201935080945050614850565b600481810154908401546fffffffffffffffffffffffffffffffff91821691166000816fffffffffffffffffffffffffffffffff166149f16149dc856fffffffffffffffffffffffffffffffff1660011c90565b6fffffffffffffffffffffffffffffffff1690565b6fffffffffffffffffffffffffffffffff161490508015614ac0576000614a29836fffffffffffffffffffffffffffffffff16614569565b6fffffffffffffffffffffffffffffffff161115614a94576000614a6b614a6360016fffffffffffffffffffffffffffffffff8616615b0d565b896001614608565b6003810154600490910154909c506fffffffffffffffffffffffffffffffff169a50614a9a9050565b6008549a505b600386015460048701549099506fffffffffffffffffffffffffffffffff169750614b16565b6000614ae2614a636fffffffffffffffffffffffffffffffff85166001615b36565b6003808901546004808b015492840154930154909e506fffffffffffffffffffffffffffffffff9182169d50919b50169850505b505050505050509193509193565b60006fffffffffffffffffffffffffffffffff841615614b915760408051602081018790526fffffffffffffffffffffffffffffffff8087169282019290925260608101859052908316608082015260a00160405160208183030381529060405280519060200120611884565b8282604051602001614bbf9291909182526fffffffffffffffffffffffffffffffff16602082015260400190565b6040516020818303038152906040528051906020012095945050505050565b600080614c6b847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1690508083036001841b600180831b0386831b17039250505092915050565b60008060008360000151600003614ccf576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020840151805160001a607f8111614cf4576000600160009450945094505050615123565b60b78111614e0a576000614d09608083615983565b905080876000015111614d48576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001838101517fff00000000000000000000000000000000000000000000000000000000000000169082148015614dc057507f80000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000008216105b15614df7576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5060019550935060009250615123915050565b60bf8111614f68576000614e1f60b783615983565b905080876000015111614e5e576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614ec0576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c60378111614f08576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614f128184615933565b895111614f4b576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614f56836001615933565b97509550600094506151239350505050565b60f78111614fcd576000614f7d60c083615983565b905080876000015111614fbc576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600195509350849250615123915050565b6000614fda60f783615983565b905080876000015111615019576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff0000000000000000000000000000000000000000000000000000000000000016600081900361507b576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c603781116150c3576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6150cd8184615933565b895111615106576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b615111836001615933565b97509550600194506151239350505050565b9193909250565b60608167ffffffffffffffff81111561514557615145615809565b6040519080825280601f01601f19166020018201604052801561516f576020820181803683370190505b50905081156151b85760006151848486615933565b90506020820160005b848110156151a557828101518282015260200161518d565b848111156151b4576000858301525b5050505b9392505050565b60008161525e846fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff16116152745763b34b5c226000526004601cfd5b61527d8361534b565b90508161531c826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1611613a3b57613a38615332836001615933565b6fffffffffffffffffffffffffffffffff8316906153f0565b600081196001830116816153df827e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169390931c8015179392505050565b60008061547d847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169050808303600180821b0385821b179250505092915050565b60008083601f8401126154ab57600080fd5b50813567ffffffffffffffff8111156154c357600080fd5b6020830191508360208285010111156154db57600080fd5b9250929050565b600080600083850360a08112156154f857600080fd5b608081121561550657600080fd5b50839250608084013567ffffffffffffffff81111561552457600080fd5b61553086828701615499565b9497909650939450505050565b6000806040838503121561555057600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60208101600383106155c9577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b6000806000606084860312156155e457600080fd5b505081359360208301359350604090920135919050565b6000815180845260005b8181101561562157602081850181015186830182015201615605565b81811115615633576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000613a3860208301846155fb565b60006020828403121561568b57600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff811681146156b457600080fd5b50565b6000602082840312156156c957600080fd5b81356151b881615692565b803580151581146156e457600080fd5b919050565b600080600080608085870312156156ff57600080fd5b84359350602085013592506040850135915061571d606086016156d4565b905092959194509250565b60006020828403121561573a57600080fd5b81356fffffffffffffffffffffffffffffffff811681146151b857600080fd5b6000806000806000806080878903121561577357600080fd5b86359550615783602088016156d4565b9450604087013567ffffffffffffffff808211156157a057600080fd5b6157ac8a838b01615499565b909650945060608901359150808211156157c557600080fd5b506157d289828a01615499565b979a9699509497509295939492505050565b63ffffffff8416815282602082015260606040820152600061188460608301846155fb565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006080828403121561584a57600080fd5b6040516080810181811067ffffffffffffffff82111715615894577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561594657615946615904565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361597c5761597c615904565b5060010190565b60008282101561599557615995615904565b500390565b6000602082840312156159ac57600080fd5b81516151b881615692565b6000602082840312156159c957600080fd5b5051919050565b600067ffffffffffffffff8083168185168083038211156159f3576159f3615904565b01949350505050565b600067ffffffffffffffff80831681851681830481118215151615615a2357615a23615904565b02949350505050565b600067ffffffffffffffff83811690831681811015615a4d57615a4d615904565b039392505050565b60008060408385031215615a6857600080fd5b505080516020909101519092909150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082615ab757615ab7615a79565b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615af457615af4615904565b500290565b600082615b0857615b08615a79565b500690565b60006fffffffffffffffffffffffffffffffff83811690831681811015615a4d57615a4d615904565b60006fffffffffffffffffffffffffffffffff8083168185168083038211156159f3576159f3615904565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b606081526000615bbe606083018789615b61565b8281036020840152615bd1818688615b61565b9150508260408301529695505050505050565b600060ff821660ff841680821015615bfe57615bfe615904565b90039392505050565b600060ff831680615c1a57615c1a615a79565b8060ff84160691505092915050565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600084136000841385830485118282161615615c6a57615c6a615904565b7f80000000000000000000000000000000000000000000000000000000000000006000871286820588128184161615615ca557615ca5615904565b60008712925087820587128484161615615cc157615cc1615904565b87850587128184161615615cd757615cd7615904565b505050929093029392505050565b600082615cf457615cf4615a79565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f800000000000000000000000000000000000000000000000000000000000000083141615615d4857615d48615904565b50059056fea164736f6c634300080f000a"; ++ hex"6080604052600436106102f25760003560e01c806370872aa51161018f578063c6f0308c116100e1578063ec5e63081161008a578063fa24f74311610064578063fa24f74314610b18578063fa315aa914610b3c578063fe2bbeb214610b6f57600080fd5b8063ec5e630814610a95578063eff0f59214610ac8578063f8f43ff614610af857600080fd5b8063d6ae3cd5116100bb578063d6ae3cd514610a0f578063d8cc1a3c14610a42578063dabd396d14610a6257600080fd5b8063c6f0308c14610937578063cf09e0d0146109c1578063d5d44d80146109e257600080fd5b80638d450a9511610143578063bcef3b551161011d578063bcef3b55146108b7578063bd8da956146108f7578063c395e1ca1461091757600080fd5b80638d450a9514610777578063a445ece6146107aa578063bbdc02db1461087657600080fd5b80638129fc1c116101745780638129fc1c1461071a5780638980e0cc146107225780638b85902b1461073757600080fd5b806370872aa5146106f25780637b0f0adc1461070757600080fd5b80633fc8cef3116102485780635c0cba33116101fc5780636361506d116101d65780636361506d1461066c5780636b6716c0146106ac5780636f034409146106df57600080fd5b80635c0cba3314610604578063609d33341461063757806360e274641461064c57600080fd5b806354fd4d501161022d57806354fd4d501461055e57806357da950e146105b45780635a5fa2d9146105e457600080fd5b80633fc8cef314610518578063472777c61461054b57600080fd5b80632810e1d6116102aa57806337b1b2291161028457806337b1b229146104655780633a768463146104a55780633e3ac912146104d857600080fd5b80632810e1d6146103de5780632ad69aeb146103f357806330dbe5701461041357600080fd5b806319effeb4116102db57806319effeb414610339578063200d2ed21461038457806325fc2ace146103bf57600080fd5b806301935130146102f757806303c2924d14610319575b600080fd5b34801561030357600080fd5b506103176103123660046154e2565b610b9f565b005b34801561032557600080fd5b5061031761033436600461553d565b610ec0565b34801561034557600080fd5b506000546103669068010000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020015b60405180910390f35b34801561039057600080fd5b506000546103b290700100000000000000000000000000000000900460ff1681565b60405161037b919061558e565b3480156103cb57600080fd5b506008545b60405190815260200161037b565b3480156103ea57600080fd5b506103b2611566565b3480156103ff57600080fd5b506103d061040e36600461553d565b61180b565b34801561041f57600080fd5b506001546104409073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161037b565b34801561047157600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90033560601c610440565b3480156104b157600080fd5b507f000000000000000000000000180cbe2ebb9f37d3a3c542ddc2546fd160555a73610440565b3480156104e457600080fd5b50600054610508907201000000000000000000000000000000000000900460ff1681565b604051901515815260200161037b565b34801561052457600080fd5b507f000000000000000000000000ef179756ea6525afade217ca5ab0b1b5cfe0fd92610440565b6103176105593660046155cf565b611841565b34801561056a57600080fd5b506105a76040518060400160405280600c81526020017f312e332e312d626574612e32000000000000000000000000000000000000000081525081565b60405161037b9190615666565b3480156105c057600080fd5b506008546009546105cf919082565b6040805192835260208301919091520161037b565b3480156105f057600080fd5b506103d06105ff366004615679565b611853565b34801561061057600080fd5b507f000000000000000000000000970670459734a83899773a0fd45941b5afc1200e610440565b34801561064357600080fd5b506105a761188d565b34801561065857600080fd5b506103176106673660046156b7565b61189b565b34801561067857600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003603401356103d0565b3480156106b857600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610366565b6103176106ed3660046156e9565b611a42565b3480156106fe57600080fd5b506009546103d0565b6103176107153660046155cf565b61251b565b610317612528565b34801561072e57600080fd5b506002546103d0565b34801561074357600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401356103d0565b34801561078357600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006103d0565b3480156107b657600080fd5b506108226107c5366004615679565b6007602052600090815260409020805460019091015460ff821691610100810463ffffffff1691650100000000009091046fffffffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff1684565b60408051941515855263ffffffff90931660208501526fffffffffffffffffffffffffffffffff9091169183019190915273ffffffffffffffffffffffffffffffffffffffff16606082015260800161037b565b34801561088257600080fd5b5060405163ffffffff7f000000000000000000000000000000000000000000000000000000000000000016815260200161037b565b3480156108c357600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003601401356103d0565b34801561090357600080fd5b50610366610912366004615679565b612a81565b34801561092357600080fd5b506103d0610932366004615728565b612c60565b34801561094357600080fd5b50610957610952366004615679565b612e43565b6040805163ffffffff909816885273ffffffffffffffffffffffffffffffffffffffff968716602089015295909416948601949094526fffffffffffffffffffffffffffffffff9182166060860152608085015291821660a08401521660c082015260e00161037b565b3480156109cd57600080fd5b506000546103669067ffffffffffffffff1681565b3480156109ee57600080fd5b506103d06109fd3660046156b7565b60036020526000908152604090205481565b348015610a1b57600080fd5b507f00000000000000000000000000000000000000000000000000000000000003856103d0565b348015610a4e57600080fd5b50610317610a5d36600461575a565b612eda565b348015610a6e57600080fd5b507f00000000000000000000000000000000000000000000000000000000000004b0610366565b348015610aa157600080fd5b507f00000000000000000000000000000000000000000000000000000000000000046103d0565b348015610ad457600080fd5b50610508610ae3366004615679565b60046020526000908152604090205460ff1681565b348015610b0457600080fd5b50610317610b133660046155cf565b613509565b348015610b2457600080fd5b50610b2d6139c6565b60405161037b939291906157e4565b348015610b4857600080fd5b507f00000000000000000000000000000000000000000000000000000000000000086103d0565b348015610b7b57600080fd5b50610508610b8a366004615679565b60066020526000908152604090205460ff1681565b60008054700100000000000000000000000000000000900460ff166002811115610bcb57610bcb61555f565b14610c02576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000547201000000000000000000000000000000000000900460ff1615610c55576040517f0ea2e75200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610c8c367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013590565b90565b610ca3610c9e36869003860186615838565b613a41565b14610cda576040517f9cc00b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82606001358282604051610cef9291906158c5565b604051809103902014610d2e576040517fd81d583b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610d77610d7284848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613a9d92505050565b613b0a565b90506000610d9e82600881518110610d9157610d916158d5565b6020026020010151613cc0565b9050602081511115610ddc576040517fd81d583b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602081810151825190910360031b1c367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401358103610e51576040517fb8ed883000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050600180547fffffffffffffffffffffffff000000000000000000000000000000000000000016331790555050600080547fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff1672010000000000000000000000000000000000001790555050565b60008054700100000000000000000000000000000000900460ff166002811115610eec57610eec61555f565b14610f23576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028381548110610f3857610f386158d5565b906000526020600020906005020190506000610f5384612a81565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b081169082161015610fbc576040517ff2440b5300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008481526006602052604090205460ff1615611005576040517ff1a9458100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600084815260056020526040902080548015801561102257508515155b156110bd578354640100000000900473ffffffffffffffffffffffffffffffffffffffff16600081156110555781611071565b600186015473ffffffffffffffffffffffffffffffffffffffff165b905061107d8187613d74565b50505060009485525050600660205250506040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b6000868152600760209081526040918290208251608081018452815460ff81161515808352610100820463ffffffff16948301949094526501000000000090046fffffffffffffffffffffffffffffffff16938101939093526001015473ffffffffffffffffffffffffffffffffffffffff166060830152611160576fffffffffffffffffffffffffffffffff6040820152600181526000869003611160578195505b600086826020015163ffffffff166111789190615933565b90506000838211611189578161118b565b835b602084015190915063ffffffff165b818110156112d75760008682815481106111b6576111b66158d5565b6000918252602080832090910154808352600690915260409091205490915060ff1661120e576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028281548110611223576112236158d5565b600091825260209091206005909102018054909150640100000000900473ffffffffffffffffffffffffffffffffffffffff161580156112805750600481015460408701516fffffffffffffffffffffffffffffffff9182169116115b156112c257600181015473ffffffffffffffffffffffffffffffffffffffff16606087015260048101546fffffffffffffffffffffffffffffffff1660408701525b505080806112cf9061594b565b91505061119a565b5063ffffffff818116602085810191825260008c81526007909152604090819020865181549351928801517fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009094169015157fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ff161761010092909416918202939093177fffffffffffffffffffffff00000000000000000000000000000000ffffffffff16650100000000006fffffffffffffffffffffffffffffffff909316929092029190911782556060850151600190920180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9093169290921790915584900361155b57606083015160008a815260066020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558915801561145757506000547201000000000000000000000000000000000000900460ff165b156114cc5760015473ffffffffffffffffffffffffffffffffffffffff1661147f818a613d74565b885473ffffffffffffffffffffffffffffffffffffffff909116640100000000027fffffffffffffffff0000000000000000000000000000000000000000ffffffff909116178855611559565b61151373ffffffffffffffffffffffffffffffffffffffff8216156114f1578161150d565b600189015473ffffffffffffffffffffffffffffffffffffffff165b89613d74565b87547fffffffffffffffff0000000000000000000000000000000000000000ffffffff1664010000000073ffffffffffffffffffffffffffffffffffffffff8316021788555b505b505050505050505050565b600080600054700100000000000000000000000000000000900460ff1660028111156115945761159461555f565b146115cb576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000805260066020527f54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4f85460ff1661162f576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600260008154811061165b5761165b6158d5565b6000918252602090912060059091020154640100000000900473ffffffffffffffffffffffffffffffffffffffff1614611696576001611699565b60025b6000805467ffffffffffffffff421668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff82168117835592935083927fffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffff000000000000000000ffffffffffffffff9091161770010000000000000000000000000000000083600281111561174a5761174a61555f565b02179055600281111561175f5761175f61555f565b6040517f5e186f09b9c93491f14e277eea7faa5de6a2d4bda75a79af7a3684fbfb42da6090600090a27f000000000000000000000000970670459734a83899773a0fd45941b5afc1200e73ffffffffffffffffffffffffffffffffffffffff1663838c2d1e6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156117f057600080fd5b505af1158015611804573d6000803e3d6000fd5b5050505090565b6005602052816000526040600020818154811061182757600080fd5b90600052602060002001600091509150505481565b905090565b61184e8383836001611a42565b505050565b6000818152600760209081526040808320600590925282208054825461188490610100900463ffffffff1682615983565b95945050505050565b606061183c60546020613e75565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260036020526040812080549082905590819003611900576040517f17bfe5f700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517ff3fef3a300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152602482018390527f000000000000000000000000ef179756ea6525afade217ca5ab0b1b5cfe0fd92169063f3fef3a390604401600060405180830381600087803b15801561199057600080fd5b505af11580156119a4573d6000803e3d6000fd5b5050505060008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114611a02576040519150601f19603f3d011682016040523d82523d6000602084013e611a07565b606091505b505090508061184e576040517f83e6cc6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008054700100000000000000000000000000000000900460ff166002811115611a6e57611a6e61555f565b14611aa5576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028481548110611aba57611aba6158d5565b60009182526020918290206040805160e0810182526005909302909101805463ffffffff8116845273ffffffffffffffffffffffffffffffffffffffff64010000000090910481169484019490945260018101549093169082015260028201546fffffffffffffffffffffffffffffffff908116606083015260038301546080830181905260049093015480821660a084015270010000000000000000000000000000000090041660c082015291508514611ba1576040517f3014033200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60a0810151600083156fffffffffffffffffffffffffffffffff83161760011b90506000611c61826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169050861580611c9c5750611c997f00000000000000000000000000000000000000000000000000000000000000046002615933565b81145b8015611ca6575084155b15611cdd576040517fa42637bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000547201000000000000000000000000000000000000900460ff168015611d03575086155b15611d3a576040517f0ea2e75200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000008811115611d94576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611dbf7f00000000000000000000000000000000000000000000000000000000000000046001615933565b8103611dd157611dd186888588613ec7565b34611ddb83612c60565b14611e12576040517f8620aa1900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611e1d88612a81565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b0811690821603611e85576040517f3381d11400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611eb260017f0000000000000000000000000000000000000000000000000000000000000008615983565b8303611ff0577f000000000000000000000000180cbe2ebb9f37d3a3c542ddc2546fd160555a7373ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f47919061599a565b73ffffffffffffffffffffffffffffffffffffffff1663f3f480d96040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f91573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fb591906159b7565b611fe9907f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff166159d0565b9050612083565b61201b60017f0000000000000000000000000000000000000000000000000000000000000004615983565b830361205657611fe97f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1660026159fc565b507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff165b6120b7817f00000000000000000000000000000000000000000000000000000000000004b067ffffffffffffffff16615a2c565b67ffffffffffffffff166120d28367ffffffffffffffff1690565b67ffffffffffffffff16111561211957612116817f00000000000000000000000000000000000000000000000000000000000004b067ffffffffffffffff16615a2c565b91505b6000604083901b421760008a8152608087901b6fffffffffffffffffffffffffffffffff8d1617602052604081209192509060008181526004602052604090205490915060ff1615612197576040517f80497e3b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60016004600083815260200190815260200160002060006101000a81548160ff02191690831515021790555060026040518060e001604052808d63ffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020013373ffffffffffffffffffffffffffffffffffffffff168152602001346fffffffffffffffffffffffffffffffff1681526020018c8152602001886fffffffffffffffffffffffffffffffff168152602001846fffffffffffffffffffffffffffffffff16815250908060018154018082558091505060019003906000526020600020906005020160009091909190915060008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060608201518160020160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055506080820151816003015560a08201518160040160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555060c08201518160040160106101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055505050600560008c8152602001908152602001600020600160028054905061242d9190615983565b81546001810183556000928352602083200155604080517fd0e30db0000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ef179756ea6525afade217ca5ab0b1b5cfe0fd92169263d0e30db09234926004808301939282900301818588803b1580156124c557600080fd5b505af11580156124d9573d6000803e3d6000fd5b50506040513393508d92508e91507f9b3245740ec3b155098a55be84957a4da13eaf7f14a8bc6f53126c0b9350f2be90600090a4505050505050505050505050565b61184e8383836000611a42565b60005471010000000000000000000000000000000000900460ff161561257a576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f7258a80700000000000000000000000000000000000000000000000000000000815263ffffffff7f0000000000000000000000000000000000000000000000000000000000000000166004820152600090819073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000970670459734a83899773a0fd45941b5afc1200e1690637258a807906024016040805180830381865afa15801561262e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126529190615a55565b90925090508161268e576040517f6a6bc3b200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080518082019091528281526020018190526008829055600981905536607a146126c157639824bdab6000526004601cfd5b80367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401351161275b576040517ff40239db000000000000000000000000000000000000000000000000000000008152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013560048201526024015b60405180910390fd5b6040805160e08101825263ffffffff8082526000602083018181527ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe369081013560f01c90038035606090811c868801908152346fffffffffffffffffffffffffffffffff81811693890193845260149094013560808901908152600160a08a0181815242871660c08c019081526002805493840181558a529a5160059092027f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace81018054995173ffffffffffffffffffffffffffffffffffffffff908116640100000000027fffffffffffffffff000000000000000000000000000000000000000000000000909b1694909c16939093179890981790915592517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5acf87018054918a167fffffffffffffffffffffffff000000000000000000000000000000000000000090921691909117905592517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad0860180549186167fffffffffffffffffffffffffffffffff0000000000000000000000000000000090921691909117905591517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad185015551955182167001000000000000000000000000000000000295909116949094177f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad29091015580547fffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffff167101000000000000000000000000000000000017815583517fd0e30db000000000000000000000000000000000000000000000000000000000815293517f000000000000000000000000ef179756ea6525afade217ca5ab0b1b5cfe0fd929092169363d0e30db093926004828101939282900301818588803b158015612a3057600080fd5b505af1158015612a44573d6000803e3d6000fd5b5050600080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000164267ffffffffffffffff161790555050505050565b600080600054700100000000000000000000000000000000900460ff166002811115612aaf57612aaf61555f565b14612ae6576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028381548110612afb57612afb6158d5565b600091825260208220600590910201805490925063ffffffff90811614612b6a57815460028054909163ffffffff16908110612b3957612b396158d5565b906000526020600020906005020160040160109054906101000a90046fffffffffffffffffffffffffffffffff1690505b6004820154600090612ba290700100000000000000000000000000000000900467ffffffffffffffff165b67ffffffffffffffff1690565b612bb69067ffffffffffffffff1642615983565b612bd5612b95846fffffffffffffffffffffffffffffffff1660401c90565b67ffffffffffffffff16612be99190615933565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b01667ffffffffffffffff168167ffffffffffffffff1611612c365780611884565b7f00000000000000000000000000000000000000000000000000000000000004b095945050505050565b600080612cff836fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1690507f0000000000000000000000000000000000000000000000000000000000000008811115612d5e576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b642e90edd00062061a806311e1a3006000612d798383615aa8565b9050670de0b6b3a76400006000612db0827f0000000000000000000000000000000000000000000000000000000000000008615abc565b90506000612dce612dc9670de0b6b3a764000086615abc565b614078565b90506000612ddc84846142d3565b90506000612dea8383614322565b90506000612df782614350565b90506000612e1682612e11670de0b6b3a76400008f615abc565b614538565b90506000612e248b83614322565b9050612e30818d615abc565b9f9e505050505050505050505050505050565b60028181548110612e5357600080fd5b60009182526020909120600590910201805460018201546002830154600384015460049094015463ffffffff8416955064010000000090930473ffffffffffffffffffffffffffffffffffffffff908116949216926fffffffffffffffffffffffffffffffff91821692918082169170010000000000000000000000000000000090041687565b60008054700100000000000000000000000000000000900460ff166002811115612f0657612f0661555f565b14612f3d576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028781548110612f5257612f526158d5565b6000918252602082206005919091020160048101549092506fffffffffffffffffffffffffffffffff16908715821760011b9050612fb17f00000000000000000000000000000000000000000000000000000000000000086001615933565b61304d826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1614613087576040517f5f53dd9800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080891561317e576130da7f00000000000000000000000000000000000000000000000000000000000000047f0000000000000000000000000000000000000000000000000000000000000008615983565b6001901b6130f9846fffffffffffffffffffffffffffffffff16614569565b6fffffffffffffffffffffffffffffffff166131159190615af9565b156131525761314961313a60016fffffffffffffffffffffffffffffffff8716615b0d565b865463ffffffff166000614608565b60030154613174565b7f00000000000000000000000000000000000000000000000000000000000000005b91508490506131a8565b600385015491506131a561313a6fffffffffffffffffffffffffffffffff86166001615b36565b90505b600882901b60088a8a6040516131bf9291906158c5565b6040518091039020901b14613200576040517f696550ff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061320b8c6146ec565b9050600061321a836003015490565b6040517fe14ced320000000000000000000000000000000000000000000000000000000081527f000000000000000000000000180cbe2ebb9f37d3a3c542ddc2546fd160555a7373ffffffffffffffffffffffffffffffffffffffff169063e14ced3290613294908f908f908f908f908a90600401615baa565b6020604051808303816000875af11580156132b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132d791906159b7565b600485015491149150600090600290613382906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b61341e896fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b6134289190615be4565b6134329190615c07565b60ff161590508115158103613473576040517ffb4e40dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8754640100000000900473ffffffffffffffffffffffffffffffffffffffff16156134ca576040517f9071e6af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505085547fffffffffffffffff0000000000000000000000000000000000000000ffffffff163364010000000002179095555050505050505050505050565b60008054700100000000000000000000000000000000900460ff1660028111156135355761353561555f565b1461356c576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060008061357b8661471b565b9350935093509350600061359185858585614b24565b905060007f000000000000000000000000180cbe2ebb9f37d3a3c542ddc2546fd160555a7373ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015613600573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613624919061599a565b90506001890361371c5773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a84613680367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036034013590565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815260048101939093526024830191909152604482015260206064820152608481018a905260a4015b6020604051808303816000875af11580156136f2573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061371691906159b7565b5061155b565b600289036137485773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a8489613680565b600389036137745773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a8487613680565b600489036138fb5760006137ba6fffffffffffffffffffffffffffffffff85167f0000000000000000000000000000000000000000000000000000000000000004614bde565b6009546137c79190615933565b6137d2906001615933565b9050367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900360540135811061383b57367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036054013561383d565b805b905073ffffffffffffffffffffffffffffffffffffffff82166352f0f3ad8b8560405160e084901b7fffffffff000000000000000000000000000000000000000000000000000000001681526004810192909252602482015260c084901b604482015260086064820152608481018b905260a4016020604051808303816000875af11580156138d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138f491906159b7565b505061155b565b60058903613994576040517f52f0f3ad000000000000000000000000000000000000000000000000000000008152600481018a9052602481018390527f000000000000000000000000000000000000000000000000000000000000038560c01b6044820152600860648201526084810188905273ffffffffffffffffffffffffffffffffffffffff8216906352f0f3ad9060a4016136d3565b6040517fff137e6500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000000367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003601401356060613a1f61188d565b9050909192565b600081831015613a365781613a38565b825b90505b92915050565b60008160000151826020015183604001518460600151604051602001613a80949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b60408051808201909152600080825260208201528151600003613aec576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50604080518082019091528151815260209182019181019190915290565b60606000806000613b1a85614c8c565b919450925090506001816001811115613b3557613b3561555f565b14613b6c576040517f4b9c6abe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8451613b788385615933565b14613baf576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516020808252610420820190925290816020015b6040805180820190915260008082526020820152815260200190600190039081613bc65790505093506000835b8651811015613cb457600080613c396040518060400160405280858c60000151613c1d9190615983565b8152602001858c60200151613c329190615933565b9052614c8c565b509150915060405180604001604052808383613c559190615933565b8152602001848b60200151613c6a9190615933565b815250888581518110613c7f57613c7f6158d5565b6020908102919091010152613c95600185615933565b9350613ca18183615933565b613cab9084615933565b92505050613bf3565b50845250919392505050565b60606000806000613cd085614c8c565b919450925090506000816001811115613ceb57613ceb61555f565b14613d22576040517f1ff9b2e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613d2c8284615933565b855114613d65576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6118848560200151848461512a565b600281015473ffffffffffffffffffffffffffffffffffffffff8316600090815260036020526040812080546fffffffffffffffffffffffffffffffff90931692839290613dc3908490615933565b90915550506040517f7eee288d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152602482018390527f000000000000000000000000ef179756ea6525afade217ca5ab0b1b5cfe0fd921690637eee288d90604401600060405180830381600087803b158015613e5857600080fd5b505af1158015613e6c573d6000803e3d6000fd5b50505050505050565b604051818152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90038284820160208401378260208301016000815260208101604052505092915050565b6000613ee66fffffffffffffffffffffffffffffffff84166001615b36565b90506000613ef682866001614608565b9050600086901a8380613fe25750613f2f60027f0000000000000000000000000000000000000000000000000000000000000004615af9565b6004830154600290613fd3906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b613fdd9190615c07565b60ff16145b1561403a5760ff811660011480613ffc575060ff81166002145b614035576040517ff40239db00000000000000000000000000000000000000000000000000000000815260048101889052602401612752565b613e6c565b60ff811615613e6c576040517ff40239db00000000000000000000000000000000000000000000000000000000815260048101889052602401612752565b6fffffffffffffffffffffffffffffffff811160071b81811c67ffffffffffffffff1060061b1781811c63ffffffff1060051b1781811c61ffff1060041b1781811c60ff1060031b17600082136140d757631615e6386000526004601cfd5b7ff8f9f9faf9fdfafbf9fdfcfdfafbfcfef9fafdfafcfcfbfefafafcfbffffffff6f8421084210842108cc6318c6db6d54be83831c1c601f161a1890811b609f90811c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506029190037d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b302017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d90565b60007812725dd1d243aba0e75fe645cc4873f9e65afe688c928e1f218311670de0b6b3a76400000215820261431057637c5f487d6000526004601cfd5b50670de0b6b3a7640000919091020490565b6000816000190483118202156143405763bac65e5b6000526004601cfd5b50670de0b6b3a764000091020490565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdc0d0570925a462d7821361437e57919050565b680755bf798b4a1bf1e5821261439c5763a37bfec96000526004601cfd5b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b6000613a38670de0b6b3a76400008361455086614078565b61455a9190615c29565b6145649190615ce5565b614350565b6000806145f6837e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b600160ff919091161b90920392915050565b600080826146515761464c6fffffffffffffffffffffffffffffffff86167f00000000000000000000000000000000000000000000000000000000000000046151bf565b61466c565b61466c856fffffffffffffffffffffffffffffffff1661534b565b905060028481548110614681576146816158d5565b906000526020600020906005020191505b60048201546fffffffffffffffffffffffffffffffff8281169116146146e457815460028054909163ffffffff169081106146cf576146cf6158d5565b90600052602060002090600502019150614692565b509392505050565b60008060008060006146fd8661471b565b935093509350935061471184848484614b24565b9695505050505050565b600080600080600085905060006002828154811061473b5761473b6158d5565b600091825260209091206004600590920201908101549091507f000000000000000000000000000000000000000000000000000000000000000490614812906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff161161484c576040517fb34b5c2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000815b60048301547f000000000000000000000000000000000000000000000000000000000000000490614913906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff16925082111561498857825463ffffffff166149527f00000000000000000000000000000000000000000000000000000000000000046001615933565b830361495c578391505b6002818154811061496f5761496f6158d5565b9060005260206000209060050201935080945050614850565b600481810154908401546fffffffffffffffffffffffffffffffff91821691166000816fffffffffffffffffffffffffffffffff166149f16149dc856fffffffffffffffffffffffffffffffff1660011c90565b6fffffffffffffffffffffffffffffffff1690565b6fffffffffffffffffffffffffffffffff161490508015614ac0576000614a29836fffffffffffffffffffffffffffffffff16614569565b6fffffffffffffffffffffffffffffffff161115614a94576000614a6b614a6360016fffffffffffffffffffffffffffffffff8616615b0d565b896001614608565b6003810154600490910154909c506fffffffffffffffffffffffffffffffff169a50614a9a9050565b6008549a505b600386015460048701549099506fffffffffffffffffffffffffffffffff169750614b16565b6000614ae2614a636fffffffffffffffffffffffffffffffff85166001615b36565b6003808901546004808b015492840154930154909e506fffffffffffffffffffffffffffffffff9182169d50919b50169850505b505050505050509193509193565b60006fffffffffffffffffffffffffffffffff841615614b915760408051602081018790526fffffffffffffffffffffffffffffffff8087169282019290925260608101859052908316608082015260a00160405160208183030381529060405280519060200120611884565b8282604051602001614bbf9291909182526fffffffffffffffffffffffffffffffff16602082015260400190565b6040516020818303038152906040528051906020012095945050505050565b600080614c6b847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1690508083036001841b600180831b0386831b17039250505092915050565b60008060008360000151600003614ccf576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020840151805160001a607f8111614cf4576000600160009450945094505050615123565b60b78111614e0a576000614d09608083615983565b905080876000015111614d48576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001838101517fff00000000000000000000000000000000000000000000000000000000000000169082148015614dc057507f80000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000008216105b15614df7576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5060019550935060009250615123915050565b60bf8111614f68576000614e1f60b783615983565b905080876000015111614e5e576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614ec0576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c60378111614f08576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614f128184615933565b895111614f4b576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614f56836001615933565b97509550600094506151239350505050565b60f78111614fcd576000614f7d60c083615983565b905080876000015111614fbc576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600195509350849250615123915050565b6000614fda60f783615983565b905080876000015111615019576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff0000000000000000000000000000000000000000000000000000000000000016600081900361507b576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c603781116150c3576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6150cd8184615933565b895111615106576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b615111836001615933565b97509550600194506151239350505050565b9193909250565b60608167ffffffffffffffff81111561514557615145615809565b6040519080825280601f01601f19166020018201604052801561516f576020820181803683370190505b50905081156151b85760006151848486615933565b90506020820160005b848110156151a557828101518282015260200161518d565b848111156151b4576000858301525b5050505b9392505050565b60008161525e846fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff16116152745763b34b5c226000526004601cfd5b61527d8361534b565b90508161531c826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1611613a3b57613a38615332836001615933565b6fffffffffffffffffffffffffffffffff8316906153f0565b600081196001830116816153df827e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169390931c8015179392505050565b60008061547d847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169050808303600180821b0385821b179250505092915050565b60008083601f8401126154ab57600080fd5b50813567ffffffffffffffff8111156154c357600080fd5b6020830191508360208285010111156154db57600080fd5b9250929050565b600080600083850360a08112156154f857600080fd5b608081121561550657600080fd5b50839250608084013567ffffffffffffffff81111561552457600080fd5b61553086828701615499565b9497909650939450505050565b6000806040838503121561555057600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60208101600383106155c9577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b6000806000606084860312156155e457600080fd5b505081359360208301359350604090920135919050565b6000815180845260005b8181101561562157602081850181015186830182015201615605565b81811115615633576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000613a3860208301846155fb565b60006020828403121561568b57600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff811681146156b457600080fd5b50565b6000602082840312156156c957600080fd5b81356151b881615692565b803580151581146156e457600080fd5b919050565b600080600080608085870312156156ff57600080fd5b84359350602085013592506040850135915061571d606086016156d4565b905092959194509250565b60006020828403121561573a57600080fd5b81356fffffffffffffffffffffffffffffffff811681146151b857600080fd5b6000806000806000806080878903121561577357600080fd5b86359550615783602088016156d4565b9450604087013567ffffffffffffffff808211156157a057600080fd5b6157ac8a838b01615499565b909650945060608901359150808211156157c557600080fd5b506157d289828a01615499565b979a9699509497509295939492505050565b63ffffffff8416815282602082015260606040820152600061188460608301846155fb565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006080828403121561584a57600080fd5b6040516080810181811067ffffffffffffffff82111715615894577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561594657615946615904565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361597c5761597c615904565b5060010190565b60008282101561599557615995615904565b500390565b6000602082840312156159ac57600080fd5b81516151b881615692565b6000602082840312156159c957600080fd5b5051919050565b600067ffffffffffffffff8083168185168083038211156159f3576159f3615904565b01949350505050565b600067ffffffffffffffff80831681851681830481118215151615615a2357615a23615904565b02949350505050565b600067ffffffffffffffff83811690831681811015615a4d57615a4d615904565b039392505050565b60008060408385031215615a6857600080fd5b505080516020909101519092909150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082615ab757615ab7615a79565b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615af457615af4615904565b500290565b600082615b0857615b08615a79565b500690565b60006fffffffffffffffffffffffffffffffff83811690831681811015615a4d57615a4d615904565b60006fffffffffffffffffffffffffffffffff8083168185168083038211156159f3576159f3615904565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b606081526000615bbe606083018789615b61565b8281036020840152615bd1818688615b61565b9150508260408301529695505050505050565b600060ff821660ff841680821015615bfe57615bfe615904565b90039392505050565b600060ff831680615c1a57615c1a615a79565b8060ff84160691505092915050565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600084136000841385830485118282161615615c6a57615c6a615904565b7f80000000000000000000000000000000000000000000000000000000000000006000871286820588128184161615615ca557615ca5615904565b60008712925087820587128484161615615cc157615cc1615904565b87850587128184161615615cd757615cd7615904565b505050929093029392505050565b600082615cf457615cf4615a79565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f800000000000000000000000000000000000000000000000000000000000000083141615615d4857615d48615904565b50059056fea164736f6c634300080f000a"; + bytes internal constant acc34Code = +- hex"6080604052600436106103085760003560e01c806370872aa51161019a578063c6f0308c116100e1578063ec5e63081161008a578063fa24f74311610064578063fa24f74314610b94578063fa315aa914610bb8578063fe2bbeb214610beb57600080fd5b8063ec5e630814610b11578063eff0f59214610b44578063f8f43ff614610b7457600080fd5b8063d6ae3cd5116100bb578063d6ae3cd514610a8b578063d8cc1a3c14610abe578063dabd396d14610ade57600080fd5b8063c6f0308c146109b3578063cf09e0d014610a3d578063d5d44d8014610a5e57600080fd5b8063a445ece611610143578063bcef3b551161011d578063bcef3b5514610933578063bd8da95614610973578063c395e1ca1461099357600080fd5b8063a445ece6146107f3578063a8e4fb90146108bf578063bbdc02db146108f257600080fd5b80638980e0cc116101745780638980e0cc1461076b5780638b85902b146107805780638d450a95146107c057600080fd5b806370872aa51461073b5780637b0f0adc146107505780638129fc1c1461076357600080fd5b80633fc8cef31161025e5780635c0cba33116102075780636361506d116101e15780636361506d146106b55780636b6716c0146106f55780636f0344091461072857600080fd5b80635c0cba331461064d578063609d33341461068057806360e274641461069557600080fd5b806354fd4d501161023857806354fd4d50146105a757806357da950e146105fd5780635a5fa2d91461062d57600080fd5b80633fc8cef31461052e578063472777c614610561578063534db0e21461057457600080fd5b80632810e1d6116102c057806337b1b2291161029a57806337b1b2291461047b5780633a768463146104bb5780633e3ac912146104ee57600080fd5b80632810e1d6146103f45780632ad69aeb1461040957806330dbe5701461042957600080fd5b806319effeb4116102f157806319effeb41461034f578063200d2ed21461039a57806325fc2ace146103d557600080fd5b8063019351301461030d57806303c2924d1461032f575b600080fd5b34801561031957600080fd5b5061032d61032836600461575d565b610c1b565b005b34801561033b57600080fd5b5061032d61034a3660046157b8565b610f3c565b34801561035b57600080fd5b5060005461037c9068010000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020015b60405180910390f35b3480156103a657600080fd5b506000546103c890700100000000000000000000000000000000900460ff1681565b6040516103919190615809565b3480156103e157600080fd5b506008545b604051908152602001610391565b34801561040057600080fd5b506103c86115e2565b34801561041557600080fd5b506103e66104243660046157b8565b611887565b34801561043557600080fd5b506001546104569073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610391565b34801561048757600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90033560601c610456565b3480156104c757600080fd5b507f000000000000000000000000444e09fe6d839273316a87002ab0efbea6fe7806610456565b3480156104fa57600080fd5b5060005461051e907201000000000000000000000000000000000000900460ff1681565b6040519015158152602001610391565b34801561053a57600080fd5b507f000000000000000000000000d6eaf4c146261653ee059077b78ed088add54309610456565b61032d61056f36600461584a565b6118bd565b34801561058057600080fd5b507f0000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b63610456565b3480156105b357600080fd5b506105f06040518060400160405280600a81526020017f312e332e302d72632e310000000000000000000000000000000000000000000081525081565b60405161039191906158e1565b34801561060957600080fd5b50600854600954610618919082565b60408051928352602083019190915201610391565b34801561063957600080fd5b506103e66106483660046158f4565b6118cf565b34801561065957600080fd5b507f000000000000000000000000970670459734a83899773a0fd45941b5afc1200e610456565b34801561068c57600080fd5b506105f0611909565b3480156106a157600080fd5b5061032d6106b0366004615932565b611917565b3480156106c157600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003603401356103e6565b34801561070157600080fd5b507f000000000000000000000000000000000000000000000000000000000000000061037c565b61032d610736366004615964565b611abe565b34801561074757600080fd5b506009546103e6565b61032d61075e36600461584a565b611b7f565b61032d611b8c565b34801561077757600080fd5b506002546103e6565b34801561078c57600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401356103e6565b3480156107cc57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006103e6565b3480156107ff57600080fd5b5061086b61080e3660046158f4565b6007602052600090815260409020805460019091015460ff821691610100810463ffffffff1691650100000000009091046fffffffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff1684565b60408051941515855263ffffffff90931660208501526fffffffffffffffffffffffffffffffff9091169183019190915273ffffffffffffffffffffffffffffffffffffffff166060820152608001610391565b3480156108cb57600080fd5b507f00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8610456565b3480156108fe57600080fd5b5060405163ffffffff7f0000000000000000000000000000000000000000000000000000000000000001168152602001610391565b34801561093f57600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003601401356103e6565b34801561097f57600080fd5b5061037c61098e3660046158f4565b611c05565b34801561099f57600080fd5b506103e66109ae3660046159a3565b611de4565b3480156109bf57600080fd5b506109d36109ce3660046158f4565b611fc7565b6040805163ffffffff909816885273ffffffffffffffffffffffffffffffffffffffff968716602089015295909416948601949094526fffffffffffffffffffffffffffffffff9182166060860152608085015291821660a08401521660c082015260e001610391565b348015610a4957600080fd5b5060005461037c9067ffffffffffffffff1681565b348015610a6a57600080fd5b506103e6610a79366004615932565b60036020526000908152604090205481565b348015610a9757600080fd5b507f00000000000000000000000000000000000000000000000000000000000003856103e6565b348015610aca57600080fd5b5061032d610ad93660046159d5565b61205e565b348015610aea57600080fd5b507f00000000000000000000000000000000000000000000000000000000000004b061037c565b348015610b1d57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000046103e6565b348015610b5057600080fd5b5061051e610b5f3660046158f4565b60046020526000908152604090205460ff1681565b348015610b8057600080fd5b5061032d610b8f36600461584a565b612123565b348015610ba057600080fd5b50610ba96125e0565b60405161039193929190615a5f565b348015610bc457600080fd5b507f00000000000000000000000000000000000000000000000000000000000000086103e6565b348015610bf757600080fd5b5061051e610c063660046158f4565b60066020526000908152604090205460ff1681565b60008054700100000000000000000000000000000000900460ff166002811115610c4757610c476157da565b14610c7e576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000547201000000000000000000000000000000000000900460ff1615610cd1576040517f0ea2e75200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d08367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013590565b90565b610d1f610d1a36869003860186615ab3565b61265b565b14610d56576040517f9cc00b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82606001358282604051610d6b929190615b40565b604051809103902014610daa576040517fd81d583b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610df3610dee84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506126b792505050565b612724565b90506000610e1a82600881518110610e0d57610e0d615b50565b60200260200101516128da565b9050602081511115610e58576040517fd81d583b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602081810151825190910360031b1c367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401358103610ecd576040517fb8ed883000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050600180547fffffffffffffffffffffffff000000000000000000000000000000000000000016331790555050600080547fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff1672010000000000000000000000000000000000001790555050565b60008054700100000000000000000000000000000000900460ff166002811115610f6857610f686157da565b14610f9f576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028381548110610fb457610fb4615b50565b906000526020600020906005020190506000610fcf84611c05565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b081169082161015611038576040517ff2440b5300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008481526006602052604090205460ff1615611081576040517ff1a9458100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600084815260056020526040902080548015801561109e57508515155b15611139578354640100000000900473ffffffffffffffffffffffffffffffffffffffff16600081156110d157816110ed565b600186015473ffffffffffffffffffffffffffffffffffffffff165b90506110f9818761298e565b50505060009485525050600660205250506040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b6000868152600760209081526040918290208251608081018452815460ff81161515808352610100820463ffffffff16948301949094526501000000000090046fffffffffffffffffffffffffffffffff16938101939093526001015473ffffffffffffffffffffffffffffffffffffffff1660608301526111dc576fffffffffffffffffffffffffffffffff60408201526001815260008690036111dc578195505b600086826020015163ffffffff166111f49190615bae565b905060008382116112055781611207565b835b602084015190915063ffffffff165b8181101561135357600086828154811061123257611232615b50565b6000918252602080832090910154808352600690915260409091205490915060ff1661128a576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006002828154811061129f5761129f615b50565b600091825260209091206005909102018054909150640100000000900473ffffffffffffffffffffffffffffffffffffffff161580156112fc5750600481015460408701516fffffffffffffffffffffffffffffffff9182169116115b1561133e57600181015473ffffffffffffffffffffffffffffffffffffffff16606087015260048101546fffffffffffffffffffffffffffffffff1660408701525b5050808061134b90615bc6565b915050611216565b5063ffffffff818116602085810191825260008c81526007909152604090819020865181549351928801517fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009094169015157fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ff161761010092909416918202939093177fffffffffffffffffffffff00000000000000000000000000000000ffffffffff16650100000000006fffffffffffffffffffffffffffffffff909316929092029190911782556060850151600190920180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909316929092179091558490036115d757606083015160008a815260066020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055891580156114d357506000547201000000000000000000000000000000000000900460ff165b156115485760015473ffffffffffffffffffffffffffffffffffffffff166114fb818a61298e565b885473ffffffffffffffffffffffffffffffffffffffff909116640100000000027fffffffffffffffff0000000000000000000000000000000000000000ffffffff9091161788556115d5565b61158f73ffffffffffffffffffffffffffffffffffffffff82161561156d5781611589565b600189015473ffffffffffffffffffffffffffffffffffffffff165b8961298e565b87547fffffffffffffffff0000000000000000000000000000000000000000ffffffff1664010000000073ffffffffffffffffffffffffffffffffffffffff8316021788555b505b505050505050505050565b600080600054700100000000000000000000000000000000900460ff166002811115611610576116106157da565b14611647576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000805260066020527f54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4f85460ff166116ab576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660026000815481106116d7576116d7615b50565b6000918252602090912060059091020154640100000000900473ffffffffffffffffffffffffffffffffffffffff1614611712576001611715565b60025b6000805467ffffffffffffffff421668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff82168117835592935083927fffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffff000000000000000000ffffffffffffffff909116177001000000000000000000000000000000008360028111156117c6576117c66157da565b0217905560028111156117db576117db6157da565b6040517f5e186f09b9c93491f14e277eea7faa5de6a2d4bda75a79af7a3684fbfb42da6090600090a27f000000000000000000000000970670459734a83899773a0fd45941b5afc1200e73ffffffffffffffffffffffffffffffffffffffff1663838c2d1e6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561186c57600080fd5b505af1158015611880573d6000803e3d6000fd5b5050505090565b600560205281600052604060002081815481106118a357600080fd5b90600052602060002001600091509150505481565b905090565b6118ca8383836001611abe565b505050565b6000818152600760209081526040808320600590925282208054825461190090610100900463ffffffff1682615bfe565b95945050505050565b60606118b860546020612a8f565b73ffffffffffffffffffffffffffffffffffffffff811660009081526003602052604081208054908290559081900361197c576040517f17bfe5f700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517ff3fef3a300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152602482018390527f000000000000000000000000d6eaf4c146261653ee059077b78ed088add54309169063f3fef3a390604401600060405180830381600087803b158015611a0c57600080fd5b505af1158015611a20573d6000803e3d6000fd5b5050505060008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114611a7e576040519150601f19603f3d011682016040523d82523d6000602084013e611a83565b606091505b50509050806118ca576040517f83e6cc6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8161480611b3757503373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b6316145b611b6d576040517fd386ef3e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611b7984848484612ae1565b50505050565b6118ca8383836000611abe565b3273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c81614611bfb576040517fd386ef3e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611c036135ba565b565b600080600054700100000000000000000000000000000000900460ff166002811115611c3357611c336157da565b14611c6a576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028381548110611c7f57611c7f615b50565b600091825260208220600590910201805490925063ffffffff90811614611cee57815460028054909163ffffffff16908110611cbd57611cbd615b50565b906000526020600020906005020160040160109054906101000a90046fffffffffffffffffffffffffffffffff1690505b6004820154600090611d2690700100000000000000000000000000000000900467ffffffffffffffff165b67ffffffffffffffff1690565b611d3a9067ffffffffffffffff1642615bfe565b611d59611d19846fffffffffffffffffffffffffffffffff1660401c90565b67ffffffffffffffff16611d6d9190615bae565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b01667ffffffffffffffff168167ffffffffffffffff1611611dba5780611900565b7f00000000000000000000000000000000000000000000000000000000000004b095945050505050565b600080611e83836fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1690507f0000000000000000000000000000000000000000000000000000000000000008811115611ee2576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b642e90edd00062061a806311e1a3006000611efd8383615c44565b9050670de0b6b3a76400006000611f34827f0000000000000000000000000000000000000000000000000000000000000008615c58565b90506000611f52611f4d670de0b6b3a764000086615c58565b613b13565b90506000611f608484613d6e565b90506000611f6e8383613dbd565b90506000611f7b82613deb565b90506000611f9a82611f95670de0b6b3a76400008f615c58565b613fd3565b90506000611fa88b83613dbd565b9050611fb4818d615c58565b9f9e505050505050505050505050505050565b60028181548110611fd757600080fd5b60009182526020909120600590910201805460018201546002830154600384015460049094015463ffffffff8416955064010000000090930473ffffffffffffffffffffffffffffffffffffffff908116949216926fffffffffffffffffffffffffffffffff91821692918082169170010000000000000000000000000000000090041687565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c81614806120d757503373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b6316145b61210d576040517fd386ef3e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61211b868686868686614004565b505050505050565b60008054700100000000000000000000000000000000900460ff16600281111561214f5761214f6157da565b14612186576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060008061219586614633565b935093509350935060006121ab85858585614a3c565b905060007f000000000000000000000000444e09fe6d839273316a87002ab0efbea6fe780673ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561221a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061223e9190615c95565b9050600189036123365773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a8461229a367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036034013590565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815260048101939093526024830191909152604482015260206064820152608481018a905260a4015b6020604051808303816000875af115801561230c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123309190615cb2565b506115d7565b600289036123625773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a848961229a565b6003890361238e5773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a848761229a565b600489036125155760006123d46fffffffffffffffffffffffffffffffff85167f0000000000000000000000000000000000000000000000000000000000000004614af6565b6009546123e19190615bae565b6123ec906001615bae565b9050367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900360540135811061245557367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900360540135612457565b805b905073ffffffffffffffffffffffffffffffffffffffff82166352f0f3ad8b8560405160e084901b7fffffffff000000000000000000000000000000000000000000000000000000001681526004810192909252602482015260c084901b604482015260086064820152608481018b905260a4016020604051808303816000875af11580156124ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061250e9190615cb2565b50506115d7565b600589036125ae576040517f52f0f3ad000000000000000000000000000000000000000000000000000000008152600481018a9052602481018390527f000000000000000000000000000000000000000000000000000000000000038560c01b6044820152600860648201526084810188905273ffffffffffffffffffffffffffffffffffffffff8216906352f0f3ad9060a4016122ed565b6040517fff137e6500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000001367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003601401356060612639611909565b9050909192565b6000818310156126505781612652565b825b90505b92915050565b6000816000015182602001518360400151846060015160405160200161269a949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b60408051808201909152600080825260208201528151600003612706576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50604080518082019091528151815260209182019181019190915290565b6060600080600061273485614ba4565b91945092509050600181600181111561274f5761274f6157da565b14612786576040517f4b9c6abe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84516127928385615bae565b146127c9576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516020808252610420820190925290816020015b60408051808201909152600080825260208201528152602001906001900390816127e05790505093506000835b86518110156128ce576000806128536040518060400160405280858c600001516128379190615bfe565b8152602001858c6020015161284c9190615bae565b9052614ba4565b50915091506040518060400160405280838361286f9190615bae565b8152602001848b602001516128849190615bae565b81525088858151811061289957612899615b50565b60209081029190910101526128af600185615bae565b93506128bb8183615bae565b6128c59084615bae565b9250505061280d565b50845250919392505050565b606060008060006128ea85614ba4565b919450925090506000816001811115612905576129056157da565b1461293c576040517f1ff9b2e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6129468284615bae565b85511461297f576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61190085602001518484615042565b600281015473ffffffffffffffffffffffffffffffffffffffff8316600090815260036020526040812080546fffffffffffffffffffffffffffffffff909316928392906129dd908490615bae565b90915550506040517f7eee288d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152602482018390527f000000000000000000000000d6eaf4c146261653ee059077b78ed088add543091690637eee288d90604401600060405180830381600087803b158015612a7257600080fd5b505af1158015612a86573d6000803e3d6000fd5b50505050505050565b604051818152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90038284820160208401378260208301016000815260208101604052505092915050565b60008054700100000000000000000000000000000000900460ff166002811115612b0d57612b0d6157da565b14612b44576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028481548110612b5957612b59615b50565b60009182526020918290206040805160e0810182526005909302909101805463ffffffff8116845273ffffffffffffffffffffffffffffffffffffffff64010000000090910481169484019490945260018101549093169082015260028201546fffffffffffffffffffffffffffffffff908116606083015260038301546080830181905260049093015480821660a084015270010000000000000000000000000000000090041660c082015291508514612c40576040517f3014033200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60a0810151600083156fffffffffffffffffffffffffffffffff83161760011b90506000612d00826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169050861580612d3b5750612d387f00000000000000000000000000000000000000000000000000000000000000046002615bae565b81145b8015612d45575084155b15612d7c576040517fa42637bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000547201000000000000000000000000000000000000900460ff168015612da2575086155b15612dd9576040517f0ea2e75200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000008811115612e33576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612e5e7f00000000000000000000000000000000000000000000000000000000000000046001615bae565b8103612e7057612e70868885886150d7565b34612e7a83611de4565b14612eb1576040517f8620aa1900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000612ebc88611c05565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b0811690821603612f24576040517f3381d11400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000612f5160017f0000000000000000000000000000000000000000000000000000000000000008615bfe565b830361308f577f000000000000000000000000444e09fe6d839273316a87002ab0efbea6fe780673ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015612fc2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fe69190615c95565b73ffffffffffffffffffffffffffffffffffffffff1663f3f480d96040518163ffffffff1660e01b8152600401602060405180830381865afa158015613030573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130549190615cb2565b613088907f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff16615ccb565b9050613122565b6130ba60017f0000000000000000000000000000000000000000000000000000000000000004615bfe565b83036130f5576130887f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff166002615cf7565b507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff165b613156817f00000000000000000000000000000000000000000000000000000000000004b067ffffffffffffffff16615d27565b67ffffffffffffffff166131718367ffffffffffffffff1690565b67ffffffffffffffff1611156131b8576131b5817f00000000000000000000000000000000000000000000000000000000000004b067ffffffffffffffff16615d27565b91505b6000604083901b421760008a8152608087901b6fffffffffffffffffffffffffffffffff8d1617602052604081209192509060008181526004602052604090205490915060ff1615613236576040517f80497e3b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60016004600083815260200190815260200160002060006101000a81548160ff02191690831515021790555060026040518060e001604052808d63ffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020013373ffffffffffffffffffffffffffffffffffffffff168152602001346fffffffffffffffffffffffffffffffff1681526020018c8152602001886fffffffffffffffffffffffffffffffff168152602001846fffffffffffffffffffffffffffffffff16815250908060018154018082558091505060019003906000526020600020906005020160009091909190915060008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060608201518160020160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055506080820151816003015560a08201518160040160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555060c08201518160040160106101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055505050600560008c815260200190815260200160002060016002805490506134cc9190615bfe565b81546001810183556000928352602083200155604080517fd0e30db0000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000d6eaf4c146261653ee059077b78ed088add54309169263d0e30db09234926004808301939282900301818588803b15801561356457600080fd5b505af1158015613578573d6000803e3d6000fd5b50506040513393508d92508e91507f9b3245740ec3b155098a55be84957a4da13eaf7f14a8bc6f53126c0b9350f2be90600090a4505050505050505050505050565b60005471010000000000000000000000000000000000900460ff161561360c576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f7258a80700000000000000000000000000000000000000000000000000000000815263ffffffff7f0000000000000000000000000000000000000000000000000000000000000001166004820152600090819073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000970670459734a83899773a0fd45941b5afc1200e1690637258a807906024016040805180830381865afa1580156136c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136e49190615d50565b909250905081613720576040517f6a6bc3b200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080518082019091528281526020018190526008829055600981905536607a1461375357639824bdab6000526004601cfd5b80367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900360540135116137ed576040517ff40239db000000000000000000000000000000000000000000000000000000008152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013560048201526024015b60405180910390fd5b6040805160e08101825263ffffffff8082526000602083018181527ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe369081013560f01c90038035606090811c868801908152346fffffffffffffffffffffffffffffffff81811693890193845260149094013560808901908152600160a08a0181815242871660c08c019081526002805493840181558a529a5160059092027f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace81018054995173ffffffffffffffffffffffffffffffffffffffff908116640100000000027fffffffffffffffff000000000000000000000000000000000000000000000000909b1694909c16939093179890981790915592517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5acf87018054918a167fffffffffffffffffffffffff000000000000000000000000000000000000000090921691909117905592517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad0860180549186167fffffffffffffffffffffffffffffffff0000000000000000000000000000000090921691909117905591517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad185015551955182167001000000000000000000000000000000000295909116949094177f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad29091015580547fffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffff167101000000000000000000000000000000000017815583517fd0e30db000000000000000000000000000000000000000000000000000000000815293517f000000000000000000000000d6eaf4c146261653ee059077b78ed088add543099092169363d0e30db093926004828101939282900301818588803b158015613ac257600080fd5b505af1158015613ad6573d6000803e3d6000fd5b5050600080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000164267ffffffffffffffff161790555050505050565b6fffffffffffffffffffffffffffffffff811160071b81811c67ffffffffffffffff1060061b1781811c63ffffffff1060051b1781811c61ffff1060041b1781811c60ff1060031b1760008213613b7257631615e6386000526004601cfd5b7ff8f9f9faf9fdfafbf9fdfcfdfafbfcfef9fafdfafcfcfbfefafafcfbffffffff6f8421084210842108cc6318c6db6d54be83831c1c601f161a1890811b609f90811c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506029190037d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b302017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d90565b60007812725dd1d243aba0e75fe645cc4873f9e65afe688c928e1f218311670de0b6b3a764000002158202613dab57637c5f487d6000526004601cfd5b50670de0b6b3a7640000919091020490565b600081600019048311820215613ddb5763bac65e5b6000526004601cfd5b50670de0b6b3a764000091020490565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdc0d0570925a462d78213613e1957919050565b680755bf798b4a1bf1e58212613e375763a37bfec96000526004601cfd5b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b6000612652670de0b6b3a764000083613feb86613b13565b613ff59190615d74565b613fff9190615e30565b613deb565b60008054700100000000000000000000000000000000900460ff166002811115614030576140306157da565b14614067576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006002878154811061407c5761407c615b50565b6000918252602082206005919091020160048101549092506fffffffffffffffffffffffffffffffff16908715821760011b90506140db7f00000000000000000000000000000000000000000000000000000000000000086001615bae565b614177826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff16146141b1576040517f5f53dd9800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008089156142a8576142047f00000000000000000000000000000000000000000000000000000000000000047f0000000000000000000000000000000000000000000000000000000000000008615bfe565b6001901b614223846fffffffffffffffffffffffffffffffff16615288565b6fffffffffffffffffffffffffffffffff1661423f9190615e98565b1561427c5761427361426460016fffffffffffffffffffffffffffffffff8716615eac565b865463ffffffff166000615327565b6003015461429e565b7f00000000000000000000000000000000000000000000000000000000000000005b91508490506142d2565b600385015491506142cf6142646fffffffffffffffffffffffffffffffff86166001615ed5565b90505b600882901b60088a8a6040516142e9929190615b40565b6040518091039020901b1461432a576040517f696550ff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006143358c61540b565b90506000614344836003015490565b6040517fe14ced320000000000000000000000000000000000000000000000000000000081527f000000000000000000000000444e09fe6d839273316a87002ab0efbea6fe780673ffffffffffffffffffffffffffffffffffffffff169063e14ced32906143be908f908f908f908f908a90600401615f49565b6020604051808303816000875af11580156143dd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144019190615cb2565b6004850154911491506000906002906144ac906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b614548896fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b6145529190615f83565b61455c9190615fa6565b60ff16159050811515810361459d576040517ffb4e40dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8754640100000000900473ffffffffffffffffffffffffffffffffffffffff16156145f4576040517f9071e6af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505085547fffffffffffffffff0000000000000000000000000000000000000000ffffffff163364010000000002179095555050505050505050505050565b600080600080600085905060006002828154811061465357614653615b50565b600091825260209091206004600590920201908101549091507f00000000000000000000000000000000000000000000000000000000000000049061472a906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1611614764576040517fb34b5c2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000815b60048301547f00000000000000000000000000000000000000000000000000000000000000049061482b906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1692508211156148a057825463ffffffff1661486a7f00000000000000000000000000000000000000000000000000000000000000046001615bae565b8303614874578391505b6002818154811061488757614887615b50565b9060005260206000209060050201935080945050614768565b600481810154908401546fffffffffffffffffffffffffffffffff91821691166000816fffffffffffffffffffffffffffffffff166149096148f4856fffffffffffffffffffffffffffffffff1660011c90565b6fffffffffffffffffffffffffffffffff1690565b6fffffffffffffffffffffffffffffffff1614905080156149d8576000614941836fffffffffffffffffffffffffffffffff16615288565b6fffffffffffffffffffffffffffffffff1611156149ac57600061498361497b60016fffffffffffffffffffffffffffffffff8616615eac565b896001615327565b6003810154600490910154909c506fffffffffffffffffffffffffffffffff169a506149b29050565b6008549a505b600386015460048701549099506fffffffffffffffffffffffffffffffff169750614a2e565b60006149fa61497b6fffffffffffffffffffffffffffffffff85166001615ed5565b6003808901546004808b015492840154930154909e506fffffffffffffffffffffffffffffffff9182169d50919b50169850505b505050505050509193509193565b60006fffffffffffffffffffffffffffffffff841615614aa95760408051602081018790526fffffffffffffffffffffffffffffffff8087169282019290925260608101859052908316608082015260a00160405160208183030381529060405280519060200120611900565b8282604051602001614ad79291909182526fffffffffffffffffffffffffffffffff16602082015260400190565b6040516020818303038152906040528051906020012095945050505050565b600080614b83847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1690508083036001841b600180831b0386831b17039250505092915050565b60008060008360000151600003614be7576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020840151805160001a607f8111614c0c57600060016000945094509450505061503b565b60b78111614d22576000614c21608083615bfe565b905080876000015111614c60576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001838101517fff00000000000000000000000000000000000000000000000000000000000000169082148015614cd857507f80000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000008216105b15614d0f576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506001955093506000925061503b915050565b60bf8111614e80576000614d3760b783615bfe565b905080876000015111614d76576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614dd8576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c60378111614e20576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614e2a8184615bae565b895111614e63576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614e6e836001615bae565b975095506000945061503b9350505050565b60f78111614ee5576000614e9560c083615bfe565b905080876000015111614ed4576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60019550935084925061503b915050565b6000614ef260f783615bfe565b905080876000015111614f31576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614f93576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c60378111614fdb576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614fe58184615bae565b89511161501e576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b615029836001615bae565b975095506001945061503b9350505050565b9193909250565b60608167ffffffffffffffff81111561505d5761505d615a84565b6040519080825280601f01601f191660200182016040528015615087576020820181803683370190505b50905081156150d057600061509c8486615bae565b90506020820160005b848110156150bd5782810151828201526020016150a5565b848111156150cc576000858301525b5050505b9392505050565b60006150f66fffffffffffffffffffffffffffffffff84166001615ed5565b9050600061510682866001615327565b9050600086901a83806151f2575061513f60027f0000000000000000000000000000000000000000000000000000000000000004615e98565b60048301546002906151e3906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b6151ed9190615fa6565b60ff16145b1561524a5760ff81166001148061520c575060ff81166002145b615245576040517ff40239db000000000000000000000000000000000000000000000000000000008152600481018890526024016137e4565b612a86565b60ff811615612a86576040517ff40239db000000000000000000000000000000000000000000000000000000008152600481018890526024016137e4565b600080615315837e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b600160ff919091161b90920392915050565b600080826153705761536b6fffffffffffffffffffffffffffffffff86167f000000000000000000000000000000000000000000000000000000000000000461543a565b61538b565b61538b856fffffffffffffffffffffffffffffffff166155c6565b9050600284815481106153a0576153a0615b50565b906000526020600020906005020191505b60048201546fffffffffffffffffffffffffffffffff82811691161461540357815460028054909163ffffffff169081106153ee576153ee615b50565b906000526020600020906005020191506153b1565b509392505050565b600080600080600061541c86614633565b935093509350935061543084848484614a3c565b9695505050505050565b6000816154d9846fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff16116154ef5763b34b5c226000526004601cfd5b6154f8836155c6565b905081615597826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1611612655576126526155ad836001615bae565b6fffffffffffffffffffffffffffffffff83169061566b565b6000811960018301168161565a827e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169390931c8015179392505050565b6000806156f8847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169050808303600180821b0385821b179250505092915050565b60008083601f84011261572657600080fd5b50813567ffffffffffffffff81111561573e57600080fd5b60208301915083602082850101111561575657600080fd5b9250929050565b600080600083850360a081121561577357600080fd5b608081121561578157600080fd5b50839250608084013567ffffffffffffffff81111561579f57600080fd5b6157ab86828701615714565b9497909650939450505050565b600080604083850312156157cb57600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6020810160038310615844577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b60008060006060848603121561585f57600080fd5b505081359360208301359350604090920135919050565b6000815180845260005b8181101561589c57602081850181015186830182015201615880565b818111156158ae576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006126526020830184615876565b60006020828403121561590657600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff8116811461592f57600080fd5b50565b60006020828403121561594457600080fd5b81356150d08161590d565b8035801515811461595f57600080fd5b919050565b6000806000806080858703121561597a57600080fd5b8435935060208501359250604085013591506159986060860161594f565b905092959194509250565b6000602082840312156159b557600080fd5b81356fffffffffffffffffffffffffffffffff811681146150d057600080fd5b600080600080600080608087890312156159ee57600080fd5b863595506159fe6020880161594f565b9450604087013567ffffffffffffffff80821115615a1b57600080fd5b615a278a838b01615714565b90965094506060890135915080821115615a4057600080fd5b50615a4d89828a01615714565b979a9699509497509295939492505050565b63ffffffff841681528260208201526060604082015260006119006060830184615876565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600060808284031215615ac557600080fd5b6040516080810181811067ffffffffffffffff82111715615b0f577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115615bc157615bc1615b7f565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203615bf757615bf7615b7f565b5060010190565b600082821015615c1057615c10615b7f565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082615c5357615c53615c15565b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615c9057615c90615b7f565b500290565b600060208284031215615ca757600080fd5b81516150d08161590d565b600060208284031215615cc457600080fd5b5051919050565b600067ffffffffffffffff808316818516808303821115615cee57615cee615b7f565b01949350505050565b600067ffffffffffffffff80831681851681830481118215151615615d1e57615d1e615b7f565b02949350505050565b600067ffffffffffffffff83811690831681811015615d4857615d48615b7f565b039392505050565b60008060408385031215615d6357600080fd5b505080516020909101519092909150565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600084136000841385830485118282161615615db557615db5615b7f565b7f80000000000000000000000000000000000000000000000000000000000000006000871286820588128184161615615df057615df0615b7f565b60008712925087820587128484161615615e0c57615e0c615b7f565b87850587128184161615615e2257615e22615b7f565b505050929093029392505050565b600082615e3f57615e3f615c15565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f800000000000000000000000000000000000000000000000000000000000000083141615615e9357615e93615b7f565b500590565b600082615ea757615ea7615c15565b500690565b60006fffffffffffffffffffffffffffffffff83811690831681811015615d4857615d48615b7f565b60006fffffffffffffffffffffffffffffffff808316818516808303821115615cee57615cee615b7f565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b606081526000615f5d606083018789615f00565b8281036020840152615f70818688615f00565b9150508260408301529695505050505050565b600060ff821660ff841680821015615f9d57615f9d615b7f565b90039392505050565b600060ff831680615fb957615fb9615c15565b8060ff8416069150509291505056fea164736f6c634300080f000a"; ++ hex"6080604052600436106103085760003560e01c806370872aa51161019a578063c6f0308c116100e1578063ec5e63081161008a578063fa24f74311610064578063fa24f74314610b94578063fa315aa914610bb8578063fe2bbeb214610beb57600080fd5b8063ec5e630814610b11578063eff0f59214610b44578063f8f43ff614610b7457600080fd5b8063d6ae3cd5116100bb578063d6ae3cd514610a8b578063d8cc1a3c14610abe578063dabd396d14610ade57600080fd5b8063c6f0308c146109b3578063cf09e0d014610a3d578063d5d44d8014610a5e57600080fd5b8063a445ece611610143578063bcef3b551161011d578063bcef3b5514610933578063bd8da95614610973578063c395e1ca1461099357600080fd5b8063a445ece6146107f3578063a8e4fb90146108bf578063bbdc02db146108f257600080fd5b80638980e0cc116101745780638980e0cc1461076b5780638b85902b146107805780638d450a95146107c057600080fd5b806370872aa51461073b5780637b0f0adc146107505780638129fc1c1461076357600080fd5b80633fc8cef31161025e5780635c0cba33116102075780636361506d116101e15780636361506d146106b55780636b6716c0146106f55780636f0344091461072857600080fd5b80635c0cba331461064d578063609d33341461068057806360e274641461069557600080fd5b806354fd4d501161023857806354fd4d50146105a757806357da950e146105fd5780635a5fa2d91461062d57600080fd5b80633fc8cef31461052e578063472777c614610561578063534db0e21461057457600080fd5b80632810e1d6116102c057806337b1b2291161029a57806337b1b2291461047b5780633a768463146104bb5780633e3ac912146104ee57600080fd5b80632810e1d6146103f45780632ad69aeb1461040957806330dbe5701461042957600080fd5b806319effeb4116102f157806319effeb41461034f578063200d2ed21461039a57806325fc2ace146103d557600080fd5b8063019351301461030d57806303c2924d1461032f575b600080fd5b34801561031957600080fd5b5061032d61032836600461575d565b610c1b565b005b34801561033b57600080fd5b5061032d61034a3660046157b8565b610f3c565b34801561035b57600080fd5b5060005461037c9068010000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020015b60405180910390f35b3480156103a657600080fd5b506000546103c890700100000000000000000000000000000000900460ff1681565b6040516103919190615809565b3480156103e157600080fd5b506008545b604051908152602001610391565b34801561040057600080fd5b506103c86115e2565b34801561041557600080fd5b506103e66104243660046157b8565b611887565b34801561043557600080fd5b506001546104569073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610391565b34801561048757600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90033560601c610456565b3480156104c757600080fd5b507f000000000000000000000000180cbe2ebb9f37d3a3c542ddc2546fd160555a73610456565b3480156104fa57600080fd5b5060005461051e907201000000000000000000000000000000000000900460ff1681565b6040519015158152602001610391565b34801561053a57600080fd5b507f000000000000000000000000d6eaf4c146261653ee059077b78ed088add54309610456565b61032d61056f36600461584a565b6118bd565b34801561058057600080fd5b507f0000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b63610456565b3480156105b357600080fd5b506105f06040518060400160405280600c81526020017f312e332e312d626574612e32000000000000000000000000000000000000000081525081565b60405161039191906158e1565b34801561060957600080fd5b50600854600954610618919082565b60408051928352602083019190915201610391565b34801561063957600080fd5b506103e66106483660046158f4565b6118cf565b34801561065957600080fd5b507f000000000000000000000000970670459734a83899773a0fd45941b5afc1200e610456565b34801561068c57600080fd5b506105f0611909565b3480156106a157600080fd5b5061032d6106b0366004615932565b611917565b3480156106c157600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003603401356103e6565b34801561070157600080fd5b507f000000000000000000000000000000000000000000000000000000000000000061037c565b61032d610736366004615964565b611abe565b34801561074757600080fd5b506009546103e6565b61032d61075e36600461584a565b611b7f565b61032d611b8c565b34801561077757600080fd5b506002546103e6565b34801561078c57600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401356103e6565b3480156107cc57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006103e6565b3480156107ff57600080fd5b5061086b61080e3660046158f4565b6007602052600090815260409020805460019091015460ff821691610100810463ffffffff1691650100000000009091046fffffffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff1684565b60408051941515855263ffffffff90931660208501526fffffffffffffffffffffffffffffffff9091169183019190915273ffffffffffffffffffffffffffffffffffffffff166060820152608001610391565b3480156108cb57600080fd5b507f00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8610456565b3480156108fe57600080fd5b5060405163ffffffff7f0000000000000000000000000000000000000000000000000000000000000001168152602001610391565b34801561093f57600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003601401356103e6565b34801561097f57600080fd5b5061037c61098e3660046158f4565b611c05565b34801561099f57600080fd5b506103e66109ae3660046159a3565b611de4565b3480156109bf57600080fd5b506109d36109ce3660046158f4565b611fc7565b6040805163ffffffff909816885273ffffffffffffffffffffffffffffffffffffffff968716602089015295909416948601949094526fffffffffffffffffffffffffffffffff9182166060860152608085015291821660a08401521660c082015260e001610391565b348015610a4957600080fd5b5060005461037c9067ffffffffffffffff1681565b348015610a6a57600080fd5b506103e6610a79366004615932565b60036020526000908152604090205481565b348015610a9757600080fd5b507f00000000000000000000000000000000000000000000000000000000000003856103e6565b348015610aca57600080fd5b5061032d610ad93660046159d5565b61205e565b348015610aea57600080fd5b507f00000000000000000000000000000000000000000000000000000000000004b061037c565b348015610b1d57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000046103e6565b348015610b5057600080fd5b5061051e610b5f3660046158f4565b60046020526000908152604090205460ff1681565b348015610b8057600080fd5b5061032d610b8f36600461584a565b612123565b348015610ba057600080fd5b50610ba96125e0565b60405161039193929190615a5f565b348015610bc457600080fd5b507f00000000000000000000000000000000000000000000000000000000000000086103e6565b348015610bf757600080fd5b5061051e610c063660046158f4565b60066020526000908152604090205460ff1681565b60008054700100000000000000000000000000000000900460ff166002811115610c4757610c476157da565b14610c7e576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000547201000000000000000000000000000000000000900460ff1615610cd1576040517f0ea2e75200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d08367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013590565b90565b610d1f610d1a36869003860186615ab3565b61265b565b14610d56576040517f9cc00b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82606001358282604051610d6b929190615b40565b604051809103902014610daa576040517fd81d583b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610df3610dee84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506126b792505050565b612724565b90506000610e1a82600881518110610e0d57610e0d615b50565b60200260200101516128da565b9050602081511115610e58576040517fd81d583b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602081810151825190910360031b1c367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401358103610ecd576040517fb8ed883000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050600180547fffffffffffffffffffffffff000000000000000000000000000000000000000016331790555050600080547fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff1672010000000000000000000000000000000000001790555050565b60008054700100000000000000000000000000000000900460ff166002811115610f6857610f686157da565b14610f9f576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028381548110610fb457610fb4615b50565b906000526020600020906005020190506000610fcf84611c05565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b081169082161015611038576040517ff2440b5300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008481526006602052604090205460ff1615611081576040517ff1a9458100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600084815260056020526040902080548015801561109e57508515155b15611139578354640100000000900473ffffffffffffffffffffffffffffffffffffffff16600081156110d157816110ed565b600186015473ffffffffffffffffffffffffffffffffffffffff165b90506110f9818761298e565b50505060009485525050600660205250506040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b6000868152600760209081526040918290208251608081018452815460ff81161515808352610100820463ffffffff16948301949094526501000000000090046fffffffffffffffffffffffffffffffff16938101939093526001015473ffffffffffffffffffffffffffffffffffffffff1660608301526111dc576fffffffffffffffffffffffffffffffff60408201526001815260008690036111dc578195505b600086826020015163ffffffff166111f49190615bae565b905060008382116112055781611207565b835b602084015190915063ffffffff165b8181101561135357600086828154811061123257611232615b50565b6000918252602080832090910154808352600690915260409091205490915060ff1661128a576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006002828154811061129f5761129f615b50565b600091825260209091206005909102018054909150640100000000900473ffffffffffffffffffffffffffffffffffffffff161580156112fc5750600481015460408701516fffffffffffffffffffffffffffffffff9182169116115b1561133e57600181015473ffffffffffffffffffffffffffffffffffffffff16606087015260048101546fffffffffffffffffffffffffffffffff1660408701525b5050808061134b90615bc6565b915050611216565b5063ffffffff818116602085810191825260008c81526007909152604090819020865181549351928801517fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009094169015157fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ff161761010092909416918202939093177fffffffffffffffffffffff00000000000000000000000000000000ffffffffff16650100000000006fffffffffffffffffffffffffffffffff909316929092029190911782556060850151600190920180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909316929092179091558490036115d757606083015160008a815260066020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055891580156114d357506000547201000000000000000000000000000000000000900460ff165b156115485760015473ffffffffffffffffffffffffffffffffffffffff166114fb818a61298e565b885473ffffffffffffffffffffffffffffffffffffffff909116640100000000027fffffffffffffffff0000000000000000000000000000000000000000ffffffff9091161788556115d5565b61158f73ffffffffffffffffffffffffffffffffffffffff82161561156d5781611589565b600189015473ffffffffffffffffffffffffffffffffffffffff165b8961298e565b87547fffffffffffffffff0000000000000000000000000000000000000000ffffffff1664010000000073ffffffffffffffffffffffffffffffffffffffff8316021788555b505b505050505050505050565b600080600054700100000000000000000000000000000000900460ff166002811115611610576116106157da565b14611647576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000805260066020527f54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4f85460ff166116ab576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660026000815481106116d7576116d7615b50565b6000918252602090912060059091020154640100000000900473ffffffffffffffffffffffffffffffffffffffff1614611712576001611715565b60025b6000805467ffffffffffffffff421668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff82168117835592935083927fffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffff000000000000000000ffffffffffffffff909116177001000000000000000000000000000000008360028111156117c6576117c66157da565b0217905560028111156117db576117db6157da565b6040517f5e186f09b9c93491f14e277eea7faa5de6a2d4bda75a79af7a3684fbfb42da6090600090a27f000000000000000000000000970670459734a83899773a0fd45941b5afc1200e73ffffffffffffffffffffffffffffffffffffffff1663838c2d1e6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561186c57600080fd5b505af1158015611880573d6000803e3d6000fd5b5050505090565b600560205281600052604060002081815481106118a357600080fd5b90600052602060002001600091509150505481565b905090565b6118ca8383836001611abe565b505050565b6000818152600760209081526040808320600590925282208054825461190090610100900463ffffffff1682615bfe565b95945050505050565b60606118b860546020612a8f565b73ffffffffffffffffffffffffffffffffffffffff811660009081526003602052604081208054908290559081900361197c576040517f17bfe5f700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517ff3fef3a300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152602482018390527f000000000000000000000000d6eaf4c146261653ee059077b78ed088add54309169063f3fef3a390604401600060405180830381600087803b158015611a0c57600080fd5b505af1158015611a20573d6000803e3d6000fd5b5050505060008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114611a7e576040519150601f19603f3d011682016040523d82523d6000602084013e611a83565b606091505b50509050806118ca576040517f83e6cc6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8161480611b3757503373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b6316145b611b6d576040517fd386ef3e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611b7984848484612ae1565b50505050565b6118ca8383836000611abe565b3273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c81614611bfb576040517fd386ef3e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611c036135ba565b565b600080600054700100000000000000000000000000000000900460ff166002811115611c3357611c336157da565b14611c6a576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028381548110611c7f57611c7f615b50565b600091825260208220600590910201805490925063ffffffff90811614611cee57815460028054909163ffffffff16908110611cbd57611cbd615b50565b906000526020600020906005020160040160109054906101000a90046fffffffffffffffffffffffffffffffff1690505b6004820154600090611d2690700100000000000000000000000000000000900467ffffffffffffffff165b67ffffffffffffffff1690565b611d3a9067ffffffffffffffff1642615bfe565b611d59611d19846fffffffffffffffffffffffffffffffff1660401c90565b67ffffffffffffffff16611d6d9190615bae565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b01667ffffffffffffffff168167ffffffffffffffff1611611dba5780611900565b7f00000000000000000000000000000000000000000000000000000000000004b095945050505050565b600080611e83836fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1690507f0000000000000000000000000000000000000000000000000000000000000008811115611ee2576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b642e90edd00062061a806311e1a3006000611efd8383615c44565b9050670de0b6b3a76400006000611f34827f0000000000000000000000000000000000000000000000000000000000000008615c58565b90506000611f52611f4d670de0b6b3a764000086615c58565b613b13565b90506000611f608484613d6e565b90506000611f6e8383613dbd565b90506000611f7b82613deb565b90506000611f9a82611f95670de0b6b3a76400008f615c58565b613fd3565b90506000611fa88b83613dbd565b9050611fb4818d615c58565b9f9e505050505050505050505050505050565b60028181548110611fd757600080fd5b60009182526020909120600590910201805460018201546002830154600384015460049094015463ffffffff8416955064010000000090930473ffffffffffffffffffffffffffffffffffffffff908116949216926fffffffffffffffffffffffffffffffff91821692918082169170010000000000000000000000000000000090041687565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c81614806120d757503373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b6316145b61210d576040517fd386ef3e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61211b868686868686614004565b505050505050565b60008054700100000000000000000000000000000000900460ff16600281111561214f5761214f6157da565b14612186576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060008061219586614633565b935093509350935060006121ab85858585614a3c565b905060007f000000000000000000000000180cbe2ebb9f37d3a3c542ddc2546fd160555a7373ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561221a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061223e9190615c95565b9050600189036123365773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a8461229a367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036034013590565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815260048101939093526024830191909152604482015260206064820152608481018a905260a4015b6020604051808303816000875af115801561230c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123309190615cb2565b506115d7565b600289036123625773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a848961229a565b6003890361238e5773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a848761229a565b600489036125155760006123d46fffffffffffffffffffffffffffffffff85167f0000000000000000000000000000000000000000000000000000000000000004614af6565b6009546123e19190615bae565b6123ec906001615bae565b9050367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900360540135811061245557367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900360540135612457565b805b905073ffffffffffffffffffffffffffffffffffffffff82166352f0f3ad8b8560405160e084901b7fffffffff000000000000000000000000000000000000000000000000000000001681526004810192909252602482015260c084901b604482015260086064820152608481018b905260a4016020604051808303816000875af11580156124ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061250e9190615cb2565b50506115d7565b600589036125ae576040517f52f0f3ad000000000000000000000000000000000000000000000000000000008152600481018a9052602481018390527f000000000000000000000000000000000000000000000000000000000000038560c01b6044820152600860648201526084810188905273ffffffffffffffffffffffffffffffffffffffff8216906352f0f3ad9060a4016122ed565b6040517fff137e6500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000001367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003601401356060612639611909565b9050909192565b6000818310156126505781612652565b825b90505b92915050565b6000816000015182602001518360400151846060015160405160200161269a949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b60408051808201909152600080825260208201528151600003612706576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50604080518082019091528151815260209182019181019190915290565b6060600080600061273485614ba4565b91945092509050600181600181111561274f5761274f6157da565b14612786576040517f4b9c6abe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84516127928385615bae565b146127c9576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516020808252610420820190925290816020015b60408051808201909152600080825260208201528152602001906001900390816127e05790505093506000835b86518110156128ce576000806128536040518060400160405280858c600001516128379190615bfe565b8152602001858c6020015161284c9190615bae565b9052614ba4565b50915091506040518060400160405280838361286f9190615bae565b8152602001848b602001516128849190615bae565b81525088858151811061289957612899615b50565b60209081029190910101526128af600185615bae565b93506128bb8183615bae565b6128c59084615bae565b9250505061280d565b50845250919392505050565b606060008060006128ea85614ba4565b919450925090506000816001811115612905576129056157da565b1461293c576040517f1ff9b2e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6129468284615bae565b85511461297f576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61190085602001518484615042565b600281015473ffffffffffffffffffffffffffffffffffffffff8316600090815260036020526040812080546fffffffffffffffffffffffffffffffff909316928392906129dd908490615bae565b90915550506040517f7eee288d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152602482018390527f000000000000000000000000d6eaf4c146261653ee059077b78ed088add543091690637eee288d90604401600060405180830381600087803b158015612a7257600080fd5b505af1158015612a86573d6000803e3d6000fd5b50505050505050565b604051818152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90038284820160208401378260208301016000815260208101604052505092915050565b60008054700100000000000000000000000000000000900460ff166002811115612b0d57612b0d6157da565b14612b44576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028481548110612b5957612b59615b50565b60009182526020918290206040805160e0810182526005909302909101805463ffffffff8116845273ffffffffffffffffffffffffffffffffffffffff64010000000090910481169484019490945260018101549093169082015260028201546fffffffffffffffffffffffffffffffff908116606083015260038301546080830181905260049093015480821660a084015270010000000000000000000000000000000090041660c082015291508514612c40576040517f3014033200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60a0810151600083156fffffffffffffffffffffffffffffffff83161760011b90506000612d00826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169050861580612d3b5750612d387f00000000000000000000000000000000000000000000000000000000000000046002615bae565b81145b8015612d45575084155b15612d7c576040517fa42637bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000547201000000000000000000000000000000000000900460ff168015612da2575086155b15612dd9576040517f0ea2e75200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000008811115612e33576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612e5e7f00000000000000000000000000000000000000000000000000000000000000046001615bae565b8103612e7057612e70868885886150d7565b34612e7a83611de4565b14612eb1576040517f8620aa1900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000612ebc88611c05565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b0811690821603612f24576040517f3381d11400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000612f5160017f0000000000000000000000000000000000000000000000000000000000000008615bfe565b830361308f577f000000000000000000000000180cbe2ebb9f37d3a3c542ddc2546fd160555a7373ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015612fc2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fe69190615c95565b73ffffffffffffffffffffffffffffffffffffffff1663f3f480d96040518163ffffffff1660e01b8152600401602060405180830381865afa158015613030573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130549190615cb2565b613088907f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff16615ccb565b9050613122565b6130ba60017f0000000000000000000000000000000000000000000000000000000000000004615bfe565b83036130f5576130887f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff166002615cf7565b507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff165b613156817f00000000000000000000000000000000000000000000000000000000000004b067ffffffffffffffff16615d27565b67ffffffffffffffff166131718367ffffffffffffffff1690565b67ffffffffffffffff1611156131b8576131b5817f00000000000000000000000000000000000000000000000000000000000004b067ffffffffffffffff16615d27565b91505b6000604083901b421760008a8152608087901b6fffffffffffffffffffffffffffffffff8d1617602052604081209192509060008181526004602052604090205490915060ff1615613236576040517f80497e3b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60016004600083815260200190815260200160002060006101000a81548160ff02191690831515021790555060026040518060e001604052808d63ffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020013373ffffffffffffffffffffffffffffffffffffffff168152602001346fffffffffffffffffffffffffffffffff1681526020018c8152602001886fffffffffffffffffffffffffffffffff168152602001846fffffffffffffffffffffffffffffffff16815250908060018154018082558091505060019003906000526020600020906005020160009091909190915060008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060608201518160020160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055506080820151816003015560a08201518160040160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555060c08201518160040160106101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055505050600560008c815260200190815260200160002060016002805490506134cc9190615bfe565b81546001810183556000928352602083200155604080517fd0e30db0000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000d6eaf4c146261653ee059077b78ed088add54309169263d0e30db09234926004808301939282900301818588803b15801561356457600080fd5b505af1158015613578573d6000803e3d6000fd5b50506040513393508d92508e91507f9b3245740ec3b155098a55be84957a4da13eaf7f14a8bc6f53126c0b9350f2be90600090a4505050505050505050505050565b60005471010000000000000000000000000000000000900460ff161561360c576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f7258a80700000000000000000000000000000000000000000000000000000000815263ffffffff7f0000000000000000000000000000000000000000000000000000000000000001166004820152600090819073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000970670459734a83899773a0fd45941b5afc1200e1690637258a807906024016040805180830381865afa1580156136c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136e49190615d50565b909250905081613720576040517f6a6bc3b200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080518082019091528281526020018190526008829055600981905536607a1461375357639824bdab6000526004601cfd5b80367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900360540135116137ed576040517ff40239db000000000000000000000000000000000000000000000000000000008152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013560048201526024015b60405180910390fd5b6040805160e08101825263ffffffff8082526000602083018181527ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe369081013560f01c90038035606090811c868801908152346fffffffffffffffffffffffffffffffff81811693890193845260149094013560808901908152600160a08a0181815242871660c08c019081526002805493840181558a529a5160059092027f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace81018054995173ffffffffffffffffffffffffffffffffffffffff908116640100000000027fffffffffffffffff000000000000000000000000000000000000000000000000909b1694909c16939093179890981790915592517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5acf87018054918a167fffffffffffffffffffffffff000000000000000000000000000000000000000090921691909117905592517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad0860180549186167fffffffffffffffffffffffffffffffff0000000000000000000000000000000090921691909117905591517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad185015551955182167001000000000000000000000000000000000295909116949094177f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad29091015580547fffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffff167101000000000000000000000000000000000017815583517fd0e30db000000000000000000000000000000000000000000000000000000000815293517f000000000000000000000000d6eaf4c146261653ee059077b78ed088add543099092169363d0e30db093926004828101939282900301818588803b158015613ac257600080fd5b505af1158015613ad6573d6000803e3d6000fd5b5050600080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000164267ffffffffffffffff161790555050505050565b6fffffffffffffffffffffffffffffffff811160071b81811c67ffffffffffffffff1060061b1781811c63ffffffff1060051b1781811c61ffff1060041b1781811c60ff1060031b1760008213613b7257631615e6386000526004601cfd5b7ff8f9f9faf9fdfafbf9fdfcfdfafbfcfef9fafdfafcfcfbfefafafcfbffffffff6f8421084210842108cc6318c6db6d54be83831c1c601f161a1890811b609f90811c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506029190037d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b302017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d90565b60007812725dd1d243aba0e75fe645cc4873f9e65afe688c928e1f218311670de0b6b3a764000002158202613dab57637c5f487d6000526004601cfd5b50670de0b6b3a7640000919091020490565b600081600019048311820215613ddb5763bac65e5b6000526004601cfd5b50670de0b6b3a764000091020490565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdc0d0570925a462d78213613e1957919050565b680755bf798b4a1bf1e58212613e375763a37bfec96000526004601cfd5b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b6000612652670de0b6b3a764000083613feb86613b13565b613ff59190615d74565b613fff9190615e30565b613deb565b60008054700100000000000000000000000000000000900460ff166002811115614030576140306157da565b14614067576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006002878154811061407c5761407c615b50565b6000918252602082206005919091020160048101549092506fffffffffffffffffffffffffffffffff16908715821760011b90506140db7f00000000000000000000000000000000000000000000000000000000000000086001615bae565b614177826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff16146141b1576040517f5f53dd9800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008089156142a8576142047f00000000000000000000000000000000000000000000000000000000000000047f0000000000000000000000000000000000000000000000000000000000000008615bfe565b6001901b614223846fffffffffffffffffffffffffffffffff16615288565b6fffffffffffffffffffffffffffffffff1661423f9190615e98565b1561427c5761427361426460016fffffffffffffffffffffffffffffffff8716615eac565b865463ffffffff166000615327565b6003015461429e565b7f00000000000000000000000000000000000000000000000000000000000000005b91508490506142d2565b600385015491506142cf6142646fffffffffffffffffffffffffffffffff86166001615ed5565b90505b600882901b60088a8a6040516142e9929190615b40565b6040518091039020901b1461432a576040517f696550ff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006143358c61540b565b90506000614344836003015490565b6040517fe14ced320000000000000000000000000000000000000000000000000000000081527f000000000000000000000000180cbe2ebb9f37d3a3c542ddc2546fd160555a7373ffffffffffffffffffffffffffffffffffffffff169063e14ced32906143be908f908f908f908f908a90600401615f49565b6020604051808303816000875af11580156143dd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144019190615cb2565b6004850154911491506000906002906144ac906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b614548896fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b6145529190615f83565b61455c9190615fa6565b60ff16159050811515810361459d576040517ffb4e40dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8754640100000000900473ffffffffffffffffffffffffffffffffffffffff16156145f4576040517f9071e6af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505085547fffffffffffffffff0000000000000000000000000000000000000000ffffffff163364010000000002179095555050505050505050505050565b600080600080600085905060006002828154811061465357614653615b50565b600091825260209091206004600590920201908101549091507f00000000000000000000000000000000000000000000000000000000000000049061472a906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1611614764576040517fb34b5c2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000815b60048301547f00000000000000000000000000000000000000000000000000000000000000049061482b906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1692508211156148a057825463ffffffff1661486a7f00000000000000000000000000000000000000000000000000000000000000046001615bae565b8303614874578391505b6002818154811061488757614887615b50565b9060005260206000209060050201935080945050614768565b600481810154908401546fffffffffffffffffffffffffffffffff91821691166000816fffffffffffffffffffffffffffffffff166149096148f4856fffffffffffffffffffffffffffffffff1660011c90565b6fffffffffffffffffffffffffffffffff1690565b6fffffffffffffffffffffffffffffffff1614905080156149d8576000614941836fffffffffffffffffffffffffffffffff16615288565b6fffffffffffffffffffffffffffffffff1611156149ac57600061498361497b60016fffffffffffffffffffffffffffffffff8616615eac565b896001615327565b6003810154600490910154909c506fffffffffffffffffffffffffffffffff169a506149b29050565b6008549a505b600386015460048701549099506fffffffffffffffffffffffffffffffff169750614a2e565b60006149fa61497b6fffffffffffffffffffffffffffffffff85166001615ed5565b6003808901546004808b015492840154930154909e506fffffffffffffffffffffffffffffffff9182169d50919b50169850505b505050505050509193509193565b60006fffffffffffffffffffffffffffffffff841615614aa95760408051602081018790526fffffffffffffffffffffffffffffffff8087169282019290925260608101859052908316608082015260a00160405160208183030381529060405280519060200120611900565b8282604051602001614ad79291909182526fffffffffffffffffffffffffffffffff16602082015260400190565b6040516020818303038152906040528051906020012095945050505050565b600080614b83847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1690508083036001841b600180831b0386831b17039250505092915050565b60008060008360000151600003614be7576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020840151805160001a607f8111614c0c57600060016000945094509450505061503b565b60b78111614d22576000614c21608083615bfe565b905080876000015111614c60576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001838101517fff00000000000000000000000000000000000000000000000000000000000000169082148015614cd857507f80000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000008216105b15614d0f576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506001955093506000925061503b915050565b60bf8111614e80576000614d3760b783615bfe565b905080876000015111614d76576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614dd8576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c60378111614e20576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614e2a8184615bae565b895111614e63576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614e6e836001615bae565b975095506000945061503b9350505050565b60f78111614ee5576000614e9560c083615bfe565b905080876000015111614ed4576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60019550935084925061503b915050565b6000614ef260f783615bfe565b905080876000015111614f31576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614f93576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c60378111614fdb576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614fe58184615bae565b89511161501e576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b615029836001615bae565b975095506001945061503b9350505050565b9193909250565b60608167ffffffffffffffff81111561505d5761505d615a84565b6040519080825280601f01601f191660200182016040528015615087576020820181803683370190505b50905081156150d057600061509c8486615bae565b90506020820160005b848110156150bd5782810151828201526020016150a5565b848111156150cc576000858301525b5050505b9392505050565b60006150f66fffffffffffffffffffffffffffffffff84166001615ed5565b9050600061510682866001615327565b9050600086901a83806151f2575061513f60027f0000000000000000000000000000000000000000000000000000000000000004615e98565b60048301546002906151e3906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b6151ed9190615fa6565b60ff16145b1561524a5760ff81166001148061520c575060ff81166002145b615245576040517ff40239db000000000000000000000000000000000000000000000000000000008152600481018890526024016137e4565b612a86565b60ff811615612a86576040517ff40239db000000000000000000000000000000000000000000000000000000008152600481018890526024016137e4565b600080615315837e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b600160ff919091161b90920392915050565b600080826153705761536b6fffffffffffffffffffffffffffffffff86167f000000000000000000000000000000000000000000000000000000000000000461543a565b61538b565b61538b856fffffffffffffffffffffffffffffffff166155c6565b9050600284815481106153a0576153a0615b50565b906000526020600020906005020191505b60048201546fffffffffffffffffffffffffffffffff82811691161461540357815460028054909163ffffffff169081106153ee576153ee615b50565b906000526020600020906005020191506153b1565b509392505050565b600080600080600061541c86614633565b935093509350935061543084848484614a3c565b9695505050505050565b6000816154d9846fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff16116154ef5763b34b5c226000526004601cfd5b6154f8836155c6565b905081615597826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1611612655576126526155ad836001615bae565b6fffffffffffffffffffffffffffffffff83169061566b565b6000811960018301168161565a827e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169390931c8015179392505050565b6000806156f8847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169050808303600180821b0385821b179250505092915050565b60008083601f84011261572657600080fd5b50813567ffffffffffffffff81111561573e57600080fd5b60208301915083602082850101111561575657600080fd5b9250929050565b600080600083850360a081121561577357600080fd5b608081121561578157600080fd5b50839250608084013567ffffffffffffffff81111561579f57600080fd5b6157ab86828701615714565b9497909650939450505050565b600080604083850312156157cb57600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6020810160038310615844577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b60008060006060848603121561585f57600080fd5b505081359360208301359350604090920135919050565b6000815180845260005b8181101561589c57602081850181015186830182015201615880565b818111156158ae576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006126526020830184615876565b60006020828403121561590657600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff8116811461592f57600080fd5b50565b60006020828403121561594457600080fd5b81356150d08161590d565b8035801515811461595f57600080fd5b919050565b6000806000806080858703121561597a57600080fd5b8435935060208501359250604085013591506159986060860161594f565b905092959194509250565b6000602082840312156159b557600080fd5b81356fffffffffffffffffffffffffffffffff811681146150d057600080fd5b600080600080600080608087890312156159ee57600080fd5b863595506159fe6020880161594f565b9450604087013567ffffffffffffffff80821115615a1b57600080fd5b615a278a838b01615714565b90965094506060890135915080821115615a4057600080fd5b50615a4d89828a01615714565b979a9699509497509295939492505050565b63ffffffff841681528260208201526060604082015260006119006060830184615876565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600060808284031215615ac557600080fd5b6040516080810181811067ffffffffffffffff82111715615b0f577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115615bc157615bc1615b7f565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203615bf757615bf7615b7f565b5060010190565b600082821015615c1057615c10615b7f565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082615c5357615c53615c15565b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615c9057615c90615b7f565b500290565b600060208284031215615ca757600080fd5b81516150d08161590d565b600060208284031215615cc457600080fd5b5051919050565b600067ffffffffffffffff808316818516808303821115615cee57615cee615b7f565b01949350505050565b600067ffffffffffffffff80831681851681830481118215151615615d1e57615d1e615b7f565b02949350505050565b600067ffffffffffffffff83811690831681811015615d4857615d48615b7f565b039392505050565b60008060408385031215615d6357600080fd5b505080516020909101519092909150565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600084136000841385830485118282161615615db557615db5615b7f565b7f80000000000000000000000000000000000000000000000000000000000000006000871286820588128184161615615df057615df0615b7f565b60008712925087820587128484161615615e0c57615e0c615b7f565b87850587128184161615615e2257615e22615b7f565b505050929093029392505050565b600082615e3f57615e3f615c15565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f800000000000000000000000000000000000000000000000000000000000000083141615615e9357615e93615b7f565b500590565b600082615ea757615ea7615c15565b500690565b60006fffffffffffffffffffffffffffffffff83811690831681811015615d4857615d48615b7f565b60006fffffffffffffffffffffffffffffffff808316818516808303821115615cee57615cee615b7f565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b606081526000615f5d606083018789615f00565b8281036020840152615f70818688615f00565b9150508260408301529695505050505050565b600060ff821660ff841680821015615f9d57615f9d615b7f565b90039392505050565b600060ff831680615fb957615fb9615c15565b8060ff8416069150509291505056fea164736f6c634300080f000a"; + }
@@ -34880,37 +137550,185 @@
-
+3
-
-3
+
+28
+
-28
-
diff --git OP/packages/contracts-bedrock/test/kontrol/proofs/utils/DeploymentSummaryFaultProofs.sol CELO/packages/contracts-bedrock/test/kontrol/proofs/utils/DeploymentSummaryFaultProofs.sol -index 41a56ef77bad2af52afad8c196470df305dc417f..928324c37ce7d9127c3fb8b1cdde6bf101671c94 100644 +
diff --git OP/packages/contracts-bedrock/test/kontrol/proofs/utils/DeploymentSummaryFaultProofs.sol CELO/packages/contracts-bedrock/test/kontrol/proofs/utils/DeploymentSummaryFaultProofs.sol +index 41a56ef77bad2af52afad8c196470df305dc417f..3b54141df2d7bbe1403aebc70e1c8775e142a476 100644 --- OP/packages/contracts-bedrock/test/kontrol/proofs/utils/DeploymentSummaryFaultProofs.sol +++ CELO/packages/contracts-bedrock/test/kontrol/proofs/utils/DeploymentSummaryFaultProofs.sol -@@ -28,9 +28,9 @@ address internal constant l1StandardBridgeProxyAddress = 0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D; - address internal constant l2OutputOracleAddress = 0x19652082F846171168Daf378C4fD3ee85a0D4A60; +@@ -13,36 +13,36 @@ address private constant VM_ADDRESS = address(uint160(uint256(keccak256("hevm cheat code")))); + Vm private constant vm = Vm(VM_ADDRESS); +  + address internal constant addressManagerAddress = 0x50EEf481cae4250d252Ae577A09bF514f224C6C4; +- address internal constant anchorStateRegistryAddress = 0x63B71B96756C693f7065345fecD9b7843b3e7C57; ++ address internal constant anchorStateRegistryAddress = 0xdEC4D949Cf1A2e824eE4F8B12064e166b96171dD; + address internal constant anchorStateRegistryProxyAddress = 0x970670459734a83899773A0fd45941B5afC1200e; +- address internal constant delayedWETHAddress = 0x2A6347EDD3C7813CDE46DD7eA61FF1Cf2290BC05; ++ address internal constant delayedWETHAddress = 0xe49cED258137CC5E18fB9ABA2Aa14069263D8f49; + address internal constant delayedWETHProxyAddress = 0xEF179756ea6525AFade217cA5aB0b1b5CfE0fd92; +- address internal constant disputeGameFactoryAddress = 0x20B168142354Cee65a32f6D8cf3033E592299765; ++ address internal constant disputeGameFactoryAddress = 0x8efDa795511CBBdfFC9eeca1a5bF30f5B1E1ef9E; + address internal constant disputeGameFactoryProxyAddress = 0x5207CfA0166E8de0FCdFd78B4d17b68587bE306d; +- address internal constant l1CrossDomainMessengerAddress = 0x094e6508ba9d9bf1ce421fff3dE06aE56e67901b; ++ address internal constant l1CrossDomainMessengerAddress = 0x357B6CdA94109749a0dA475ac1BFd395a61eb908; + address internal constant l1CrossDomainMessengerProxyAddress = 0xDeF3bca8c80064589E6787477FFa7Dd616B5574F; +- address internal constant l1ERC721BridgeAddress = 0x5C4F5e749A61a9503c4AAE8a9393e89609a0e804; ++ address internal constant l1ERC721BridgeAddress = 0xA4BD7E58A30ED0477fe7372883d09bF86619Bb66; + address internal constant l1ERC721BridgeProxyAddress = 0xD31598c909d9C935a9e35bA70d9a3DD47d4D5865; +- address internal constant l1StandardBridgeAddress = 0xb7900B27Be8f0E0fF65d1C3A4671e1220437dd2b; ++ address internal constant l1StandardBridgeAddress = 0x6cb2c88ABCd6391F9496f44BE27d5D3b247E0159; + address internal constant l1StandardBridgeProxyAddress = 0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D; +- address internal constant l2OutputOracleAddress = 0x19652082F846171168Daf378C4fD3ee85a0D4A60; ++ address internal constant l2OutputOracleAddress = 0x60d37db59d0D14f7EA5c7425A2C03244E08B162D; address internal constant l2OutputOracleProxyAddress = 0x39Af23E00F1e662025aA01b0cEdA19542B78DF99; - address internal constant mipsAddress = 0x444e09fe6D839273316a87002aB0EFBeA6fe7806; +- address internal constant mipsAddress = 0x444e09fe6D839273316a87002aB0EFBeA6fe7806; - address internal constant optimismMintableERC20FactoryAddress = 0x7c06d3a0a2f45e39E1798afbd9C3330971332a4F; -+ address internal constant optimismMintableERC20FactoryAddress = 0x9DAaD714C8eD63f5FE60B85e3694b40899486d58; ++ address internal constant mipsAddress = 0x180CBe2EBb9F37D3a3C542DDc2546Fd160555a73; ++ address internal constant optimismMintableERC20FactoryAddress = 0x79c3114E5f89266e2C8842871Bce16D4e5076b1e; address internal constant optimismMintableERC20FactoryProxyAddress = 0xc7B87b2b892EA5C3CfF47168881FE168C00377FB; - address internal constant optimismPortalAddress = 0xbdD90485FCbcac869D5b5752179815a3103d8131; -+ address internal constant optimismPortalAddress = 0xA4c07622d72648913221A0512Bdb95D0387ebe3B; - address internal constant optimismPortal2Address = 0xae5DadFc48928543f706a9E6Ce25c682aaD2b63b; +- address internal constant optimismPortal2Address = 0xae5DadFc48928543f706a9E6Ce25c682aaD2b63b; ++ address internal constant optimismPortalAddress = 0xb5A42f01EF5068F82C11fa1c4F9bBD4c8D346961; ++ address internal constant optimismPortal2Address = 0x150581358018524994Fc29800b1783637943b103; address internal constant optimismPortalProxyAddress = 0x1c23A6d89F95ef3148BCDA8E242cAb145bf9c0E4; address internal constant permissionedDelayedWETHProxyAddress = 0xd6EAF4c146261653EE059077B78ED088Add54309; +- address internal constant preimageOracleAddress = 0x373d916D11cce55b548F7051002e76BCFBD7a85d; +- address internal constant protocolVersionsAddress = 0xfbfD64a6C0257F613feFCe050Aa30ecC3E3d7C3F; ++ address internal constant preimageOracleAddress = 0x7A9Eab4CE99d157AeE7A02E95b366E972a2D5b0b; ++ address internal constant protocolVersionsAddress = 0xa99F1ab91821747b76Ec0cDFA38368DF4Ba06E84; + address internal constant protocolVersionsProxyAddress = 0x4C52a6277b1B84121b3072C0c92b6Be0b7CC10F1; + address internal constant proxyAdminAddress = 0x62c20Aa1e0272312BC100b4e23B4DC1Ed96dD7D1; + address internal constant safeProxyFactoryAddress = 0xA8452Ec99ce0C64f20701dB7dD3abDb607c00496; + address internal constant safeSingletonAddress = 0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3; +- address internal constant superchainConfigAddress = 0x068E44eB31e111028c41598E4535be7468674D0A; ++ address internal constant superchainConfigAddress = 0xDAf629c26abd7a84B6330c369887053B75dB2AF2; + address internal constant superchainConfigProxyAddress = 0x4f559F30f5eB88D635FDe1548C4267DB8FaB0351; +- address internal constant systemConfigAddress = 0x67866A5052E5302aaD08e9f352331fd8622eB6DC; ++ address internal constant systemConfigAddress = 0xd9CEcA938f039e427Edf626FA1f377d23A6b60c9; + address internal constant systemConfigProxyAddress = 0x0c8b5822b6e02CDa722174F19A1439A7495a3fA6; + address internal constant systemOwnerSafeAddress = 0x7C0c8a15773ED7B50E7c738D1aF4c5e3a2b210BD; + address internal constant acc33Address = 0xb6b1579AA54e2F61e621a40d5F2704D717B3544F; +@@ -107,7 +107,7 @@ slot = hex"0000000000000000000000000000000000000000000000000000000000000005"; + value = hex"0000000000000000000000000000000000000000000000000000000000000001"; + vm.store(systemOwnerSafeAddress, slot, value); + slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; +- value = hex"000000000000000000000000068e44eb31e111028c41598e4535be7468674d0a"; ++ value = hex"000000000000000000000000daf629c26abd7a84b6330c369887053b75db2af2"; + vm.store(superchainConfigProxyAddress, slot, value); + slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; + value = hex"0000000000000000000000000000000000000000000000000000000000000001"; +@@ -145,7 +145,7 @@ slot = hex"0000000000000000000000000000000000000000000000000000000000000005"; + value = hex"0000000000000000000000000000000000000000000000000000000000000002"; + vm.store(systemOwnerSafeAddress, slot, value); + slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; +- value = hex"000000000000000000000000fbfd64a6c0257f613fefce050aa30ecc3e3d7c3f"; ++ value = hex"000000000000000000000000a99f1ab91821747b76ec0cdfa38368df4ba06e84"; + vm.store(protocolVersionsProxyAddress, slot, value); + slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; + value = hex"0000000000000000000000000000000000000000000000000000000000000001"; +@@ -430,7 +430,7 @@ slot = hex"0000000000000000000000000000000000000000000000000000000000000005"; + value = hex"0000000000000000000000000000000000000000000000000000000000000003"; + vm.store(systemOwnerSafeAddress, slot, value); + slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; +- value = hex"000000000000000000000000ae5dadfc48928543f706a9e6ce25c682aad2b63b"; ++ value = hex"000000000000000000000000150581358018524994fc29800b1783637943b103"; + vm.store(optimismPortalProxyAddress, slot, value); + slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; + value = hex"0000000000000000000000000000000000000000000000000000000000000001"; +@@ -463,7 +463,7 @@ slot = hex"0000000000000000000000000000000000000000000000000000000000000005"; + value = hex"0000000000000000000000000000000000000000000000000000000000000004"; + vm.store(systemOwnerSafeAddress, slot, value); + slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; +- value = hex"00000000000000000000000067866a5052e5302aad08e9f352331fd8622eb6dc"; ++ value = hex"000000000000000000000000d9ceca938f039e427edf626fa1f377d23a6b60c9"; + vm.store(systemConfigProxyAddress, slot, value); + slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; + value = hex"0000000000000000000000000000000000000000000000000000000000000001"; +@@ -532,7 +532,7 @@ slot = hex"0000000000000000000000000000000000000000000000000000000000000005"; + value = hex"0000000000000000000000000000000000000000000000000000000000000006"; + vm.store(systemOwnerSafeAddress, slot, value); + slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; +- value = hex"000000000000000000000000b7900b27be8f0e0ff65d1c3a4671e1220437dd2b"; ++ value = hex"0000000000000000000000006cb2c88abcd6391f9496f44be27d5d3b247e0159"; + vm.store(l1StandardBridgeProxyAddress, slot, value); + slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; + value = hex"0000000000000000000000000000000000000000000000000000000000000001"; +@@ -559,7 +559,7 @@ slot = hex"0000000000000000000000000000000000000000000000000000000000000005"; + value = hex"0000000000000000000000000000000000000000000000000000000000000007"; + vm.store(systemOwnerSafeAddress, slot, value); + slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; +- value = hex"0000000000000000000000005c4f5e749a61a9503c4aae8a9393e89609a0e804"; ++ value = hex"000000000000000000000000a4bd7e58a30ed0477fe7372883d09bf86619bb66"; + vm.store(l1ERC721BridgeProxyAddress, slot, value); + slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; + value = hex"0000000000000000000000000000000000000000000000000000000000000001"; @@ -583,7 +583,7 @@ slot = hex"0000000000000000000000000000000000000000000000000000000000000005"; value = hex"0000000000000000000000000000000000000000000000000000000000000008"; vm.store(systemOwnerSafeAddress, slot, value); slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; - value = hex"0000000000000000000000007c06d3a0a2f45e39e1798afbd9c3330971332a4f"; -+ value = hex"0000000000000000000000009daad714c8ed63f5fe60b85e3694b40899486d58"; ++ value = hex"00000000000000000000000079c3114e5f89266e2c8842871bce16d4e5076b1e"; vm.store(optimismMintableERC20FactoryProxyAddress, slot, value); slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; + value = hex"0000000000000000000000000000000000000000000000000000000000000001"; +@@ -613,7 +613,7 @@ slot = hex"0000000000000000000000000000000000000000000000000000000000000005"; + value = hex"000000000000000000000000000000000000000000000000000000000000000b"; + vm.store(systemOwnerSafeAddress, slot, value); + slot = hex"515216935740e67dfdda5cf8e248ea32b3277787818ab59153061ac875c9385e"; +- value = hex"000000000000000000000000094e6508ba9d9bf1ce421fff3de06ae56e67901b"; ++ value = hex"000000000000000000000000357b6cda94109749a0da475ac1bfd395a61eb908"; + vm.store(addressManagerAddress, slot, value); + slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; + value = hex"0000000000000000000000010000000000000000000000000000000000000000"; +@@ -643,7 +643,7 @@ slot = hex"0000000000000000000000000000000000000000000000000000000000000005"; + value = hex"000000000000000000000000000000000000000000000000000000000000000c"; + vm.store(systemOwnerSafeAddress, slot, value); + slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; +- value = hex"00000000000000000000000019652082f846171168daf378c4fd3ee85a0d4a60"; ++ value = hex"00000000000000000000000060d37db59d0d14f7ea5c7425a2c03244e08b162d"; + vm.store(l2OutputOracleProxyAddress, slot, value); + slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; + value = hex"0000000000000000000000000000000000000000000000000000000000000001"; +@@ -679,7 +679,7 @@ slot = hex"0000000000000000000000000000000000000000000000000000000000000005"; + value = hex"000000000000000000000000000000000000000000000000000000000000000d"; + vm.store(systemOwnerSafeAddress, slot, value); + slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; +- value = hex"00000000000000000000000020b168142354cee65a32f6d8cf3033e592299765"; ++ value = hex"0000000000000000000000008efda795511cbbdffc9eeca1a5bf30f5b1e1ef9e"; + vm.store(disputeGameFactoryProxyAddress, slot, value); + slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; + value = hex"0000000000000000000000000000000000000000000000000000000000000001"; +@@ -700,7 +700,7 @@ slot = hex"0000000000000000000000000000000000000000000000000000000000000005"; + value = hex"000000000000000000000000000000000000000000000000000000000000000e"; + vm.store(systemOwnerSafeAddress, slot, value); + slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; +- value = hex"0000000000000000000000002a6347edd3c7813cde46dd7ea61ff1cf2290bc05"; ++ value = hex"000000000000000000000000e49ced258137cc5e18fb9aba2aa14069263d8f49"; + vm.store(delayedWETHProxyAddress, slot, value); + slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; + value = hex"0000000000000000000000000000000000000000000000000000000000000001"; +@@ -724,7 +724,7 @@ slot = hex"0000000000000000000000000000000000000000000000000000000000000005"; + value = hex"000000000000000000000000000000000000000000000000000000000000000f"; + vm.store(systemOwnerSafeAddress, slot, value); + slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; +- value = hex"0000000000000000000000002a6347edd3c7813cde46dd7ea61ff1cf2290bc05"; ++ value = hex"000000000000000000000000e49ced258137cc5e18fb9aba2aa14069263d8f49"; + vm.store(permissionedDelayedWETHProxyAddress, slot, value); + slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; + value = hex"0000000000000000000000000000000000000000000000000000000000000001"; +@@ -748,7 +748,7 @@ slot = hex"0000000000000000000000000000000000000000000000000000000000000005"; + value = hex"0000000000000000000000000000000000000000000000000000000000000010"; + vm.store(systemOwnerSafeAddress, slot, value); + slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; +- value = hex"00000000000000000000000063b71b96756c693f7065345fecd9b7843b3e7c57"; ++ value = hex"000000000000000000000000dec4d949cf1a2e824ee4f8b12064e166b96171dd"; + vm.store(anchorStateRegistryProxyAddress, slot, value); + slot = hex"0000000000000000000000000000000000000000000000000000000000000000"; value = hex"0000000000000000000000000000000000000000000000000000000000000001";
@@ -34918,8 +137736,8 @@
@@ -34945,35 +137763,80 @@
-
+2
-
-2
+
+17
+
-17
-
diff --git OP/packages/contracts-bedrock/test/kontrol/proofs/utils/DeploymentSummaryFaultProofsCode.sol CELO/packages/contracts-bedrock/test/kontrol/proofs/utils/DeploymentSummaryFaultProofsCode.sol -index d05414671296eb675afcba7482458f29057a8d45..3c0ca67938e96256fda9cd1de90b8c331f0d83b7 100644 +
diff --git OP/packages/contracts-bedrock/test/kontrol/proofs/utils/DeploymentSummaryFaultProofsCode.sol CELO/packages/contracts-bedrock/test/kontrol/proofs/utils/DeploymentSummaryFaultProofsCode.sol +index d05414671296eb675afcba7482458f29057a8d45..a2809e334863857248b30652e6bc6350cd65cdda 100644 --- OP/packages/contracts-bedrock/test/kontrol/proofs/utils/DeploymentSummaryFaultProofsCode.sol +++ CELO/packages/contracts-bedrock/test/kontrol/proofs/utils/DeploymentSummaryFaultProofsCode.sol -@@ -47,7 +47,7 @@ hex"60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a"; +@@ -17,11 +17,11 @@ hex"60806040526004361061010e5760003560e01c8063860f7cda116100a557806399a88ec411610074578063b794726211610059578063b794726214610329578063f2fde38b14610364578063f3b7dead1461038457600080fd5b806399a88ec4146102e95780639b2ea4bd1461030957600080fd5b8063860f7cda1461026b5780638d52d4a01461028b5780638da5cb5b146102ab5780639623609d146102d657600080fd5b80633ab76e9f116100e15780633ab76e9f146101cc5780636bd9f516146101f9578063715018a6146102365780637eff275e1461024b57600080fd5b80630652b57a1461011357806307c8f7b014610135578063204e1c7a14610155578063238181ae1461019f575b600080fd5b34801561011f57600080fd5b5061013361012e3660046111f9565b6103a4565b005b34801561014157600080fd5b50610133610150366004611216565b6103f3565b34801561016157600080fd5b506101756101703660046111f9565b610445565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156101ab57600080fd5b506101bf6101ba3660046111f9565b61066b565b60405161019691906112ae565b3480156101d857600080fd5b506003546101759073ffffffffffffffffffffffffffffffffffffffff1681565b34801561020557600080fd5b506102296102143660046111f9565b60016020526000908152604090205460ff1681565b60405161019691906112f0565b34801561024257600080fd5b50610133610705565b34801561025757600080fd5b50610133610266366004611331565b610719565b34801561027757600080fd5b5061013361028636600461148c565b6108cc565b34801561029757600080fd5b506101336102a63660046114dc565b610903565b3480156102b757600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff16610175565b6101336102e436600461150e565b610977565b3480156102f557600080fd5b50610133610304366004611331565b610b8e565b34801561031557600080fd5b50610133610324366004611584565b610e1e565b34801561033557600080fd5b5060035474010000000000000000000000000000000000000000900460ff166040519015158152602001610196565b34801561037057600080fd5b5061013361037f3660046111f9565b610eb4565b34801561039057600080fd5b5061017561039f3660046111f9565b610f6b565b6103ac6110e1565b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6103fb6110e1565b6003805491151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff909216919091179055565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602052604081205460ff1681816002811115610481576104816112c1565b036104fc578273ffffffffffffffffffffffffffffffffffffffff16635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104f591906115cb565b9392505050565b6001816002811115610510576105106112c1565b03610560578273ffffffffffffffffffffffffffffffffffffffff1663aaf10f426040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b6002816002811115610574576105746112c1565b036105fe5760035473ffffffffffffffffffffffffffffffffffffffff8481166000908152600260205260409081902090517fbf40fac1000000000000000000000000000000000000000000000000000000008152919092169163bf40fac1916105e19190600401611635565b602060405180830381865afa1580156104d1573d6000803e3d6000fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f50726f787941646d696e3a20756e6b6e6f776e2070726f78792074797065000060448201526064015b60405180910390fd5b50919050565b60026020526000908152604090208054610684906115e8565b80601f01602080910402602001604051908101604052809291908181526020018280546106b0906115e8565b80156106fd5780601f106106d2576101008083540402835291602001916106fd565b820191906000526020600020905b8154815290600101906020018083116106e057829003601f168201915b505050505081565b61070d6110e1565b6107176000611162565b565b6107216110e1565b73ffffffffffffffffffffffffffffffffffffffff821660009081526001602052604081205460ff169081600281111561075d5761075d6112c1565b036107e9576040517f8f28397000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152841690638f283970906024015b600060405180830381600087803b1580156107cc57600080fd5b505af11580156107e0573d6000803e3d6000fd5b50505050505050565b60018160028111156107fd576107fd6112c1565b03610856576040517f13af403500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906313af4035906024016107b2565b600281600281111561086a5761086a6112c1565b036105fe576003546040517ff2fde38b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301529091169063f2fde38b906024016107b2565b505050565b6108d46110e1565b73ffffffffffffffffffffffffffffffffffffffff821660009081526002602052604090206108c78282611724565b61090b6110e1565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600160208190526040909120805483927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff009091169083600281111561096e5761096e6112c1565b02179055505050565b61097f6110e1565b73ffffffffffffffffffffffffffffffffffffffff831660009081526001602052604081205460ff16908160028111156109bb576109bb6112c1565b03610a81576040517f4f1ef28600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff851690634f1ef286903490610a16908790879060040161183e565b60006040518083038185885af1158015610a34573d6000803e3d6000fd5b50505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610a7b9190810190611875565b50610b88565b610a8b8484610b8e565b60008473ffffffffffffffffffffffffffffffffffffffff163484604051610ab391906118ec565b60006040518083038185875af1925050503d8060008114610af0576040519150601f19603f3d011682016040523d82523d6000602084013e610af5565b606091505b5050905080610b86576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f50726f787941646d696e3a2063616c6c20746f2070726f78792061667465722060448201527f75706772616465206661696c6564000000000000000000000000000000000000606482015260840161065c565b505b50505050565b610b966110e1565b73ffffffffffffffffffffffffffffffffffffffff821660009081526001602052604081205460ff1690816002811115610bd257610bd26112c1565b03610c2b576040517f3659cfe600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152841690633659cfe6906024016107b2565b6001816002811115610c3f57610c3f6112c1565b03610cbe576040517f9b0b0fda0000000000000000000000000000000000000000000000000000000081527f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc600482015273ffffffffffffffffffffffffffffffffffffffff8381166024830152841690639b0b0fda906044016107b2565b6002816002811115610cd257610cd26112c1565b03610e165773ffffffffffffffffffffffffffffffffffffffff831660009081526002602052604081208054610d07906115e8565b80601f0160208091040260200160405190810160405280929190818152602001828054610d33906115e8565b8015610d805780601f10610d5557610100808354040283529160200191610d80565b820191906000526020600020905b815481529060010190602001808311610d6357829003601f168201915b50506003546040517f9b2ea4bd00000000000000000000000000000000000000000000000000000000815294955073ffffffffffffffffffffffffffffffffffffffff1693639b2ea4bd9350610dde92508591508790600401611908565b600060405180830381600087803b158015610df857600080fd5b505af1158015610e0c573d6000803e3d6000fd5b5050505050505050565b6108c7611940565b610e266110e1565b6003546040517f9b2ea4bd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911690639b2ea4bd90610e7e9085908590600401611908565b600060405180830381600087803b158015610e9857600080fd5b505af1158015610eac573d6000803e3d6000fd5b505050505050565b610ebc6110e1565b73ffffffffffffffffffffffffffffffffffffffff8116610f5f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161065c565b610f6881611162565b50565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602052604081205460ff1681816002811115610fa757610fa76112c1565b03610ff7578273ffffffffffffffffffffffffffffffffffffffff1663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b600181600281111561100b5761100b6112c1565b0361105b578273ffffffffffffffffffffffffffffffffffffffff1663893d20e86040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b600281600281111561106f5761106f6112c1565b036105fe57600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d1573d6000803e3d6000fd5b60005473ffffffffffffffffffffffffffffffffffffffff163314610717576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161065c565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b73ffffffffffffffffffffffffffffffffffffffff81168114610f6857600080fd5b60006020828403121561120b57600080fd5b81356104f5816111d7565b60006020828403121561122857600080fd5b813580151581146104f557600080fd5b60005b8381101561125357818101518382015260200161123b565b83811115610b885750506000910152565b6000815180845261127c816020860160208601611238565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006104f56020830184611264565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b602081016003831061132b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b6000806040838503121561134457600080fd5b823561134f816111d7565b9150602083013561135f816111d7565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156113e0576113e061136a565b604052919050565b600067ffffffffffffffff8211156114025761140261136a565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600061144161143c846113e8565b611399565b905082815283838301111561145557600080fd5b828260208301376000602084830101529392505050565b600082601f83011261147d57600080fd5b6104f58383356020850161142e565b6000806040838503121561149f57600080fd5b82356114aa816111d7565b9150602083013567ffffffffffffffff8111156114c657600080fd5b6114d28582860161146c565b9150509250929050565b600080604083850312156114ef57600080fd5b82356114fa816111d7565b915060208301356003811061135f57600080fd5b60008060006060848603121561152357600080fd5b833561152e816111d7565b9250602084013561153e816111d7565b9150604084013567ffffffffffffffff81111561155a57600080fd5b8401601f8101861361156b57600080fd5b61157a8682356020840161142e565b9150509250925092565b6000806040838503121561159757600080fd5b823567ffffffffffffffff8111156115ae57600080fd5b6115ba8582860161146c565b925050602083013561135f816111d7565b6000602082840312156115dd57600080fd5b81516104f5816111d7565b600181811c908216806115fc57607f821691505b602082108103610665577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000602080835260008454611649816115e8565b8084870152604060018084166000811461166a57600181146116a2576116d0565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008516838a01528284151560051b8a010195506116d0565b896000528660002060005b858110156116c85781548b82018601529083019088016116ad565b8a0184019650505b509398975050505050505050565b601f8211156108c757600081815260208120601f850160051c810160208610156117055750805b601f850160051c820191505b81811015610eac57828155600101611711565b815167ffffffffffffffff81111561173e5761173e61136a565b6117528161174c84546115e8565b846116de565b602080601f8311600181146117a5576000841561176f5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555610eac565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156117f2578886015182559484019460019091019084016117d3565b508582101561182e57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b73ffffffffffffffffffffffffffffffffffffffff8316815260406020820152600061186d6040830184611264565b949350505050565b60006020828403121561188757600080fd5b815167ffffffffffffffff81111561189e57600080fd5b8201601f810184136118af57600080fd5b80516118bd61143c826113e8565b8181528560208385010111156118d257600080fd5b6118e3826020830160208601611238565b95945050505050565b600082516118fe818460208701611238565b9190910192915050565b60408152600061191b6040830185611264565b905073ffffffffffffffffffffffffffffffffffffffff831660208301529392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fdfea164736f6c634300080f000a"; + bytes internal constant superchainConfigProxyCode = + hex"60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a"; + bytes internal constant superchainConfigCode = +- hex"608060405234801561001057600080fd5b50600436106100885760003560e01c80635c975abb1161005b5780635c975abb146101255780636da663551461013d5780637fbf7b6a14610150578063c23a451a1461016657600080fd5b80633f4ba83a1461008d578063400ada7514610097578063452a9320146100aa57806354fd4d50146100dc575b600080fd5b61009561016e565b005b6100956100a5366004610746565b610294565b6100b261046d565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6101186040518060400160405280600581526020017f312e312e3000000000000000000000000000000000000000000000000000000081525081565b6040516100d39190610808565b61012d6104a6565b60405190151581526020016100d3565b61009561014b366004610851565b6104d6565b6101586105a4565b6040519081526020016100d3565b6101586105d2565b61017661046d565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610235576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f5375706572636861696e436f6e6669673a206f6e6c7920677561726469616e2060448201527f63616e20756e706175736500000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61026961026360017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b60009055565b6040517fa45f47fdea8a1efdd9029a5691c7f759c32b7c698632b563573e155625d1693390600090a1565b600054610100900460ff16158080156102b45750600054600160ff909116105b806102ce5750303b1580156102ce575060005460ff166001145b61035a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161022c565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156103b857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6103c18361061d565b8115610405576104056040518060400160405280601281526020017f496e697469616c697a65722070617573656400000000000000000000000000008152506106d8565b801561046857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b60006104a161049d60017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe69610920565b5490565b905090565b60006104a161049d60017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b6104de61046d565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610598576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f5375706572636861696e436f6e6669673a206f6e6c7920677561726469616e2060448201527f63616e2070617573650000000000000000000000000000000000000000000000606482015260840161022c565b6105a1816106d8565b50565b6105cf60017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b81565b6105cf60017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe69610920565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b9055565b61065061064b60017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe69610920565b829055565b60006040805173ffffffffffffffffffffffffffffffffffffffff841660208201527f7b743789cff01dafdeae47739925425aab5dfd02d0c8229e4a508bcd2b9f42bb9101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526106cd91610808565b60405180910390a250565b61070c61070660017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b60019055565b7fc32e6d5d6d1de257f64eac19ddb1f700ba13527983849c9486b1ab007ea283818160405161073b9190610808565b60405180910390a150565b6000806040838503121561075957600080fd5b823573ffffffffffffffffffffffffffffffffffffffff8116811461077d57600080fd5b91506020830135801515811461079257600080fd5b809150509250929050565b6000815180845260005b818110156107c3576020818501810151868301820152016107a7565b818111156107d5576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061081b602083018461079d565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561086357600080fd5b813567ffffffffffffffff8082111561087b57600080fd5b818401915084601f83011261088f57600080fd5b8135818111156108a1576108a1610822565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156108e7576108e7610822565b8160405282815287602084870101111561090057600080fd5b826020860160208301376000928101602001929092525095945050505050565b600082821015610959577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50039056fea164736f6c634300080f000a"; ++ hex"608060405234801561001057600080fd5b50600436106100885760003560e01c80635c975abb1161005b5780635c975abb146101255780636da663551461013d5780637fbf7b6a14610150578063c23a451a1461016657600080fd5b80633f4ba83a1461008d578063400ada7514610097578063452a9320146100aa57806354fd4d50146100dc575b600080fd5b61009561016e565b005b6100956100a5366004610746565b610294565b6100b261046d565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6101186040518060400160405280600c81526020017f312e312e312d626574612e31000000000000000000000000000000000000000081525081565b6040516100d39190610808565b61012d6104a6565b60405190151581526020016100d3565b61009561014b366004610851565b6104d6565b6101586105a4565b6040519081526020016100d3565b6101586105d2565b61017661046d565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610235576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f5375706572636861696e436f6e6669673a206f6e6c7920677561726469616e2060448201527f63616e20756e706175736500000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61026961026360017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b60009055565b6040517fa45f47fdea8a1efdd9029a5691c7f759c32b7c698632b563573e155625d1693390600090a1565b600054610100900460ff16158080156102b45750600054600160ff909116105b806102ce5750303b1580156102ce575060005460ff166001145b61035a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161022c565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156103b857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6103c18361061d565b8115610405576104056040518060400160405280601281526020017f496e697469616c697a65722070617573656400000000000000000000000000008152506106d8565b801561046857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b60006104a161049d60017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe69610920565b5490565b905090565b60006104a161049d60017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b6104de61046d565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610598576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f5375706572636861696e436f6e6669673a206f6e6c7920677561726469616e2060448201527f63616e2070617573650000000000000000000000000000000000000000000000606482015260840161022c565b6105a1816106d8565b50565b6105cf60017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b81565b6105cf60017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe69610920565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b9055565b61065061064b60017fd30e835d3f35624761057ff5b27d558f97bd5be034621e62240e5c0b784abe69610920565b829055565b60006040805173ffffffffffffffffffffffffffffffffffffffff841660208201527f7b743789cff01dafdeae47739925425aab5dfd02d0c8229e4a508bcd2b9f42bb9101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526106cd91610808565b60405180910390a250565b61070c61070660017f54176ff9944c4784e5857ec4e5ef560a462c483bf534eda43f91bb01a470b1b7610920565b60019055565b7fc32e6d5d6d1de257f64eac19ddb1f700ba13527983849c9486b1ab007ea283818160405161073b9190610808565b60405180910390a150565b6000806040838503121561075957600080fd5b823573ffffffffffffffffffffffffffffffffffffffff8116811461077d57600080fd5b91506020830135801515811461079257600080fd5b809150509250929050565b6000815180845260005b818110156107c3576020818501810151868301820152016107a7565b818111156107d5576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061081b602083018461079d565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561086357600080fd5b813567ffffffffffffffff8082111561087b57600080fd5b818401915084601f83011261088f57600080fd5b8135818111156108a1576108a1610822565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156108e7576108e7610822565b8160405282815287602084870101111561090057600080fd5b826020860160208301376000928101602001929092525095945050505050565b600082821015610959577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50039056fea164736f6c634300080f000a"; + bytes internal constant protocolVersionsProxyCode = + hex"60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a"; + bytes internal constant protocolVersionsCode = +- hex"608060405234801561001057600080fd5b50600436106100d45760003560e01c80638da5cb5b11610081578063f2fde38b1161005b578063f2fde38b146101b8578063f7d12760146101cb578063ffa1ad74146101d357600080fd5b80638da5cb5b14610180578063d798b1ac146101a8578063dc8452cd146101b057600080fd5b80635fd579af116100b25780635fd579af14610152578063715018a6146101655780637a1ac61e1461016d57600080fd5b80630457d6f2146100d9578063206a8300146100ee57806354fd4d5014610109575b600080fd5b6100ec6100e73660046108c3565b6101db565b005b6100f66101ef565b6040519081526020015b60405180910390f35b6101456040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516101009190610947565b6100ec6101603660046108c3565b61021d565b6100ec61022e565b6100ec61017b36600461098a565b610242565b60335460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610100565b6100f66103f7565b6100f6610430565b6100ec6101c63660046109bd565b610460565b6100f6610514565b6100f6600081565b6101e361055f565b6101ec816105e0565b50565b61021a60017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16109d8565b81565b61022561055f565b6101ec81610698565b61023661055f565b6102406000610712565b565b600054610100900460ff16158080156102625750600054600160ff909116105b8061027c5750303b15801561027c575060005460ff166001145b61030d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561036b57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610373610789565b61037c84610460565b610385836105e0565b61038e82610698565b80156103f157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b600061042b61042760017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6109d8565b5490565b905090565b600061042b61042760017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16109d8565b61046861055f565b73ffffffffffffffffffffffffffffffffffffffff811661050b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610304565b6101ec81610712565b61021a60017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6109d8565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b9055565b60335473ffffffffffffffffffffffffffffffffffffffff163314610240576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610304565b61061361060e60017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16109d8565b829055565b60008160405160200161062891815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060005b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be8360405161068c9190610947565b60405180910390a35050565b6106c661060e60017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6109d8565b6000816040516020016106db91815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529050600161065b565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16610820576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610304565b610240600054610100900460ff166108ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610304565b61024033610712565b6000602082840312156108d557600080fd5b5035919050565b6000815180845260005b81811015610902576020818501810151868301820152016108e6565b81811115610914576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061095a60208301846108dc565b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461098557600080fd5b919050565b60008060006060848603121561099f57600080fd5b6109a884610961565b95602085013595506040909401359392505050565b6000602082840312156109cf57600080fd5b61095a82610961565b600082821015610a11577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50039056fea164736f6c634300080f000a"; ++ hex"608060405234801561001057600080fd5b50600436106100d45760003560e01c80638da5cb5b11610081578063f2fde38b1161005b578063f2fde38b146101b8578063f7d12760146101cb578063ffa1ad74146101d357600080fd5b80638da5cb5b14610180578063d798b1ac146101a8578063dc8452cd146101b057600080fd5b80635fd579af116100b25780635fd579af14610152578063715018a6146101655780637a1ac61e1461016d57600080fd5b80630457d6f2146100d9578063206a8300146100ee57806354fd4d5014610109575b600080fd5b6100ec6100e73660046108c3565b6101db565b005b6100f66101ef565b6040519081526020015b60405180910390f35b6101456040518060400160405280600c81526020017f312e302e312d626574612e31000000000000000000000000000000000000000081525081565b6040516101009190610947565b6100ec6101603660046108c3565b61021d565b6100ec61022e565b6100ec61017b36600461098a565b610242565b60335460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610100565b6100f66103f7565b6100f6610430565b6100ec6101c63660046109bd565b610460565b6100f6610514565b6100f6600081565b6101e361055f565b6101ec816105e0565b50565b61021a60017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16109d8565b81565b61022561055f565b6101ec81610698565b61023661055f565b6102406000610712565b565b600054610100900460ff16158080156102625750600054600160ff909116105b8061027c5750303b15801561027c575060005460ff166001145b61030d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561036b57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610373610789565b61037c84610460565b610385836105e0565b61038e82610698565b80156103f157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b600061042b61042760017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6109d8565b5490565b905090565b600061042b61042760017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16109d8565b61046861055f565b73ffffffffffffffffffffffffffffffffffffffff811661050b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610304565b6101ec81610712565b61021a60017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6109d8565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b9055565b60335473ffffffffffffffffffffffffffffffffffffffff163314610240576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610304565b61061361060e60017f4aaefe95bd84fd3f32700cf3b7566bc944b73138e41958b5785826df2aecace16109d8565b829055565b60008160405160200161062891815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060005b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be8360405161068c9190610947565b60405180910390a35050565b6106c661060e60017fe314dfc40f0025322aacc0ba8ef420b62fb3b702cf01e0cdf3d829117ac2ff1b6109d8565b6000816040516020016106db91815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529050600161065b565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16610820576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610304565b610240600054610100900460ff166108ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610304565b61024033610712565b6000602082840312156108d557600080fd5b5035919050565b6000815180845260005b81811015610902576020818501810151868301820152016108e6565b81811115610914576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061095a60208301846108dc565b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461098557600080fd5b919050565b60008060006060848603121561099f57600080fd5b6109a884610961565b95602085013595506040909401359392505050565b6000602082840312156109cf57600080fd5b61095a82610961565b600082821015610a11577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50039056fea164736f6c634300080f000a"; + bytes internal constant optimismPortalProxyCode = + hex"60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a"; + bytes internal constant systemConfigProxyCode = +@@ -45,33 +45,33 @@ hex"60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a"; + bytes internal constant anchorStateRegistryProxyCode = + hex"60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100be5780638f283970146100f8578063f851a440146101185761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61012d565b005b61006b61012d565b34801561008157600080fd5b5061006b6100903660046106dd565b610224565b6100a86100a33660046106f8565b610296565b6040516100b5919061077b565b60405180910390f35b3480156100ca57600080fd5b506100d3610419565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b34801561010457600080fd5b5061006b6101133660046106dd565b6104b0565b34801561012457600080fd5b506100d3610517565b60006101577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b905073ffffffffffffffffffffffffffffffffffffffff8116610201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f50726f78793a20696d706c656d656e746174696f6e206e6f7420696e6974696160448201527f6c697a656400000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b3660008037600080366000845af43d6000803e8061021e573d6000fd5b503d6000f35b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061027d575033155b1561028e5761028b816105a3565b50565b61028b61012d565b60606102c07fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806102f7575033155b1561040a57610305846105a3565b6000808573ffffffffffffffffffffffffffffffffffffffff16858560405161032f9291906107ee565b600060405180830381855af49150503d806000811461036a576040519150601f19603f3d011682016040523d82523d6000602084013e61036f565b606091505b509150915081610401576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f50726f78793a2064656c656761746563616c6c20746f206e657720696d706c6560448201527f6d656e746174696f6e20636f6e7472616374206661696c65640000000000000060648201526084016101f8565b91506104129050565b61041261012d565b9392505050565b60006104437fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061047a575033155b156104a557507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6104ad61012d565b90565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610509575033155b1561028e5761028b8161060c565b60006105417fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610578575033155b156104a557507fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc81815560405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a25050565b60006106367fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61038381556040805173ffffffffffffffffffffffffffffffffffffffff80851682528616602082015292935090917f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f910160405180910390a1505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146106d857600080fd5b919050565b6000602082840312156106ef57600080fd5b610412826106b4565b60008060006040848603121561070d57600080fd5b610716846106b4565b9250602084013567ffffffffffffffff8082111561073357600080fd5b818601915086601f83011261074757600080fd5b81358181111561075657600080fd5b87602082850101111561076857600080fd5b6020830194508093505050509250925092565b600060208083528351808285015260005b818110156107a85785810183015185820160400152820161078c565b818111156107ba576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b818382376000910190815291905056fea164736f6c634300080f000a"; bytes internal constant l1CrossDomainMessengerCode = - hex"60806040526004361061018b5760003560e01c80636425666b116100d6578063b1b1b2091161007f578063d764ad0b11610059578063d764ad0b1461049b578063db505d80146104ae578063ecc70428146104db57600080fd5b8063b1b1b2091461042b578063b28ade251461045b578063c0c53b8b1461047b57600080fd5b80638cbeeef2116100b05780638cbeeef2146102d05780639fce812c146103d0578063a4e7f8bd146103fb57600080fd5b80636425666b146103775780636e296e45146103a457806383a74074146103b957600080fd5b80633dbb202b1161013857806354fd4d501161011257806354fd4d50146102e65780635644cfdf1461033c5780635c975abb1461035257600080fd5b80633dbb202b146102935780633f827a5a146102a85780634c1d6a69146102d057600080fd5b80632828d7e8116101695780632828d7e81461022457806333d7e2bd1461023957806335e80ab31461026657600080fd5b8063028f85f7146101905780630c568498146101c35780630ff754ea146101d8575b600080fd5b34801561019c57600080fd5b506101a5601081565b60405167ffffffffffffffff90911681526020015b60405180910390f35b3480156101cf57600080fd5b506101a5603f81565b3480156101e457600080fd5b5060fc5473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101ba565b34801561023057600080fd5b506101a5604081565b34801561024557600080fd5b5060fd546101ff9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561027257600080fd5b5060fb546101ff9073ffffffffffffffffffffffffffffffffffffffff1681565b6102a66102a1366004611bdd565b610540565b005b3480156102b457600080fd5b506102bd600181565b60405161ffff90911681526020016101ba565b3480156102dc57600080fd5b506101a5619c4081565b3480156102f257600080fd5b5061032f6040518060400160405280600581526020017f322e342e3000000000000000000000000000000000000000000000000000000081525081565b6040516101ba9190611caf565b34801561034857600080fd5b506101a561138881565b34801561035e57600080fd5b5061036761083d565b60405190151581526020016101ba565b34801561038357600080fd5b5060fc546101ff9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156103b057600080fd5b506101ff6108d6565b3480156103c557600080fd5b506101a562030d4081565b3480156103dc57600080fd5b5060cf5473ffffffffffffffffffffffffffffffffffffffff166101ff565b34801561040757600080fd5b50610367610416366004611cc9565b60ce6020526000908152604090205460ff1681565b34801561043757600080fd5b50610367610446366004611cc9565b60cb6020526000908152604090205460ff1681565b34801561046757600080fd5b506101a5610476366004611ce2565b6109bd565b34801561048757600080fd5b506102a6610496366004611d36565b610a2b565b6102a66104a9366004611d81565b610ca2565b3480156104ba57600080fd5b5060cf546101ff9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156104e757600080fd5b5061053260cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b6040519081526020016101ba565b6105486115d3565b156105e05734156105e0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f43726f7373446f6d61696e4d657373656e6765723a2063616e6e6f742073656e60448201527f642076616c7565207769746820637573746f6d2067617320746f6b656e00000060648201526084015b60405180910390fd5b60cf546107129073ffffffffffffffffffffffffffffffffffffffff166106088585856109bd565b347fd764ad0b0000000000000000000000000000000000000000000000000000000061067460cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b338a34898c8c6040516024016106909796959493929190611e50565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611612565b8373ffffffffffffffffffffffffffffffffffffffff167fcb0f7ffd78f9aee47a248fae8db181db6eee833039123e026dcbff529522e52a33858561079760cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b866040516107a9959493929190611eaf565b60405180910390a260405134815233907f8ebb2ec2465bdb2a06a66fc37a0963af8a2a6a1479d81d56fdb8cbb98096d5469060200160405180910390a2505060cd80547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808216600101167fffff0000000000000000000000000000000000000000000000000000000000009091161790555050565b60fb54604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa1580156108ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108d19190611efd565b905090565b60cc5460009073ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2153016109a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f43726f7373446f6d61696e4d657373656e6765723a2078446f6d61696e4d657360448201527f7361676553656e646572206973206e6f7420736574000000000000000000000060648201526084016105d7565b5060cc5473ffffffffffffffffffffffffffffffffffffffff1690565b6000611388619c4080603f6109d9604063ffffffff8816611f4e565b6109e39190611f7e565b6109ee601088611f4e565b6109fb9062030d40611fcc565b610a059190611fcc565b610a0f9190611fcc565b610a199190611fcc565b610a239190611fcc565b949350505050565b6000547501000000000000000000000000000000000000000000900460ff1615808015610a76575060005460017401000000000000000000000000000000000000000090910460ff16105b80610aa85750303b158015610aa8575060005474010000000000000000000000000000000000000000900460ff166001145b610b34576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016105d7565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790558015610bba57600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000001790555b60fb805473ffffffffffffffffffffffffffffffffffffffff8087167fffffffffffffffffffffffff00000000000000000000000000000000000000009283161790925560fc805486841690831617905560fd805492851692909116919091179055610c397342000000000000000000000000000000000000076116ab565b8015610c9c57600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b610caa61083d565b15610d11576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f43726f7373446f6d61696e4d657373656e6765723a207061757365640000000060448201526064016105d7565b60f087901c60028110610dcc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f43726f7373446f6d61696e4d657373656e6765723a206f6e6c7920766572736960448201527f6f6e2030206f722031206d657373616765732061726520737570706f7274656460648201527f20617420746869732074696d6500000000000000000000000000000000000000608482015260a4016105d7565b8061ffff16600003610ec1576000610e1d878986868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508f92506117e7915050565b600081815260cb602052604090205490915060ff1615610ebf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f43726f7373446f6d61696e4d657373656e6765723a206c65676163792077697460448201527f6864726177616c20616c72656164792072656c6179656400000000000000000060648201526084016105d7565b505b6000610f07898989898989898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061180692505050565b9050610f11611829565b15610f4957853414610f2557610f25611ff8565b600081815260ce602052604090205460ff1615610f4457610f44611ff8565b61109b565b3415610ffd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605060248201527f43726f7373446f6d61696e4d657373656e6765723a2076616c7565206d75737460448201527f206265207a65726f20756e6c657373206d6573736167652069732066726f6d2060648201527f612073797374656d206164647265737300000000000000000000000000000000608482015260a4016105d7565b600081815260ce602052604090205460ff1661109b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520636160448201527f6e6e6f74206265207265706c617965640000000000000000000000000000000060648201526084016105d7565b6110a487611905565b15611157576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f43726f7373446f6d61696e4d657373656e6765723a2063616e6e6f742073656e60448201527f64206d65737361676520746f20626c6f636b65642073797374656d206164647260648201527f6573730000000000000000000000000000000000000000000000000000000000608482015260a4016105d7565b600081815260cb602052604090205460ff16156111f6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520686160448201527f7320616c7265616479206265656e2072656c617965640000000000000000000060648201526084016105d7565b61121785611208611388619c40611fcc565b67ffffffffffffffff1661194b565b158061123d575060cc5473ffffffffffffffffffffffffffffffffffffffff1661dead14155b1561135657600081815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555182917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff320161134f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d6573736167650000000000000000000000000000000000000060648201526084016105d7565b50506115ae565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8a1617905560006113e788619c405a6113aa9190612027565b8988888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061196992505050565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790559050801561149d57600082815260cb602052604090205460ff161561143a5761143a611ff8565b600082815260cb602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f4641df4a962071e12719d8c8c8e5ac7fc4d97b927346a3d7a335b1f7517e133c91a26115aa565b600082815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff32016115aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d6573736167650000000000000000000000000000000000000060648201526084016105d7565b5050505b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6000806115de611981565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b60fc546040517fe9e05c4200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063e9e05c4290849061167390889083908990600090899060040161203e565b6000604051808303818588803b15801561168c57600080fd5b505af11580156116a0573d6000803e3d6000fd5b505050505050505050565b6000547501000000000000000000000000000000000000000000900460ff16611756576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016105d7565b60cc5473ffffffffffffffffffffffffffffffffffffffff166117a05760cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790555b60cf80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60006117f585858585611a1e565b805190602001209050949350505050565b6000611816878787878787611ab7565b8051906020012090509695505050505050565b60fc5460009073ffffffffffffffffffffffffffffffffffffffff16331480156108d1575060cf5460fc54604080517f9bf62d82000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9384169390921691639bf62d82916004808201926020929091908290030181865afa1580156118c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118e99190612096565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b600073ffffffffffffffffffffffffffffffffffffffff8216301480611945575060fc5473ffffffffffffffffffffffffffffffffffffffff8381169116145b92915050565b600080603f83619c4001026040850201603f5a021015949350505050565b6000806000835160208501868989f195945050505050565b60fd54604080517f4397dfef0000000000000000000000000000000000000000000000000000000081528151600093849373ffffffffffffffffffffffffffffffffffffffff90911692634397dfef92600480830193928290030181865afa1580156119f1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a1591906120b3565b90939092509050565b606084848484604051602401611a3794939291906120f3565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fcbd4ece9000000000000000000000000000000000000000000000000000000001790529050949350505050565b6060868686868686604051602401611ad49695949392919061213d565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd764ad0b0000000000000000000000000000000000000000000000000000000017905290509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff81168114611b7857600080fd5b50565b60008083601f840112611b8d57600080fd5b50813567ffffffffffffffff811115611ba557600080fd5b602083019150836020828501011115611bbd57600080fd5b9250929050565b803563ffffffff81168114611bd857600080fd5b919050565b60008060008060608587031215611bf357600080fd5b8435611bfe81611b56565b9350602085013567ffffffffffffffff811115611c1a57600080fd5b611c2687828801611b7b565b9094509250611c39905060408601611bc4565b905092959194509250565b6000815180845260005b81811015611c6a57602081850181015186830182015201611c4e565b81811115611c7c576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611cc26020830184611c44565b9392505050565b600060208284031215611cdb57600080fd5b5035919050565b600080600060408486031215611cf757600080fd5b833567ffffffffffffffff811115611d0e57600080fd5b611d1a86828701611b7b565b9094509250611d2d905060208501611bc4565b90509250925092565b600080600060608486031215611d4b57600080fd5b8335611d5681611b56565b92506020840135611d6681611b56565b91506040840135611d7681611b56565b809150509250925092565b600080600080600080600060c0888a031215611d9c57600080fd5b873596506020880135611dae81611b56565b95506040880135611dbe81611b56565b9450606088013593506080880135925060a088013567ffffffffffffffff811115611de857600080fd5b611df48a828b01611b7b565b989b979a50959850939692959293505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b878152600073ffffffffffffffffffffffffffffffffffffffff808916602084015280881660408401525085606083015263ffffffff8516608083015260c060a0830152611ea260c083018486611e07565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff86168152608060208201526000611edf608083018688611e07565b905083604083015263ffffffff831660608301529695505050505050565b600060208284031215611f0f57600080fd5b81518015158114611cc257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600067ffffffffffffffff80831681851681830481118215151615611f7557611f75611f1f565b02949350505050565b600067ffffffffffffffff80841680611fc0577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b92169190910492915050565b600067ffffffffffffffff808316818516808303821115611fef57611fef611f1f565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b60008282101561203957612039611f1f565b500390565b73ffffffffffffffffffffffffffffffffffffffff8616815284602082015267ffffffffffffffff84166040820152821515606082015260a06080820152600061208b60a0830184611c44565b979650505050505050565b6000602082840312156120a857600080fd5b8151611cc281611b56565b600080604083850312156120c657600080fd5b82516120d181611b56565b602084015190925060ff811681146120e857600080fd5b809150509250929050565b600073ffffffffffffffffffffffffffffffffffffffff80871683528086166020840152506080604083015261212c6080830185611c44565b905082606083015295945050505050565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a083015261218860c0830184611c44565b9897505050505050505056fea164736f6c634300080f000a"; +- hex"60806040526004361061018b5760003560e01c80636425666b116100d6578063b1b1b2091161007f578063d764ad0b11610059578063d764ad0b1461049b578063db505d80146104ae578063ecc70428146104db57600080fd5b8063b1b1b2091461042b578063b28ade251461045b578063c0c53b8b1461047b57600080fd5b80638cbeeef2116100b05780638cbeeef2146102d05780639fce812c146103d0578063a4e7f8bd146103fb57600080fd5b80636425666b146103775780636e296e45146103a457806383a74074146103b957600080fd5b80633dbb202b1161013857806354fd4d501161011257806354fd4d50146102e65780635644cfdf1461033c5780635c975abb1461035257600080fd5b80633dbb202b146102935780633f827a5a146102a85780634c1d6a69146102d057600080fd5b80632828d7e8116101695780632828d7e81461022457806333d7e2bd1461023957806335e80ab31461026657600080fd5b8063028f85f7146101905780630c568498146101c35780630ff754ea146101d8575b600080fd5b34801561019c57600080fd5b506101a5601081565b60405167ffffffffffffffff90911681526020015b60405180910390f35b3480156101cf57600080fd5b506101a5603f81565b3480156101e457600080fd5b5060fc5473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101ba565b34801561023057600080fd5b506101a5604081565b34801561024557600080fd5b5060fd546101ff9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561027257600080fd5b5060fb546101ff9073ffffffffffffffffffffffffffffffffffffffff1681565b6102a66102a1366004611bdd565b610540565b005b3480156102b457600080fd5b506102bd600181565b60405161ffff90911681526020016101ba565b3480156102dc57600080fd5b506101a5619c4081565b3480156102f257600080fd5b5061032f6040518060400160405280600581526020017f322e342e3000000000000000000000000000000000000000000000000000000081525081565b6040516101ba9190611caf565b34801561034857600080fd5b506101a561138881565b34801561035e57600080fd5b5061036761083d565b60405190151581526020016101ba565b34801561038357600080fd5b5060fc546101ff9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156103b057600080fd5b506101ff6108d6565b3480156103c557600080fd5b506101a562030d4081565b3480156103dc57600080fd5b5060cf5473ffffffffffffffffffffffffffffffffffffffff166101ff565b34801561040757600080fd5b50610367610416366004611cc9565b60ce6020526000908152604090205460ff1681565b34801561043757600080fd5b50610367610446366004611cc9565b60cb6020526000908152604090205460ff1681565b34801561046757600080fd5b506101a5610476366004611ce2565b6109bd565b34801561048757600080fd5b506102a6610496366004611d36565b610a2b565b6102a66104a9366004611d81565b610ca2565b3480156104ba57600080fd5b5060cf546101ff9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156104e757600080fd5b5061053260cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b6040519081526020016101ba565b6105486115d3565b156105e05734156105e0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f43726f7373446f6d61696e4d657373656e6765723a2063616e6e6f742073656e60448201527f642076616c7565207769746820637573746f6d2067617320746f6b656e00000060648201526084015b60405180910390fd5b60cf546107129073ffffffffffffffffffffffffffffffffffffffff166106088585856109bd565b347fd764ad0b0000000000000000000000000000000000000000000000000000000061067460cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b338a34898c8c6040516024016106909796959493929190611e50565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611612565b8373ffffffffffffffffffffffffffffffffffffffff167fcb0f7ffd78f9aee47a248fae8db181db6eee833039123e026dcbff529522e52a33858561079760cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b866040516107a9959493929190611eaf565b60405180910390a260405134815233907f8ebb2ec2465bdb2a06a66fc37a0963af8a2a6a1479d81d56fdb8cbb98096d5469060200160405180910390a2505060cd80547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808216600101167fffff0000000000000000000000000000000000000000000000000000000000009091161790555050565b60fb54604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa1580156108ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108d19190611efd565b905090565b60cc5460009073ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2153016109a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f43726f7373446f6d61696e4d657373656e6765723a2078446f6d61696e4d657360448201527f7361676553656e646572206973206e6f7420736574000000000000000000000060648201526084016105d7565b5060cc5473ffffffffffffffffffffffffffffffffffffffff1690565b6000611388619c4080603f6109d9604063ffffffff8816611f4e565b6109e39190611f7e565b6109ee601088611f4e565b6109fb9062030d40611fcc565b610a059190611fcc565b610a0f9190611fcc565b610a199190611fcc565b610a239190611fcc565b949350505050565b6000547501000000000000000000000000000000000000000000900460ff1615808015610a76575060005460017401000000000000000000000000000000000000000090910460ff16105b80610aa85750303b158015610aa8575060005474010000000000000000000000000000000000000000900460ff166001145b610b34576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016105d7565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790558015610bba57600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000001790555b60fb805473ffffffffffffffffffffffffffffffffffffffff8087167fffffffffffffffffffffffff00000000000000000000000000000000000000009283161790925560fc805486841690831617905560fd805492851692909116919091179055610c397342000000000000000000000000000000000000076116ab565b8015610c9c57600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b610caa61083d565b15610d11576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f43726f7373446f6d61696e4d657373656e6765723a207061757365640000000060448201526064016105d7565b60f087901c60028110610dcc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f43726f7373446f6d61696e4d657373656e6765723a206f6e6c7920766572736960448201527f6f6e2030206f722031206d657373616765732061726520737570706f7274656460648201527f20617420746869732074696d6500000000000000000000000000000000000000608482015260a4016105d7565b8061ffff16600003610ec1576000610e1d878986868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508f92506117e7915050565b600081815260cb602052604090205490915060ff1615610ebf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f43726f7373446f6d61696e4d657373656e6765723a206c65676163792077697460448201527f6864726177616c20616c72656164792072656c6179656400000000000000000060648201526084016105d7565b505b6000610f07898989898989898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061180692505050565b9050610f11611829565b15610f4957853414610f2557610f25611ff8565b600081815260ce602052604090205460ff1615610f4457610f44611ff8565b61109b565b3415610ffd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605060248201527f43726f7373446f6d61696e4d657373656e6765723a2076616c7565206d75737460448201527f206265207a65726f20756e6c657373206d6573736167652069732066726f6d2060648201527f612073797374656d206164647265737300000000000000000000000000000000608482015260a4016105d7565b600081815260ce602052604090205460ff1661109b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520636160448201527f6e6e6f74206265207265706c617965640000000000000000000000000000000060648201526084016105d7565b6110a487611905565b15611157576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f43726f7373446f6d61696e4d657373656e6765723a2063616e6e6f742073656e60448201527f64206d65737361676520746f20626c6f636b65642073797374656d206164647260648201527f6573730000000000000000000000000000000000000000000000000000000000608482015260a4016105d7565b600081815260cb602052604090205460ff16156111f6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520686160448201527f7320616c7265616479206265656e2072656c617965640000000000000000000060648201526084016105d7565b61121785611208611388619c40611fcc565b67ffffffffffffffff1661194b565b158061123d575060cc5473ffffffffffffffffffffffffffffffffffffffff1661dead14155b1561135657600081815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555182917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff320161134f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d6573736167650000000000000000000000000000000000000060648201526084016105d7565b50506115ae565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8a1617905560006113e788619c405a6113aa9190612027565b8988888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061196992505050565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790559050801561149d57600082815260cb602052604090205460ff161561143a5761143a611ff8565b600082815260cb602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f4641df4a962071e12719d8c8c8e5ac7fc4d97b927346a3d7a335b1f7517e133c91a26115aa565b600082815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff32016115aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d6573736167650000000000000000000000000000000000000060648201526084016105d7565b5050505b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6000806115de611981565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b60fc546040517fe9e05c4200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063e9e05c4290849061167390889083908990600090899060040161203e565b6000604051808303818588803b15801561168c57600080fd5b505af11580156116a0573d6000803e3d6000fd5b505050505050505050565b6000547501000000000000000000000000000000000000000000900460ff16611756576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016105d7565b60cc5473ffffffffffffffffffffffffffffffffffffffff166117a05760cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790555b60cf80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60006117f585858585611a1e565b805190602001209050949350505050565b6000611816878787878787611ab7565b8051906020012090509695505050505050565b60fc5460009073ffffffffffffffffffffffffffffffffffffffff16331480156108d1575060cf5460fc54604080517f9bf62d82000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9384169390921691639bf62d82916004808201926020929091908290030181865afa1580156118c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118e99190612096565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b600073ffffffffffffffffffffffffffffffffffffffff8216301480611945575060fc5473ffffffffffffffffffffffffffffffffffffffff8381169116145b92915050565b600080603f83619c4001026040850201603f5a021015949350505050565b6000806000835160208501868989f195945050505050565b60fd54604080517f4397dfef0000000000000000000000000000000000000000000000000000000081528151600093849373ffffffffffffffffffffffffffffffffffffffff90911692634397dfef92600480830193928290030181865afa1580156119f1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a1591906120b3565b90939092509050565b606084848484604051602401611a3794939291906120f3565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fcbd4ece9000000000000000000000000000000000000000000000000000000001790529050949350505050565b6060868686868686604051602401611ad49695949392919061213d565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd764ad0b0000000000000000000000000000000000000000000000000000000017905290509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff81168114611b7857600080fd5b50565b60008083601f840112611b8d57600080fd5b50813567ffffffffffffffff811115611ba557600080fd5b602083019150836020828501011115611bbd57600080fd5b9250929050565b803563ffffffff81168114611bd857600080fd5b919050565b60008060008060608587031215611bf357600080fd5b8435611bfe81611b56565b9350602085013567ffffffffffffffff811115611c1a57600080fd5b611c2687828801611b7b565b9094509250611c39905060408601611bc4565b905092959194509250565b6000815180845260005b81811015611c6a57602081850181015186830182015201611c4e565b81811115611c7c576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611cc26020830184611c44565b9392505050565b600060208284031215611cdb57600080fd5b5035919050565b600080600060408486031215611cf757600080fd5b833567ffffffffffffffff811115611d0e57600080fd5b611d1a86828701611b7b565b9094509250611d2d905060208501611bc4565b90509250925092565b600080600060608486031215611d4b57600080fd5b8335611d5681611b56565b92506020840135611d6681611b56565b91506040840135611d7681611b56565b809150509250925092565b600080600080600080600060c0888a031215611d9c57600080fd5b873596506020880135611dae81611b56565b95506040880135611dbe81611b56565b9450606088013593506080880135925060a088013567ffffffffffffffff811115611de857600080fd5b611df48a828b01611b7b565b989b979a50959850939692959293505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b878152600073ffffffffffffffffffffffffffffffffffffffff808916602084015280881660408401525085606083015263ffffffff8516608083015260c060a0830152611ea260c083018486611e07565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff86168152608060208201526000611edf608083018688611e07565b905083604083015263ffffffff831660608301529695505050505050565b600060208284031215611f0f57600080fd5b81518015158114611cc257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600067ffffffffffffffff80831681851681830481118215151615611f7557611f75611f1f565b02949350505050565b600067ffffffffffffffff80841680611fc0577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b92169190910492915050565b600067ffffffffffffffff808316818516808303821115611fef57611fef611f1f565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b60008282101561203957612039611f1f565b500390565b73ffffffffffffffffffffffffffffffffffffffff8616815284602082015267ffffffffffffffff84166040820152821515606082015260a06080820152600061208b60a0830184611c44565b979650505050505050565b6000602082840312156120a857600080fd5b8151611cc281611b56565b600080604083850312156120c657600080fd5b82516120d181611b56565b602084015190925060ff811681146120e857600080fd5b809150509250929050565b600073ffffffffffffffffffffffffffffffffffffffff80871683528086166020840152506080604083015261212c6080830185611c44565b905082606083015295945050505050565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a083015261218860c0830184611c44565b9897505050505050505056fea164736f6c634300080f000a"; ++ hex"60806040526004361061018b5760003560e01c80636425666b116100d6578063b1b1b2091161007f578063d764ad0b11610059578063d764ad0b1461049b578063db505d80146104ae578063ecc70428146104db57600080fd5b8063b1b1b2091461042b578063b28ade251461045b578063c0c53b8b1461047b57600080fd5b80638cbeeef2116100b05780638cbeeef2146102d05780639fce812c146103d0578063a4e7f8bd146103fb57600080fd5b80636425666b146103775780636e296e45146103a457806383a74074146103b957600080fd5b80633dbb202b1161013857806354fd4d501161011257806354fd4d50146102e65780635644cfdf1461033c5780635c975abb1461035257600080fd5b80633dbb202b146102935780633f827a5a146102a85780634c1d6a69146102d057600080fd5b80632828d7e8116101695780632828d7e81461022457806333d7e2bd1461023957806335e80ab31461026657600080fd5b8063028f85f7146101905780630c568498146101c35780630ff754ea146101d8575b600080fd5b34801561019c57600080fd5b506101a5601081565b60405167ffffffffffffffff90911681526020015b60405180910390f35b3480156101cf57600080fd5b506101a5603f81565b3480156101e457600080fd5b5060fc5473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101ba565b34801561023057600080fd5b506101a5604081565b34801561024557600080fd5b5060fd546101ff9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561027257600080fd5b5060fb546101ff9073ffffffffffffffffffffffffffffffffffffffff1681565b6102a66102a1366004611bdd565b610540565b005b3480156102b457600080fd5b506102bd600181565b60405161ffff90911681526020016101ba565b3480156102dc57600080fd5b506101a5619c4081565b3480156102f257600080fd5b5061032f6040518060400160405280600c81526020017f322e342e312d626574612e31000000000000000000000000000000000000000081525081565b6040516101ba9190611caf565b34801561034857600080fd5b506101a561138881565b34801561035e57600080fd5b5061036761083d565b60405190151581526020016101ba565b34801561038357600080fd5b5060fc546101ff9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156103b057600080fd5b506101ff6108d6565b3480156103c557600080fd5b506101a562030d4081565b3480156103dc57600080fd5b5060cf5473ffffffffffffffffffffffffffffffffffffffff166101ff565b34801561040757600080fd5b50610367610416366004611cc9565b60ce6020526000908152604090205460ff1681565b34801561043757600080fd5b50610367610446366004611cc9565b60cb6020526000908152604090205460ff1681565b34801561046757600080fd5b506101a5610476366004611ce2565b6109bd565b34801561048757600080fd5b506102a6610496366004611d36565b610a2b565b6102a66104a9366004611d81565b610ca2565b3480156104ba57600080fd5b5060cf546101ff9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156104e757600080fd5b5061053260cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b6040519081526020016101ba565b6105486115d3565b156105e05734156105e0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f43726f7373446f6d61696e4d657373656e6765723a2063616e6e6f742073656e60448201527f642076616c7565207769746820637573746f6d2067617320746f6b656e00000060648201526084015b60405180910390fd5b60cf546107129073ffffffffffffffffffffffffffffffffffffffff166106088585856109bd565b347fd764ad0b0000000000000000000000000000000000000000000000000000000061067460cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b338a34898c8c6040516024016106909796959493929190611e50565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611612565b8373ffffffffffffffffffffffffffffffffffffffff167fcb0f7ffd78f9aee47a248fae8db181db6eee833039123e026dcbff529522e52a33858561079760cd547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e010000000000000000000000000000000000000000000000000000000000001790565b866040516107a9959493929190611eaf565b60405180910390a260405134815233907f8ebb2ec2465bdb2a06a66fc37a0963af8a2a6a1479d81d56fdb8cbb98096d5469060200160405180910390a2505060cd80547dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808216600101167fffff0000000000000000000000000000000000000000000000000000000000009091161790555050565b60fb54604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa1580156108ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108d19190611efd565b905090565b60cc5460009073ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2153016109a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f43726f7373446f6d61696e4d657373656e6765723a2078446f6d61696e4d657360448201527f7361676553656e646572206973206e6f7420736574000000000000000000000060648201526084016105d7565b5060cc5473ffffffffffffffffffffffffffffffffffffffff1690565b6000611388619c4080603f6109d9604063ffffffff8816611f4e565b6109e39190611f7e565b6109ee601088611f4e565b6109fb9062030d40611fcc565b610a059190611fcc565b610a0f9190611fcc565b610a199190611fcc565b610a239190611fcc565b949350505050565b6000547501000000000000000000000000000000000000000000900460ff1615808015610a76575060005460017401000000000000000000000000000000000000000090910460ff16105b80610aa85750303b158015610aa8575060005474010000000000000000000000000000000000000000900460ff166001145b610b34576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016105d7565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790558015610bba57600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000001790555b60fb805473ffffffffffffffffffffffffffffffffffffffff8087167fffffffffffffffffffffffff00000000000000000000000000000000000000009283161790925560fc805486841690831617905560fd805492851692909116919091179055610c397342000000000000000000000000000000000000076116ab565b8015610c9c57600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b610caa61083d565b15610d11576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f43726f7373446f6d61696e4d657373656e6765723a207061757365640000000060448201526064016105d7565b60f087901c60028110610dcc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604d60248201527f43726f7373446f6d61696e4d657373656e6765723a206f6e6c7920766572736960448201527f6f6e2030206f722031206d657373616765732061726520737570706f7274656460648201527f20617420746869732074696d6500000000000000000000000000000000000000608482015260a4016105d7565b8061ffff16600003610ec1576000610e1d878986868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508f92506117e7915050565b600081815260cb602052604090205490915060ff1615610ebf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f43726f7373446f6d61696e4d657373656e6765723a206c65676163792077697460448201527f6864726177616c20616c72656164792072656c6179656400000000000000000060648201526084016105d7565b505b6000610f07898989898989898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061180692505050565b9050610f11611829565b15610f4957853414610f2557610f25611ff8565b600081815260ce602052604090205460ff1615610f4457610f44611ff8565b61109b565b3415610ffd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605060248201527f43726f7373446f6d61696e4d657373656e6765723a2076616c7565206d75737460448201527f206265207a65726f20756e6c657373206d6573736167652069732066726f6d2060648201527f612073797374656d206164647265737300000000000000000000000000000000608482015260a4016105d7565b600081815260ce602052604090205460ff1661109b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520636160448201527f6e6e6f74206265207265706c617965640000000000000000000000000000000060648201526084016105d7565b6110a487611905565b15611157576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f43726f7373446f6d61696e4d657373656e6765723a2063616e6e6f742073656e60448201527f64206d65737361676520746f20626c6f636b65642073797374656d206164647260648201527f6573730000000000000000000000000000000000000000000000000000000000608482015260a4016105d7565b600081815260cb602052604090205460ff16156111f6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f43726f7373446f6d61696e4d657373656e6765723a206d65737361676520686160448201527f7320616c7265616479206265656e2072656c617965640000000000000000000060648201526084016105d7565b61121785611208611388619c40611fcc565b67ffffffffffffffff1661194b565b158061123d575060cc5473ffffffffffffffffffffffffffffffffffffffff1661dead14155b1561135657600081815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555182917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff320161134f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d6573736167650000000000000000000000000000000000000060648201526084016105d7565b50506115ae565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8a1617905560006113e788619c405a6113aa9190612027565b8988888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061196992505050565b60cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790559050801561149d57600082815260cb602052604090205460ff161561143a5761143a611ff8565b600082815260cb602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f4641df4a962071e12719d8c8c8e5ac7fc4d97b927346a3d7a335b1f7517e133c91a26115aa565b600082815260ce602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555183917f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f91a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff32016115aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f43726f7373446f6d61696e4d657373656e6765723a206661696c656420746f2060448201527f72656c6179206d6573736167650000000000000000000000000000000000000060648201526084016105d7565b5050505b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6000806115de611981565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b60fc546040517fe9e05c4200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063e9e05c4290849061167390889083908990600090899060040161203e565b6000604051808303818588803b15801561168c57600080fd5b505af11580156116a0573d6000803e3d6000fd5b505050505050505050565b6000547501000000000000000000000000000000000000000000900460ff16611756576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016105d7565b60cc5473ffffffffffffffffffffffffffffffffffffffff166117a05760cc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790555b60cf80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60006117f585858585611a1e565b805190602001209050949350505050565b6000611816878787878787611ab7565b8051906020012090509695505050505050565b60fc5460009073ffffffffffffffffffffffffffffffffffffffff16331480156108d1575060cf5460fc54604080517f9bf62d82000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9384169390921691639bf62d82916004808201926020929091908290030181865afa1580156118c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118e99190612096565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b600073ffffffffffffffffffffffffffffffffffffffff8216301480611945575060fc5473ffffffffffffffffffffffffffffffffffffffff8381169116145b92915050565b600080603f83619c4001026040850201603f5a021015949350505050565b6000806000835160208501868989f195945050505050565b60fd54604080517f4397dfef0000000000000000000000000000000000000000000000000000000081528151600093849373ffffffffffffffffffffffffffffffffffffffff90911692634397dfef92600480830193928290030181865afa1580156119f1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a1591906120b3565b90939092509050565b606084848484604051602401611a3794939291906120f3565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fcbd4ece9000000000000000000000000000000000000000000000000000000001790529050949350505050565b6060868686868686604051602401611ad49695949392919061213d565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd764ad0b0000000000000000000000000000000000000000000000000000000017905290509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff81168114611b7857600080fd5b50565b60008083601f840112611b8d57600080fd5b50813567ffffffffffffffff811115611ba557600080fd5b602083019150836020828501011115611bbd57600080fd5b9250929050565b803563ffffffff81168114611bd857600080fd5b919050565b60008060008060608587031215611bf357600080fd5b8435611bfe81611b56565b9350602085013567ffffffffffffffff811115611c1a57600080fd5b611c2687828801611b7b565b9094509250611c39905060408601611bc4565b905092959194509250565b6000815180845260005b81811015611c6a57602081850181015186830182015201611c4e565b81811115611c7c576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611cc26020830184611c44565b9392505050565b600060208284031215611cdb57600080fd5b5035919050565b600080600060408486031215611cf757600080fd5b833567ffffffffffffffff811115611d0e57600080fd5b611d1a86828701611b7b565b9094509250611d2d905060208501611bc4565b90509250925092565b600080600060608486031215611d4b57600080fd5b8335611d5681611b56565b92506020840135611d6681611b56565b91506040840135611d7681611b56565b809150509250925092565b600080600080600080600060c0888a031215611d9c57600080fd5b873596506020880135611dae81611b56565b95506040880135611dbe81611b56565b9450606088013593506080880135925060a088013567ffffffffffffffff811115611de857600080fd5b611df48a828b01611b7b565b989b979a50959850939692959293505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b878152600073ffffffffffffffffffffffffffffffffffffffff808916602084015280881660408401525085606083015263ffffffff8516608083015260c060a0830152611ea260c083018486611e07565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff86168152608060208201526000611edf608083018688611e07565b905083604083015263ffffffff831660608301529695505050505050565b600060208284031215611f0f57600080fd5b81518015158114611cc257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600067ffffffffffffffff80831681851681830481118215151615611f7557611f75611f1f565b02949350505050565b600067ffffffffffffffff80841680611fc0577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b92169190910492915050565b600067ffffffffffffffff808316818516808303821115611fef57611fef611f1f565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b60008282101561203957612039611f1f565b500390565b73ffffffffffffffffffffffffffffffffffffffff8616815284602082015267ffffffffffffffff84166040820152821515606082015260a06080820152600061208b60a0830184611c44565b979650505050505050565b6000602082840312156120a857600080fd5b8151611cc281611b56565b600080604083850312156120c657600080fd5b82516120d181611b56565b602084015190925060ff811681146120e857600080fd5b809150509250929050565b600073ffffffffffffffffffffffffffffffffffffffff80871683528086166020840152506080604083015261212c6080830185611c44565b905082606083015295945050505050565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a083015261218860c0830184611c44565b9897505050505050505056fea164736f6c634300080f000a"; bytes internal constant optimismMintableERC20FactoryCode = - hex"60806040523480156200001157600080fd5b5060043610620000935760003560e01c8063c4d66de81162000062578063c4d66de81462000175578063ce5ac90f146200018e578063e78cea9214620001a5578063ee9a31a214620001c657600080fd5b8063316b3739146200009857806354fd4d5014620000fb578063896f93d114620001475780638cf0629c146200015e575b600080fd5b620000d1620000a936600462000652565b60026020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b620001386040518060400160405280600681526020017f312e31302e30000000000000000000000000000000000000000000000000000081525081565b604051620000f29190620006e5565b620000d162000158366004620007dc565b620001e5565b620000d16200016f36600462000859565b620001fc565b6200018c6200018636600462000652565b6200041b565b005b620000d16200019f366004620007dc565b620005ed565b600154620000d19073ffffffffffffffffffffffffffffffffffffffff1681565b60015473ffffffffffffffffffffffffffffffffffffffff16620000d1565b6000620001f4848484620005ed565b949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8516620002a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d4d696e7461626c654552433230466163746f72793a206d7560448201527f73742070726f766964652072656d6f746520746f6b656e20616464726573730060648201526084015b60405180910390fd5b600085858585604051602001620002c29493929190620008f0565b604051602081830303815290604052805190602001209050600081600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168888888860405162000312906200061a565b620003229594939291906200094a565b8190604051809103906000f590508015801562000343573d6000803e3d6000fd5b5073ffffffffffffffffffffffffffffffffffffffff81811660008181526002602052604080822080547fffffffffffffffffffffffff000000000000000000000000000000000000000016948d1694851790555193945090927fceeb8e7d520d7f3b65fc11a262b91066940193b05d4f93df07cfdced0eb551cf9190a360405133815273ffffffffffffffffffffffffffffffffffffffff80891691908316907f52fe89dd5930f343d25650b62fd367bae47088bcddffd2a88350a6ecdd620cdb9060200160405180910390a39695505050505050565b600054610100900460ff16158080156200043c5750600054600160ff909116105b80620004585750303b15801562000458575060005460ff166001145b620004e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016200029e565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156200054557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84161790558015620005e957600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6000620001f48484846012620001fc565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b61178a80620009b083390190565b803573ffffffffffffffffffffffffffffffffffffffff811681146200064d57600080fd5b919050565b6000602082840312156200066557600080fd5b620006708262000628565b9392505050565b6000815180845260005b818110156200069f5760208185018101518683018201520162000681565b81811115620006b2576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600062000670602083018462000677565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126200073b57600080fd5b813567ffffffffffffffff80821115620007595762000759620006fa565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715620007a257620007a2620006fa565b81604052838152866020858801011115620007bc57600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600060608486031215620007f257600080fd5b620007fd8462000628565b9250602084013567ffffffffffffffff808211156200081b57600080fd5b620008298783880162000729565b935060408601359150808211156200084057600080fd5b506200084f8682870162000729565b9150509250925092565b600080600080608085870312156200087057600080fd5b6200087b8562000628565b9350602085013567ffffffffffffffff808211156200089957600080fd5b620008a78883890162000729565b94506040870135915080821115620008be57600080fd5b50620008cd8782880162000729565b925050606085013560ff81168114620008e557600080fd5b939692955090935050565b73ffffffffffffffffffffffffffffffffffffffff8516815260806020820152600062000921608083018662000677565b828103604084015262000935818662000677565b91505060ff8316606083015295945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808816835280871660208401525060a060408301526200098560a083018662000677565b828103606084015262000999818662000677565b91505060ff83166080830152969550505050505056fe60e06040523480156200001157600080fd5b506040516200178a3803806200178a833981016040819052620000349162000163565b828260036200004483826200029e565b5060046200005382826200029e565b5050506001600160a01b039384166080529390921660a052505060ff1660c0526200036a565b80516001600160a01b03811681146200009157600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620000be57600080fd5b81516001600160401b0380821115620000db57620000db62000096565b604051601f8301601f19908116603f0116810190828211818310171562000106576200010662000096565b816040528381526020925086838588010111156200012357600080fd5b600091505b8382101562000147578582018301518183018401529082019062000128565b83821115620001595760008385830101525b9695505050505050565b600080600080600060a086880312156200017c57600080fd5b620001878662000079565b9450620001976020870162000079565b60408701519094506001600160401b0380821115620001b557600080fd5b620001c389838a01620000ac565b94506060880151915080821115620001da57600080fd5b50620001e988828901620000ac565b925050608086015160ff811681146200020157600080fd5b809150509295509295909350565b600181811c908216806200022457607f821691505b6020821081036200024557634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200029957600081815260208120601f850160051c81016020861015620002745750805b601f850160051c820191505b81811015620002955782815560010162000280565b5050505b505050565b81516001600160401b03811115620002ba57620002ba62000096565b620002d281620002cb84546200020f565b846200024b565b602080601f8311600181146200030a5760008415620002f15750858301515b600019600386901b1c1916600185901b17855562000295565b600085815260208120601f198616915b828110156200033b578886015182559484019460019091019084016200031a565b50858210156200035a5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c0516113d4620003b6600039600061024401526000818161034b015281816103e001528181610625015261075c0152600081816101a9015261037101526113d46000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063ae1f6aaf1161008c578063dd62ed3e11610066578063dd62ed3e14610395578063e78cea9214610349578063ee9a31a2146103db57600080fd5b8063ae1f6aaf14610349578063c01e1bd61461036f578063d6c0b2c41461036f57600080fd5b80639dc29fac116100bd5780639dc29fac14610310578063a457c2d714610323578063a9059cbb1461033657600080fd5b806370a08231146102d257806395d89b411461030857600080fd5b806323b872dd1161012f5780633950935111610114578063395093511461026e57806340c10f191461028157806354fd4d501461029657600080fd5b806323b872dd1461022a578063313ce5671461023d57600080fd5b806306fdde031161016057806306fdde03146101f0578063095ea7b31461020557806318160ddd1461021857600080fd5b806301ffc9a71461017c578063033964be146101a4575b600080fd5b61018f61018a36600461117d565b610402565b60405190151581526020015b60405180910390f35b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b6101f86104f3565b60405161019b91906111c6565b61018f610213366004611262565b610585565b6002545b60405190815260200161019b565b61018f61023836600461128c565b61059d565b60405160ff7f000000000000000000000000000000000000000000000000000000000000000016815260200161019b565b61018f61027c366004611262565b6105c1565b61029461028f366004611262565b61060d565b005b6101f86040518060400160405280600581526020017f312e332e3000000000000000000000000000000000000000000000000000000081525081565b61021c6102e03660046112c8565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101f8610735565b61029461031e366004611262565b610744565b61018f610331366004611262565b61085b565b61018f610344366004611262565b61092c565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b61021c6103a33660046112e3565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007f1d1d8b63000000000000000000000000000000000000000000000000000000007fec4fc8e3000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000085168314806104bb57507fffffffff00000000000000000000000000000000000000000000000000000000858116908316145b806104ea57507fffffffff00000000000000000000000000000000000000000000000000000000858116908216145b95945050505050565b60606003805461050290611316565b80601f016020809104026020016040519081016040528092919081815260200182805461052e90611316565b801561057b5780601f106105505761010080835404028352916020019161057b565b820191906000526020600020905b81548152906001019060200180831161055e57829003601f168201915b5050505050905090565b60003361059381858561093a565b5060019392505050565b6000336105ab858285610aee565b6105b6858585610bc5565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906105939082908690610608908790611398565b61093a565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146106d7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084015b60405180910390fd5b6106e18282610e78565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d41213968858260405161072991815260200190565b60405180910390a25050565b60606004805461050290611316565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610809576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084016106ce565b6108138282610f98565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca58260405161072991815260200190565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091908381101561091f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084016106ce565b6105b6828686840361093a565b600033610593818585610bc5565b73ffffffffffffffffffffffffffffffffffffffff83166109dc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f726573730000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216610a7f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f737300000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610bbf5781811015610bb2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016106ce565b610bbf848484840361093a565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610c68576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216610d0b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f657373000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610dc1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e6365000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260208190526040808220858503905591851681529081208054849290610e05908490611398565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610e6b91815260200190565b60405180910390a3610bbf565b73ffffffffffffffffffffffffffffffffffffffff8216610ef5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016106ce565b8060026000828254610f079190611398565b909155505073ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604081208054839290610f41908490611398565b909155505060405181815273ffffffffffffffffffffffffffffffffffffffff8316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff821661103b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f730000000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260208190526040902054818110156110f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f636500000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260208190526040812083830390556002805484929061112d9084906113b0565b909155505060405182815260009073ffffffffffffffffffffffffffffffffffffffff8516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610ae1565b60006020828403121561118f57600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146111bf57600080fd5b9392505050565b600060208083528351808285015260005b818110156111f3578581018301518582016040015282016111d7565b81811115611205576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461125d57600080fd5b919050565b6000806040838503121561127557600080fd5b61127e83611239565b946020939093013593505050565b6000806000606084860312156112a157600080fd5b6112aa84611239565b92506112b860208501611239565b9150604084013590509250925092565b6000602082840312156112da57600080fd5b6111bf82611239565b600080604083850312156112f657600080fd5b6112ff83611239565b915061130d60208401611239565b90509250929050565b600181811c9082168061132a57607f821691505b602082108103611363577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156113ab576113ab611369565b500190565b6000828210156113c2576113c2611369565b50039056fea164736f6c634300080f000aa164736f6c634300080f000a"; -+ hex"60806040523480156200001157600080fd5b5060043610620000935760003560e01c8063c4d66de81162000062578063c4d66de81462000175578063ce5ac90f146200018e578063e78cea9214620001a5578063ee9a31a214620001c657600080fd5b8063316b3739146200009857806354fd4d5014620000fb578063896f93d114620001475780638cf0629c146200015e575b600080fd5b620000d1620000a936600462000652565b60026020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b620001386040518060400160405280600681526020017f312e31302e30000000000000000000000000000000000000000000000000000081525081565b604051620000f29190620006e5565b620000d162000158366004620007dc565b620001e5565b620000d16200016f36600462000859565b620001fc565b6200018c6200018636600462000652565b6200041b565b005b620000d16200019f366004620007dc565b620005ed565b600154620000d19073ffffffffffffffffffffffffffffffffffffffff1681565b60015473ffffffffffffffffffffffffffffffffffffffff16620000d1565b6000620001f4848484620005ed565b949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8516620002a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d4d696e7461626c654552433230466163746f72793a206d7560448201527f73742070726f766964652072656d6f746520746f6b656e20616464726573730060648201526084015b60405180910390fd5b600085858585604051602001620002c29493929190620008f0565b604051602081830303815290604052805190602001209050600081600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168888888860405162000312906200061a565b620003229594939291906200094a565b8190604051809103906000f590508015801562000343573d6000803e3d6000fd5b5073ffffffffffffffffffffffffffffffffffffffff81811660008181526002602052604080822080547fffffffffffffffffffffffff000000000000000000000000000000000000000016948d1694851790555193945090927fceeb8e7d520d7f3b65fc11a262b91066940193b05d4f93df07cfdced0eb551cf9190a360405133815273ffffffffffffffffffffffffffffffffffffffff80891691908316907f52fe89dd5930f343d25650b62fd367bae47088bcddffd2a88350a6ecdd620cdb9060200160405180910390a39695505050505050565b600054610100900460ff16158080156200043c5750600054600160ff909116105b80620004585750303b15801562000458575060005460ff166001145b620004e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016200029e565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156200054557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84161790558015620005e957600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6000620001f48484846012620001fc565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b611be480620009b083390190565b803573ffffffffffffffffffffffffffffffffffffffff811681146200064d57600080fd5b919050565b6000602082840312156200066557600080fd5b620006708262000628565b9392505050565b6000815180845260005b818110156200069f5760208185018101518683018201520162000681565b81811115620006b2576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600062000670602083018462000677565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126200073b57600080fd5b813567ffffffffffffffff80821115620007595762000759620006fa565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715620007a257620007a2620006fa565b81604052838152866020858801011115620007bc57600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600060608486031215620007f257600080fd5b620007fd8462000628565b9250602084013567ffffffffffffffff808211156200081b57600080fd5b620008298783880162000729565b935060408601359150808211156200084057600080fd5b506200084f8682870162000729565b9150509250925092565b600080600080608085870312156200087057600080fd5b6200087b8562000628565b9350602085013567ffffffffffffffff808211156200089957600080fd5b620008a78883890162000729565b94506040870135915080821115620008be57600080fd5b50620008cd8782880162000729565b925050606085013560ff81168114620008e557600080fd5b939692955090935050565b73ffffffffffffffffffffffffffffffffffffffff8516815260806020820152600062000921608083018662000677565b828103604084015262000935818662000677565b91505060ff8316606083015295945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808816835280871660208401525060a060408301526200098560a083018662000677565b828103606084015262000999818662000677565b91505060ff83166080830152969550505050505056fe60e06040523480156200001157600080fd5b5060405162001be438038062001be4833981016040819052620000349162000163565b828260036200004483826200029e565b5060046200005382826200029e565b5050506001600160a01b039384166080529390921660a052505060ff1660c0526200036a565b80516001600160a01b03811681146200009157600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620000be57600080fd5b81516001600160401b0380821115620000db57620000db62000096565b604051601f8301601f19908116603f0116810190828211818310171562000106576200010662000096565b816040528381526020925086838588010111156200012357600080fd5b600091505b8382101562000147578582018301518183018401529082019062000128565b83821115620001595760008385830101525b9695505050505050565b600080600080600060a086880312156200017c57600080fd5b620001878662000079565b9450620001976020870162000079565b60408701519094506001600160401b0380821115620001b557600080fd5b620001c389838a01620000ac565b94506060880151915080821115620001da57600080fd5b50620001e988828901620000ac565b925050608086015160ff811681146200020157600080fd5b809150509295509295909350565b600181811c908216806200022457607f821691505b6020821081036200024557634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200029957600081815260208120601f850160051c81016020861015620002745750805b601f850160051c820191505b81811015620002955782815560010162000280565b5050505b505050565b81516001600160401b03811115620002ba57620002ba62000096565b620002d281620002cb84546200020f565b846200024b565b602080601f8311600181146200030a5760008415620002f15750858301515b600019600386901b1c1916600185901b17855562000295565b600085815260208120601f198616915b828110156200033b578886015182559484019460019091019084016200031a565b50858210156200035a5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05161182e620003b6600039600061027a0152600081816103a50152818161043a015281816107e70152610a1f0152600081816101ca01526103cb015261182e6000f3fe608060405234801561001057600080fd5b50600436106101985760003560e01c80636a30b253116100e3578063ae1f6aaf1161008c578063dd62ed3e11610066578063dd62ed3e146103ef578063e78cea92146103a3578063ee9a31a21461043557600080fd5b8063ae1f6aaf146103a3578063c01e1bd6146103c9578063d6c0b2c4146103c957600080fd5b80639dc29fac116100bd5780639dc29fac1461036a578063a457c2d71461037d578063a9059cbb1461039057600080fd5b80636a30b2531461031957806370a082311461032c57806395d89b411461036257600080fd5b80632e0f98ad1161014557806340c10f191161011f57806340c10f19146102b757806354fd4d50146102ca57806358cf96721461030657600080fd5b80632e0f98ad1461025e578063313ce5671461027357806339509351146102a457600080fd5b8063095ea7b311610176578063095ea7b31461022657806318160ddd1461023957806323b872dd1461024b57600080fd5b806301ffc9a71461019d578063033964be146101c557806306fdde0314610211575b600080fd5b6101b06101ab366004611440565b61045c565b60405190151581526020015b60405180910390f35b6101ec7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101bc565b61021961054d565b6040516101bc9190611489565b6101b0610234366004611525565b6105df565b6002545b6040519081526020016101bc565b6101b061025936600461154f565b6105f7565b61027161026c3660046115d7565b61061b565b005b60405160ff7f00000000000000000000000000000000000000000000000000000000000000001681526020016101bc565b6101b06102b2366004611525565b610783565b6102716102c5366004611525565b6107cf565b6102196040518060400160405280600581526020017f312e332e3000000000000000000000000000000000000000000000000000000081525081565b610271610314366004611525565b6108f2565b610271610327366004611643565b610968565b61023d61033a3660046116bb565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6102196109f8565b610271610378366004611525565b610a07565b6101b061038b366004611525565b610b1e565b6101b061039e366004611525565b610bef565b7f00000000000000000000000000000000000000000000000000000000000000006101ec565b7f00000000000000000000000000000000000000000000000000000000000000006101ec565b61023d6103fd3660046116d6565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101ec7f000000000000000000000000000000000000000000000000000000000000000081565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007f1d1d8b63000000000000000000000000000000000000000000000000000000007fec4fc8e3000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000851683148061051557507fffffffff00000000000000000000000000000000000000000000000000000000858116908316145b8061054457507fffffffff00000000000000000000000000000000000000000000000000000000858116908216145b95945050505050565b60606003805461055c90611709565b80601f016020809104026020016040519081016040528092919081815260200182805461058890611709565b80156105d55780601f106105aa576101008083540402835291602001916105d5565b820191906000526020600020905b8154815290600101906020018083116105b857829003601f168201915b5050505050905090565b6000336105ed818585610bfd565b5060019392505050565b600033610605858285610db1565b610610858585610e88565b506001949350505050565b3315610688576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f4f6e6c7920564d2063616e2063616c6c0000000000000000000000000000000060448201526064015b60405180910390fd5b828114610717576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526563697069656e747320616e6420616d6f756e7473206d757374206265207460448201527f68652073616d65206c656e6774682e0000000000000000000000000000000000606482015260840161067f565b60005b8381101561077c5761076a8585838181106107375761073761175c565b905060200201602081019061074c91906116bb565b84848481811061075e5761075e61175c565b9050602002013561113b565b80610774816117ba565b91505061071a565b5050505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906105ed90829086906107ca9087906117f2565b610bfd565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610894576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e000000000000000000000000606482015260840161067f565b61089e828261113b565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885826040516108e691815260200190565b60405180910390a25050565b331561095a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f4f6e6c7920564d2063616e2063616c6c00000000000000000000000000000000604482015260640161067f565b610964828261125b565b5050565b33156109d0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f4f6e6c7920564d2063616e2063616c6c00000000000000000000000000000000604482015260640161067f565b6109da888561113b565b6109e4878461113b565b6109ee858261113b565b5050505050505050565b60606004805461055c90611709565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610acc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e000000000000000000000000606482015260840161067f565b610ad6828261125b565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5826040516108e691815260200190565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919083811015610be2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f000000000000000000000000000000000000000000000000000000606482015260840161067f565b6106108286868403610bfd565b6000336105ed818585610e88565b73ffffffffffffffffffffffffffffffffffffffff8316610c9f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f7265737300000000000000000000000000000000000000000000000000000000606482015260840161067f565b73ffffffffffffffffffffffffffffffffffffffff8216610d42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f7373000000000000000000000000000000000000000000000000000000000000606482015260840161067f565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610e825781811015610e75576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e6365000000604482015260640161067f565b610e828484848403610bfd565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610f2b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f6472657373000000000000000000000000000000000000000000000000000000606482015260840161067f565b73ffffffffffffffffffffffffffffffffffffffff8216610fce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f6573730000000000000000000000000000000000000000000000000000000000606482015260840161067f565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015611084576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e63650000000000000000000000000000000000000000000000000000606482015260840161067f565b73ffffffffffffffffffffffffffffffffffffffff8085166000908152602081905260408082208585039055918516815290812080548492906110c89084906117f2565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161112e91815260200190565b60405180910390a3610e82565b73ffffffffffffffffffffffffffffffffffffffff82166111b8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640161067f565b80600260008282546111ca91906117f2565b909155505073ffffffffffffffffffffffffffffffffffffffff8216600090815260208190526040812080548392906112049084906117f2565b909155505060405181815273ffffffffffffffffffffffffffffffffffffffff8316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff82166112fe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f7300000000000000000000000000000000000000000000000000000000000000606482015260840161067f565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260208190526040902054818110156113b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f6365000000000000000000000000000000000000000000000000000000000000606482015260840161067f565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604081208383039055600280548492906113f090849061180a565b909155505060405182815260009073ffffffffffffffffffffffffffffffffffffffff8516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610da4565b60006020828403121561145257600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461148257600080fd5b9392505050565b600060208083528351808285015260005b818110156114b65785810183015185820160400152820161149a565b818111156114c8576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461152057600080fd5b919050565b6000806040838503121561153857600080fd5b611541836114fc565b946020939093013593505050565b60008060006060848603121561156457600080fd5b61156d846114fc565b925061157b602085016114fc565b9150604084013590509250925092565b60008083601f84011261159d57600080fd5b50813567ffffffffffffffff8111156115b557600080fd5b6020830191508360208260051b85010111156115d057600080fd5b9250929050565b600080600080604085870312156115ed57600080fd5b843567ffffffffffffffff8082111561160557600080fd5b6116118883890161158b565b9096509450602087013591508082111561162a57600080fd5b506116378782880161158b565b95989497509550505050565b600080600080600080600080610100898b03121561166057600080fd5b611669896114fc565b975061167760208a016114fc565b965061168560408a016114fc565b955061169360608a016114fc565b979a969950949760808101359660a0820135965060c0820135955060e0909101359350915050565b6000602082840312156116cd57600080fd5b611482826114fc565b600080604083850312156116e957600080fd5b6116f2836114fc565b9150611700602084016114fc565b90509250929050565b600181811c9082168061171d57607f821691505b602082108103611756577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036117eb576117eb61178b565b5060010190565b600082198211156118055761180561178b565b500190565b60008282101561181c5761181c61178b565b50039056fea164736f6c634300080f000aa164736f6c634300080f000a"; ++ hex"60806040523480156200001157600080fd5b5060043610620000935760003560e01c8063c4d66de81162000062578063c4d66de81462000175578063ce5ac90f146200018e578063e78cea9214620001a5578063ee9a31a214620001c657600080fd5b8063316b3739146200009857806354fd4d5014620000fb578063896f93d114620001475780638cf0629c146200015e575b600080fd5b620000d1620000a936600462000652565b60026020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b620001386040518060400160405280600d81526020017f312e31302e312d626574612e310000000000000000000000000000000000000081525081565b604051620000f29190620006e5565b620000d162000158366004620007dc565b620001e5565b620000d16200016f36600462000859565b620001fc565b6200018c6200018636600462000652565b6200041b565b005b620000d16200019f366004620007dc565b620005ed565b600154620000d19073ffffffffffffffffffffffffffffffffffffffff1681565b60015473ffffffffffffffffffffffffffffffffffffffff16620000d1565b6000620001f4848484620005ed565b949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8516620002a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4f7074696d69736d4d696e7461626c654552433230466163746f72793a206d7560448201527f73742070726f766964652072656d6f746520746f6b656e20616464726573730060648201526084015b60405180910390fd5b600085858585604051602001620002c29493929190620008f0565b604051602081830303815290604052805190602001209050600081600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168888888860405162000312906200061a565b620003229594939291906200094a565b8190604051809103906000f590508015801562000343573d6000803e3d6000fd5b5073ffffffffffffffffffffffffffffffffffffffff81811660008181526002602052604080822080547fffffffffffffffffffffffff000000000000000000000000000000000000000016948d1694851790555193945090927fceeb8e7d520d7f3b65fc11a262b91066940193b05d4f93df07cfdced0eb551cf9190a360405133815273ffffffffffffffffffffffffffffffffffffffff80891691908316907f52fe89dd5930f343d25650b62fd367bae47088bcddffd2a88350a6ecdd620cdb9060200160405180910390a39695505050505050565b600054610100900460ff16158080156200043c5750600054600160ff909116105b80620004585750303b15801562000458575060005460ff166001145b620004e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016200029e565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156200054557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84161790558015620005e957600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6000620001f48484846012620001fc565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b61178a80620009b083390190565b803573ffffffffffffffffffffffffffffffffffffffff811681146200064d57600080fd5b919050565b6000602082840312156200066557600080fd5b620006708262000628565b9392505050565b6000815180845260005b818110156200069f5760208185018101518683018201520162000681565b81811115620006b2576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600062000670602083018462000677565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126200073b57600080fd5b813567ffffffffffffffff80821115620007595762000759620006fa565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715620007a257620007a2620006fa565b81604052838152866020858801011115620007bc57600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600060608486031215620007f257600080fd5b620007fd8462000628565b9250602084013567ffffffffffffffff808211156200081b57600080fd5b620008298783880162000729565b935060408601359150808211156200084057600080fd5b506200084f8682870162000729565b9150509250925092565b600080600080608085870312156200087057600080fd5b6200087b8562000628565b9350602085013567ffffffffffffffff808211156200089957600080fd5b620008a78883890162000729565b94506040870135915080821115620008be57600080fd5b50620008cd8782880162000729565b925050606085013560ff81168114620008e557600080fd5b939692955090935050565b73ffffffffffffffffffffffffffffffffffffffff8516815260806020820152600062000921608083018662000677565b828103604084015262000935818662000677565b91505060ff8316606083015295945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808816835280871660208401525060a060408301526200098560a083018662000677565b828103606084015262000999818662000677565b91505060ff83166080830152969550505050505056fe60e06040523480156200001157600080fd5b506040516200178a3803806200178a833981016040819052620000349162000163565b828260036200004483826200029e565b5060046200005382826200029e565b5050506001600160a01b039384166080529390921660a052505060ff1660c0526200036a565b80516001600160a01b03811681146200009157600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620000be57600080fd5b81516001600160401b0380821115620000db57620000db62000096565b604051601f8301601f19908116603f0116810190828211818310171562000106576200010662000096565b816040528381526020925086838588010111156200012357600080fd5b600091505b8382101562000147578582018301518183018401529082019062000128565b83821115620001595760008385830101525b9695505050505050565b600080600080600060a086880312156200017c57600080fd5b620001878662000079565b9450620001976020870162000079565b60408701519094506001600160401b0380821115620001b557600080fd5b620001c389838a01620000ac565b94506060880151915080821115620001da57600080fd5b50620001e988828901620000ac565b925050608086015160ff811681146200020157600080fd5b809150509295509295909350565b600181811c908216806200022457607f821691505b6020821081036200024557634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200029957600081815260208120601f850160051c81016020861015620002745750805b601f850160051c820191505b81811015620002955782815560010162000280565b5050505b505050565b81516001600160401b03811115620002ba57620002ba62000096565b620002d281620002cb84546200020f565b846200024b565b602080601f8311600181146200030a5760008415620002f15750858301515b600019600386901b1c1916600185901b17855562000295565b600085815260208120601f198616915b828110156200033b578886015182559484019460019091019084016200031a565b50858210156200035a5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c0516113d4620003b6600039600061024401526000818161034b015281816103e001528181610625015261075c0152600081816101a9015261037101526113d46000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063ae1f6aaf1161008c578063dd62ed3e11610066578063dd62ed3e14610395578063e78cea9214610349578063ee9a31a2146103db57600080fd5b8063ae1f6aaf14610349578063c01e1bd61461036f578063d6c0b2c41461036f57600080fd5b80639dc29fac116100bd5780639dc29fac14610310578063a457c2d714610323578063a9059cbb1461033657600080fd5b806370a08231146102d257806395d89b411461030857600080fd5b806323b872dd1161012f5780633950935111610114578063395093511461026e57806340c10f191461028157806354fd4d501461029657600080fd5b806323b872dd1461022a578063313ce5671461023d57600080fd5b806306fdde031161016057806306fdde03146101f0578063095ea7b31461020557806318160ddd1461021857600080fd5b806301ffc9a71461017c578063033964be146101a4575b600080fd5b61018f61018a36600461117d565b610402565b60405190151581526020015b60405180910390f35b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b6101f86104f3565b60405161019b91906111c6565b61018f610213366004611262565b610585565b6002545b60405190815260200161019b565b61018f61023836600461128c565b61059d565b60405160ff7f000000000000000000000000000000000000000000000000000000000000000016815260200161019b565b61018f61027c366004611262565b6105c1565b61029461028f366004611262565b61060d565b005b6101f86040518060400160405280600c81526020017f312e332e312d626574612e31000000000000000000000000000000000000000081525081565b61021c6102e03660046112c8565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101f8610735565b61029461031e366004611262565b610744565b61018f610331366004611262565b61085b565b61018f610344366004611262565b61092c565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b7f00000000000000000000000000000000000000000000000000000000000000006101cb565b61021c6103a33660046112e3565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101cb7f000000000000000000000000000000000000000000000000000000000000000081565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007f1d1d8b63000000000000000000000000000000000000000000000000000000007fec4fc8e3000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000085168314806104bb57507fffffffff00000000000000000000000000000000000000000000000000000000858116908316145b806104ea57507fffffffff00000000000000000000000000000000000000000000000000000000858116908216145b95945050505050565b60606003805461050290611316565b80601f016020809104026020016040519081016040528092919081815260200182805461052e90611316565b801561057b5780601f106105505761010080835404028352916020019161057b565b820191906000526020600020905b81548152906001019060200180831161055e57829003601f168201915b5050505050905090565b60003361059381858561093a565b5060019392505050565b6000336105ab858285610aee565b6105b6858585610bc5565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906105939082908690610608908790611398565b61093a565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146106d7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084015b60405180910390fd5b6106e18282610e78565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d41213968858260405161072991815260200190565b60405180910390a25050565b60606004805461050290611316565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610809576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4f7074696d69736d4d696e7461626c6545524332303a206f6e6c79206272696460448201527f67652063616e206d696e7420616e64206275726e00000000000000000000000060648201526084016106ce565b6108138282610f98565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca58260405161072991815260200190565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091908381101561091f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084016106ce565b6105b6828686840361093a565b600033610593818585610bc5565b73ffffffffffffffffffffffffffffffffffffffff83166109dc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f726573730000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216610a7f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f737300000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610bbf5781811015610bb2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016106ce565b610bbf848484840361093a565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610c68576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f647265737300000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216610d0b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f657373000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610dc1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e6365000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260208190526040808220858503905591851681529081208054849290610e05908490611398565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610e6b91815260200190565b60405180910390a3610bbf565b73ffffffffffffffffffffffffffffffffffffffff8216610ef5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016106ce565b8060026000828254610f079190611398565b909155505073ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604081208054839290610f41908490611398565b909155505060405181815273ffffffffffffffffffffffffffffffffffffffff8316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff821661103b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f730000000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260208190526040902054818110156110f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f636500000000000000000000000000000000000000000000000000000000000060648201526084016106ce565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260208190526040812083830390556002805484929061112d9084906113b0565b909155505060405182815260009073ffffffffffffffffffffffffffffffffffffffff8516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610ae1565b60006020828403121561118f57600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146111bf57600080fd5b9392505050565b600060208083528351808285015260005b818110156111f3578581018301518582016040015282016111d7565b81811115611205576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461125d57600080fd5b919050565b6000806040838503121561127557600080fd5b61127e83611239565b946020939093013593505050565b6000806000606084860312156112a157600080fd5b6112aa84611239565b92506112b860208501611239565b9150604084013590509250925092565b6000602082840312156112da57600080fd5b6111bf82611239565b600080604083850312156112f657600080fd5b6112ff83611239565b915061130d60208401611239565b90509250929050565b600181811c9082168061132a57607f821691505b602082108103611363577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156113ab576113ab611369565b500190565b6000828210156113c2576113c2611369565b50039056fea164736f6c634300080f000aa164736f6c634300080f000a"; bytes internal constant systemConfigCode = - hex"608060405234801561001057600080fd5b50600436106102de5760003560e01c8063a711986911610186578063e0e2016d116100e3578063f2fde38b11610097578063f8c68de011610071578063f8c68de0146106e2578063fd32aa0f146106ea578063ffa1ad74146106f257600080fd5b8063f2fde38b146106b2578063f45e65d8146106c5578063f68016b7146106ce57600080fd5b8063e81b2c6d116100c8578063e81b2c6d14610681578063ec7075171461068a578063f2b4e617146106aa57600080fd5b8063e0e2016d14610671578063e2a3285c1461067957600080fd5b8063c9b26f611161013a578063d84447151161011f578063d84447151461064e578063dac6e63a14610656578063db9040fa1461065e57600080fd5b8063c9b26f6114610507578063cc731b021461051a57600080fd5b8063bc49ce5f1161016b578063bc49ce5f146104c6578063bfb14fb7146104ce578063c4e8ddfa146104ff57600080fd5b8063a7119869146104ab578063b40a817c146104b357600080fd5b80634397dfef1161023f578063550fcdc9116101f35780638da5cb5b116101cd5780638da5cb5b14610472578063935f029e146104905780639b7d7f0a146104a357600080fd5b8063550fcdc91461045a5780635d73369c14610462578063715018a61461046a57600080fd5b80634add321d116102245780634add321d146103e95780634f16540b146103f157806354fd4d501461041857600080fd5b80634397dfef146103ab57806348cd4cb1146103e157600080fd5b806318d13918116102965780631fd19ee11161027b5780631fd19ee114610378578063213268491461038057806321d7fde51461039857600080fd5b806318d139181461035b57806319f5cea81461037057600080fd5b80630a49cb03116102c75780630a49cb031461032b5780630ae14b1b146103335780630c18c1621461035257600080fd5b806306c92657146102e3578063078f29cf146102fe575b600080fd5b6102eb6106fa565b6040519081526020015b60405180910390f35b610306610728565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016102f5565b610306610761565b630bebc2005b60405167ffffffffffffffff90911681526020016102f5565b6102eb60655481565b61036e610369366004612241565b610791565b005b6102eb6107a5565b6103066107d0565b6103886107fa565b60405190151581526020016102f5565b61036e6103a6366004612277565b610839565b6103b361084f565b6040805173ffffffffffffffffffffffffffffffffffffffff909316835260ff9091166020830152016102f5565b6102eb610863565b610339610893565b6102eb7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c0881565b60408051808201909152600c81527f322e332e302d626574612e32000000000000000000000000000000000000000060208201525b6040516102f59190612320565b61044d6108b9565b6102eb6108c3565b61036e6108ee565b60335473ffffffffffffffffffffffffffffffffffffffff16610306565b61036e61049e366004612333565b610902565b610306610914565b610306610944565b61036e6104c136600461236d565b610974565b6102eb610985565b6068546104ea9068010000000000000000900463ffffffff1681565b60405163ffffffff90911681526020016102f5565b6103066109b0565b61036e610515366004612388565b6109e0565b6105de6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152506040805160c08101825260695463ffffffff8082168352640100000000820460ff9081166020850152650100000000008304169383019390935266010000000000008104831660608301526a0100000000000000000000810490921660808201526e0100000000000000000000000000009091046fffffffffffffffffffffffffffffffff1660a082015290565b6040516102f59190600060c08201905063ffffffff80845116835260ff602085015116602084015260ff6040850151166040840152806060850151166060840152806080850151166080840152506fffffffffffffffffffffffffffffffff60a08401511660a083015292915050565b61044d6109f1565b6103066109fb565b61036e61066c3660046124bb565b610a2b565b6102eb610e36565b6102eb610e61565b6102eb60675481565b6068546104ea906c01000000000000000000000000900463ffffffff1681565b610306610e8c565b61036e6106c0366004612241565b610ebc565b6102eb60665481565b6068546103399067ffffffffffffffff1681565b6102eb610f70565b6102eb610f9b565b6102eb600081565b61072560017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d61263d565b81565b600061075c61075860017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad637761263d565b5490565b905090565b600061075c61075860017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad61263d565b610799611201565b6107a281611282565b50565b61072560017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a861263d565b600061075c7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c085490565b60008061080561084f565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b610841611201565b61084b828261133f565b5050565b60008061085a611184565b90939092509050565b600061075c61075860017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a061263d565b60695460009061075c9063ffffffff6a0100000000000000000000820481169116612654565b606061075c61147d565b61072560017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce958063761263d565b6108f6611201565b610900600061153e565b565b61090a611201565b61084b82826115b5565b600061075c61075860017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d61263d565b600061075c61075860017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce958063761263d565b61097c611201565b6107a28161168b565b61072560017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc59861263d565b600061075c61075860017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a861263d565b6109e8611201565b6107a2816117e1565b606061075c611809565b600061075c61075860017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc59861263d565b600054610100900460ff1615808015610a4b5750600054600160ff909116105b80610a655750303b158015610a65575060005460ff166001145b610af6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610b5457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610b5c6118bf565b610b658a610ebc565b610b6e876117e1565b610b78898961133f565b610b818661168b565b610baa7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08869055565b610bdd610bd860017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc59861263d565b849055565b610c11610c0b60017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce958063761263d565b83519055565b610c48610c3f60017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a861263d565b60208401519055565b610c7f610c7660017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad637761263d565b60408401519055565b610cb6610cad60017f52322a25d9f59ea17656545543306b7aef62bc0cc53a0e65ccfa0c75b97aa90761263d565b60608401519055565b610ced610ce460017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad61263d565b60808401519055565b610d24610d1b60017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d61263d565b60a08401519055565b610d2c61195e565b610d398260c001516119c6565b610d4284611cd0565b610d4a610893565b67ffffffffffffffff168667ffffffffffffffff161015610dc7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77006044820152606401610aed565b8015610e2a57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050505050565b61072560017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a061263d565b61072560017f52322a25d9f59ea17656545543306b7aef62bc0cc53a0e65ccfa0c75b97aa90761263d565b600061075c61075860017f52322a25d9f59ea17656545543306b7aef62bc0cc53a0e65ccfa0c75b97aa90761263d565b610ec4611201565b73ffffffffffffffffffffffffffffffffffffffff8116610f67576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610aed565b6107a28161153e565b61072560017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad637761263d565b61072560017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad61263d565b9055565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b600060208251111561107a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f476173506179696e67546f6b656e3a20737472696e672063616e6e6f7420626560448201527f2067726561746572207468616e203332206279746573000000000000000000006064820152608401610aed565b6110838261115b565b92915050565b6110ef6110b760017f04adb1412b2ddc16fcc0d4538d5c8f07cf9c83abecc6b41f6f69037b708fbcec61263d565b74ff000000000000000000000000000000000000000060a086901b1673ffffffffffffffffffffffffffffffffffffffff8716179055565b61112261111d60017f657c3582c29b3176614e3a33ddd1ec48352696a04e92b3c0566d72010fa8863d61263d565b839055565b61115561115060017fa48b38a4b44951360fbdcbfaaeae5ed6ae92585412e9841b70ec72ed8cd0576461263d565b829055565b50505050565b8051602181106111735763ec92f9a36000526004601cfd5b9081015160209190910360031b1b90565b600080806111b661075860017f04adb1412b2ddc16fcc0d4538d5c8f07cf9c83abecc6b41f6f69037b708fbcec61263d565b73ffffffffffffffffffffffffffffffffffffffff811693509050826111f5575073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee92601292509050565b60a081901c9150509091565b60335473ffffffffffffffffffffffffffffffffffffffff163314610900576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610aed565b6112ab7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08829055565b6040805173ffffffffffffffffffffffffffffffffffffffff8316602082015260009101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060035b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be836040516113339190612320565b60405180910390a35050565b606880547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff166801000000000000000063ffffffff8581169182027fffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffff16929092176c0100000000000000000000000092851692909202919091179091557f0100000000000000000000000000000000000000000000000000000000000000602083811b67ffffffff000000001690921717606681905560655460408051938401919091528201526000906060015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529050600160007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be836040516114709190612320565b60405180910390a3505050565b60606000611489611184565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff82160161150257505060408051808201909152600381527f4554480000000000000000000000000000000000000000000000000000000000602082015290565b61153861153361075860017fa48b38a4b44951360fbdcbfaaeae5ed6ae92585412e9841b70ec72ed8cd0576461263d565b612144565b91505090565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b7fff00000000000000000000000000000000000000000000000000000000000000811615611665576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f53797374656d436f6e6669673a207363616c61722065786365656473206d617860448201527f2e000000000000000000000000000000000000000000000000000000000000006064820152608401610aed565b60658290556066819055604080516020810184905290810182905260009060600161140d565b611693610893565b67ffffffffffffffff168167ffffffffffffffff161015611710576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77006044820152606401610aed565b630bebc20067ffffffffffffffff82161115611788576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f20686967686044820152606401610aed565b606880547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff83169081179091556040805160208082019390935281518082039093018352810190526002611302565b6067819055604080516020808201849052825180830390910181529082019091526000611302565b60606000611815611184565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff82160161188e57505060408051808201909152600581527f4574686572000000000000000000000000000000000000000000000000000000602082015290565b61153861153361075860017f657c3582c29b3176614e3a33ddd1ec48352696a04e92b3c0566d72010fa8863d61263d565b600054610100900460ff16611956576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610aed565b610900612178565b61198c61075860017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a061263d565b600003610900576109006119c160017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a061263d565b439055565b73ffffffffffffffffffffffffffffffffffffffff811615801590611a15575073ffffffffffffffffffffffffffffffffffffffff811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14155b8015611a265750611a246107fa565b155b156107a257601260ff168173ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a9f9190612680565b60ff1614611b2f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f53797374656d436f6e6669673a2062616420646563696d616c73206f6620676160448201527f7320706179696e6720746f6b656e0000000000000000000000000000000000006064820152608401610aed565b6000611bca8273ffffffffffffffffffffffffffffffffffffffff166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa158015611b7f573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611bc5919081019061269d565b610fe6565b90506000611c1c8373ffffffffffffffffffffffffffffffffffffffff166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015611b7f573d6000803e3d6000fd5b9050611c2b8360128484611089565b611c33610761565b6040517f71cfaa3f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015260126024830152604482018590526064820184905291909116906371cfaa3f90608401600060405180830381600087803b158015611cb357600080fd5b505af1158015611cc7573d6000803e3d6000fd5b50505050505050565b8060a001516fffffffffffffffffffffffffffffffff16816060015163ffffffff161115611d80576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f53797374656d436f6e6669673a206d696e206261736520666565206d7573742060448201527f6265206c657373207468616e206d6178206261736500000000000000000000006064820152608401610aed565b6001816040015160ff1611611e17576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f53797374656d436f6e6669673a2064656e6f6d696e61746f72206d757374206260448201527f65206c6172676572207468616e203100000000000000000000000000000000006064820152608401610aed565b6068546080820151825167ffffffffffffffff90921691611e389190612768565b63ffffffff161115611ea6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77006044820152606401610aed565b6000816020015160ff1611611f3d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f53797374656d436f6e6669673a20656c6173746963697479206d756c7469706c60448201527f6965722063616e6e6f74206265203000000000000000000000000000000000006064820152608401610aed565b8051602082015163ffffffff82169160ff90911690611f5d908290612787565b611f6791906127d1565b63ffffffff1614611ffa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f53797374656d436f6e6669673a20707265636973696f6e206c6f73732077697460448201527f6820746172676574207265736f75726365206c696d69740000000000000000006064820152608401610aed565b805160698054602084015160408501516060860151608087015160a09097015163ffffffff9687167fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009095169490941764010000000060ff94851602177fffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffff166501000000000093909216929092027fffffffffffffffffffffffffffffffffffffffffffff00000000ffffffffffff1617660100000000000091851691909102177fffff0000000000000000000000000000000000000000ffffffffffffffffffff166a010000000000000000000093909416929092027fffff00000000000000000000000000000000ffffffffffffffffffffffffffff16929092176e0100000000000000000000000000006fffffffffffffffffffffffffffffffff90921691909102179055565b60405160005b82811a1561215a5760010161214a565b80825260208201838152600082820152505060408101604052919050565b600054610100900460ff1661220f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610aed565b6109003361153e565b803573ffffffffffffffffffffffffffffffffffffffff8116811461223c57600080fd5b919050565b60006020828403121561225357600080fd5b61225c82612218565b9392505050565b803563ffffffff8116811461223c57600080fd5b6000806040838503121561228a57600080fd5b61229383612263565b91506122a160208401612263565b90509250929050565b60005b838110156122c55781810151838201526020016122ad565b838111156111555750506000910152565b600081518084526122ee8160208601602086016122aa565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061225c60208301846122d6565b6000806040838503121561234657600080fd5b50508035926020909101359150565b803567ffffffffffffffff8116811461223c57600080fd5b60006020828403121561237f57600080fd5b61225c82612355565b60006020828403121561239a57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160c0810167ffffffffffffffff811182821017156123f3576123f36123a1565b60405290565b60ff811681146107a257600080fd5b600060e0828403121561241a57600080fd5b60405160e0810181811067ffffffffffffffff8211171561243d5761243d6123a1565b60405290508061244c83612218565b815261245a60208401612218565b602082015261246b60408401612218565b604082015261247c60608401612218565b606082015261248d60808401612218565b608082015261249e60a08401612218565b60a08201526124af60c08401612218565b60c08201525092915050565b6000806000806000806000806000898b036102808112156124db57600080fd5b6124e48b612218565b99506124f260208c01612263565b985061250060408c01612263565b975060608b0135965061251560808c01612355565b955061252360a08c01612218565b945060c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff408201121561255557600080fd5b5061255e6123d0565b61256a60c08c01612263565b815260e08b013561257a816123f9565b60208201526101008b013561258e816123f9565b60408201526125a06101208c01612263565b60608201526125b26101408c01612263565b60808201526101608b01356fffffffffffffffffffffffffffffffff811681146125db57600080fd5b60a082015292506125ef6101808b01612218565b91506125ff8b6101a08c01612408565b90509295985092959850929598565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008282101561264f5761264f61260e565b500390565b600067ffffffffffffffff8083168185168083038211156126775761267761260e565b01949350505050565b60006020828403121561269257600080fd5b815161225c816123f9565b6000602082840312156126af57600080fd5b815167ffffffffffffffff808211156126c757600080fd5b818401915084601f8301126126db57600080fd5b8151818111156126ed576126ed6123a1565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715612733576127336123a1565b8160405282815287602084870101111561274c57600080fd5b61275d8360208301602088016122aa565b979650505050505050565b600063ffffffff8083168185168083038211156126775761267761260e565b600063ffffffff808416806127c5577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b92169190910492915050565b600063ffffffff808316818516818304811182151516156127f4576127f461260e565b0294935050505056fea164736f6c634300080f000a"; +- hex"608060405234801561001057600080fd5b50600436106102de5760003560e01c8063a711986911610186578063e0e2016d116100e3578063f2fde38b11610097578063f8c68de011610071578063f8c68de0146106e2578063fd32aa0f146106ea578063ffa1ad74146106f257600080fd5b8063f2fde38b146106b2578063f45e65d8146106c5578063f68016b7146106ce57600080fd5b8063e81b2c6d116100c8578063e81b2c6d14610681578063ec7075171461068a578063f2b4e617146106aa57600080fd5b8063e0e2016d14610671578063e2a3285c1461067957600080fd5b8063c9b26f611161013a578063d84447151161011f578063d84447151461064e578063dac6e63a14610656578063db9040fa1461065e57600080fd5b8063c9b26f6114610507578063cc731b021461051a57600080fd5b8063bc49ce5f1161016b578063bc49ce5f146104c6578063bfb14fb7146104ce578063c4e8ddfa146104ff57600080fd5b8063a7119869146104ab578063b40a817c146104b357600080fd5b80634397dfef1161023f578063550fcdc9116101f35780638da5cb5b116101cd5780638da5cb5b14610472578063935f029e146104905780639b7d7f0a146104a357600080fd5b8063550fcdc91461045a5780635d73369c14610462578063715018a61461046a57600080fd5b80634add321d116102245780634add321d146103e95780634f16540b146103f157806354fd4d501461041857600080fd5b80634397dfef146103ab57806348cd4cb1146103e157600080fd5b806318d13918116102965780631fd19ee11161027b5780631fd19ee114610378578063213268491461038057806321d7fde51461039857600080fd5b806318d139181461035b57806319f5cea81461037057600080fd5b80630a49cb03116102c75780630a49cb031461032b5780630ae14b1b146103335780630c18c1621461035257600080fd5b806306c92657146102e3578063078f29cf146102fe575b600080fd5b6102eb6106fa565b6040519081526020015b60405180910390f35b610306610728565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016102f5565b610306610761565b630bebc2005b60405167ffffffffffffffff90911681526020016102f5565b6102eb60655481565b61036e610369366004612241565b610791565b005b6102eb6107a5565b6103066107d0565b6103886107fa565b60405190151581526020016102f5565b61036e6103a6366004612277565b610839565b6103b361084f565b6040805173ffffffffffffffffffffffffffffffffffffffff909316835260ff9091166020830152016102f5565b6102eb610863565b610339610893565b6102eb7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c0881565b60408051808201909152600c81527f322e332e302d626574612e32000000000000000000000000000000000000000060208201525b6040516102f59190612320565b61044d6108b9565b6102eb6108c3565b61036e6108ee565b60335473ffffffffffffffffffffffffffffffffffffffff16610306565b61036e61049e366004612333565b610902565b610306610914565b610306610944565b61036e6104c136600461236d565b610974565b6102eb610985565b6068546104ea9068010000000000000000900463ffffffff1681565b60405163ffffffff90911681526020016102f5565b6103066109b0565b61036e610515366004612388565b6109e0565b6105de6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152506040805160c08101825260695463ffffffff8082168352640100000000820460ff9081166020850152650100000000008304169383019390935266010000000000008104831660608301526a0100000000000000000000810490921660808201526e0100000000000000000000000000009091046fffffffffffffffffffffffffffffffff1660a082015290565b6040516102f59190600060c08201905063ffffffff80845116835260ff602085015116602084015260ff6040850151166040840152806060850151166060840152806080850151166080840152506fffffffffffffffffffffffffffffffff60a08401511660a083015292915050565b61044d6109f1565b6103066109fb565b61036e61066c3660046124bb565b610a2b565b6102eb610e36565b6102eb610e61565b6102eb60675481565b6068546104ea906c01000000000000000000000000900463ffffffff1681565b610306610e8c565b61036e6106c0366004612241565b610ebc565b6102eb60665481565b6068546103399067ffffffffffffffff1681565b6102eb610f70565b6102eb610f9b565b6102eb600081565b61072560017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d61263d565b81565b600061075c61075860017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad637761263d565b5490565b905090565b600061075c61075860017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad61263d565b610799611201565b6107a281611282565b50565b61072560017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a861263d565b600061075c7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c085490565b60008061080561084f565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b610841611201565b61084b828261133f565b5050565b60008061085a611184565b90939092509050565b600061075c61075860017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a061263d565b60695460009061075c9063ffffffff6a0100000000000000000000820481169116612654565b606061075c61147d565b61072560017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce958063761263d565b6108f6611201565b610900600061153e565b565b61090a611201565b61084b82826115b5565b600061075c61075860017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d61263d565b600061075c61075860017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce958063761263d565b61097c611201565b6107a28161168b565b61072560017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc59861263d565b600061075c61075860017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a861263d565b6109e8611201565b6107a2816117e1565b606061075c611809565b600061075c61075860017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc59861263d565b600054610100900460ff1615808015610a4b5750600054600160ff909116105b80610a655750303b158015610a65575060005460ff166001145b610af6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610b5457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610b5c6118bf565b610b658a610ebc565b610b6e876117e1565b610b78898961133f565b610b818661168b565b610baa7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08869055565b610bdd610bd860017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc59861263d565b849055565b610c11610c0b60017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce958063761263d565b83519055565b610c48610c3f60017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a861263d565b60208401519055565b610c7f610c7660017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad637761263d565b60408401519055565b610cb6610cad60017f52322a25d9f59ea17656545543306b7aef62bc0cc53a0e65ccfa0c75b97aa90761263d565b60608401519055565b610ced610ce460017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad61263d565b60808401519055565b610d24610d1b60017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d61263d565b60a08401519055565b610d2c61195e565b610d398260c001516119c6565b610d4284611cd0565b610d4a610893565b67ffffffffffffffff168667ffffffffffffffff161015610dc7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77006044820152606401610aed565b8015610e2a57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050505050565b61072560017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a061263d565b61072560017f52322a25d9f59ea17656545543306b7aef62bc0cc53a0e65ccfa0c75b97aa90761263d565b600061075c61075860017f52322a25d9f59ea17656545543306b7aef62bc0cc53a0e65ccfa0c75b97aa90761263d565b610ec4611201565b73ffffffffffffffffffffffffffffffffffffffff8116610f67576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610aed565b6107a28161153e565b61072560017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad637761263d565b61072560017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad61263d565b9055565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b600060208251111561107a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f476173506179696e67546f6b656e3a20737472696e672063616e6e6f7420626560448201527f2067726561746572207468616e203332206279746573000000000000000000006064820152608401610aed565b6110838261115b565b92915050565b6110ef6110b760017f04adb1412b2ddc16fcc0d4538d5c8f07cf9c83abecc6b41f6f69037b708fbcec61263d565b74ff000000000000000000000000000000000000000060a086901b1673ffffffffffffffffffffffffffffffffffffffff8716179055565b61112261111d60017f657c3582c29b3176614e3a33ddd1ec48352696a04e92b3c0566d72010fa8863d61263d565b839055565b61115561115060017fa48b38a4b44951360fbdcbfaaeae5ed6ae92585412e9841b70ec72ed8cd0576461263d565b829055565b50505050565b8051602181106111735763ec92f9a36000526004601cfd5b9081015160209190910360031b1b90565b600080806111b661075860017f04adb1412b2ddc16fcc0d4538d5c8f07cf9c83abecc6b41f6f69037b708fbcec61263d565b73ffffffffffffffffffffffffffffffffffffffff811693509050826111f5575073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee92601292509050565b60a081901c9150509091565b60335473ffffffffffffffffffffffffffffffffffffffff163314610900576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610aed565b6112ab7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08829055565b6040805173ffffffffffffffffffffffffffffffffffffffff8316602082015260009101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060035b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be836040516113339190612320565b60405180910390a35050565b606880547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff166801000000000000000063ffffffff8581169182027fffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffff16929092176c0100000000000000000000000092851692909202919091179091557f0100000000000000000000000000000000000000000000000000000000000000602083811b67ffffffff000000001690921717606681905560655460408051938401919091528201526000906060015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529050600160007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be836040516114709190612320565b60405180910390a3505050565b60606000611489611184565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff82160161150257505060408051808201909152600381527f4554480000000000000000000000000000000000000000000000000000000000602082015290565b61153861153361075860017fa48b38a4b44951360fbdcbfaaeae5ed6ae92585412e9841b70ec72ed8cd0576461263d565b612144565b91505090565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b7fff00000000000000000000000000000000000000000000000000000000000000811615611665576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f53797374656d436f6e6669673a207363616c61722065786365656473206d617860448201527f2e000000000000000000000000000000000000000000000000000000000000006064820152608401610aed565b60658290556066819055604080516020810184905290810182905260009060600161140d565b611693610893565b67ffffffffffffffff168167ffffffffffffffff161015611710576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77006044820152606401610aed565b630bebc20067ffffffffffffffff82161115611788576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f20686967686044820152606401610aed565b606880547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff83169081179091556040805160208082019390935281518082039093018352810190526002611302565b6067819055604080516020808201849052825180830390910181529082019091526000611302565b60606000611815611184565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff82160161188e57505060408051808201909152600581527f4574686572000000000000000000000000000000000000000000000000000000602082015290565b61153861153361075860017f657c3582c29b3176614e3a33ddd1ec48352696a04e92b3c0566d72010fa8863d61263d565b600054610100900460ff16611956576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610aed565b610900612178565b61198c61075860017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a061263d565b600003610900576109006119c160017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a061263d565b439055565b73ffffffffffffffffffffffffffffffffffffffff811615801590611a15575073ffffffffffffffffffffffffffffffffffffffff811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14155b8015611a265750611a246107fa565b155b156107a257601260ff168173ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a9f9190612680565b60ff1614611b2f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f53797374656d436f6e6669673a2062616420646563696d616c73206f6620676160448201527f7320706179696e6720746f6b656e0000000000000000000000000000000000006064820152608401610aed565b6000611bca8273ffffffffffffffffffffffffffffffffffffffff166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa158015611b7f573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611bc5919081019061269d565b610fe6565b90506000611c1c8373ffffffffffffffffffffffffffffffffffffffff166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015611b7f573d6000803e3d6000fd5b9050611c2b8360128484611089565b611c33610761565b6040517f71cfaa3f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015260126024830152604482018590526064820184905291909116906371cfaa3f90608401600060405180830381600087803b158015611cb357600080fd5b505af1158015611cc7573d6000803e3d6000fd5b50505050505050565b8060a001516fffffffffffffffffffffffffffffffff16816060015163ffffffff161115611d80576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f53797374656d436f6e6669673a206d696e206261736520666565206d7573742060448201527f6265206c657373207468616e206d6178206261736500000000000000000000006064820152608401610aed565b6001816040015160ff1611611e17576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f53797374656d436f6e6669673a2064656e6f6d696e61746f72206d757374206260448201527f65206c6172676572207468616e203100000000000000000000000000000000006064820152608401610aed565b6068546080820151825167ffffffffffffffff90921691611e389190612768565b63ffffffff161115611ea6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77006044820152606401610aed565b6000816020015160ff1611611f3d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f53797374656d436f6e6669673a20656c6173746963697479206d756c7469706c60448201527f6965722063616e6e6f74206265203000000000000000000000000000000000006064820152608401610aed565b8051602082015163ffffffff82169160ff90911690611f5d908290612787565b611f6791906127d1565b63ffffffff1614611ffa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f53797374656d436f6e6669673a20707265636973696f6e206c6f73732077697460448201527f6820746172676574207265736f75726365206c696d69740000000000000000006064820152608401610aed565b805160698054602084015160408501516060860151608087015160a09097015163ffffffff9687167fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009095169490941764010000000060ff94851602177fffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffff166501000000000093909216929092027fffffffffffffffffffffffffffffffffffffffffffff00000000ffffffffffff1617660100000000000091851691909102177fffff0000000000000000000000000000000000000000ffffffffffffffffffff166a010000000000000000000093909416929092027fffff00000000000000000000000000000000ffffffffffffffffffffffffffff16929092176e0100000000000000000000000000006fffffffffffffffffffffffffffffffff90921691909102179055565b60405160005b82811a1561215a5760010161214a565b80825260208201838152600082820152505060408101604052919050565b600054610100900460ff1661220f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610aed565b6109003361153e565b803573ffffffffffffffffffffffffffffffffffffffff8116811461223c57600080fd5b919050565b60006020828403121561225357600080fd5b61225c82612218565b9392505050565b803563ffffffff8116811461223c57600080fd5b6000806040838503121561228a57600080fd5b61229383612263565b91506122a160208401612263565b90509250929050565b60005b838110156122c55781810151838201526020016122ad565b838111156111555750506000910152565b600081518084526122ee8160208601602086016122aa565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061225c60208301846122d6565b6000806040838503121561234657600080fd5b50508035926020909101359150565b803567ffffffffffffffff8116811461223c57600080fd5b60006020828403121561237f57600080fd5b61225c82612355565b60006020828403121561239a57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160c0810167ffffffffffffffff811182821017156123f3576123f36123a1565b60405290565b60ff811681146107a257600080fd5b600060e0828403121561241a57600080fd5b60405160e0810181811067ffffffffffffffff8211171561243d5761243d6123a1565b60405290508061244c83612218565b815261245a60208401612218565b602082015261246b60408401612218565b604082015261247c60608401612218565b606082015261248d60808401612218565b608082015261249e60a08401612218565b60a08201526124af60c08401612218565b60c08201525092915050565b6000806000806000806000806000898b036102808112156124db57600080fd5b6124e48b612218565b99506124f260208c01612263565b985061250060408c01612263565b975060608b0135965061251560808c01612355565b955061252360a08c01612218565b945060c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff408201121561255557600080fd5b5061255e6123d0565b61256a60c08c01612263565b815260e08b013561257a816123f9565b60208201526101008b013561258e816123f9565b60408201526125a06101208c01612263565b60608201526125b26101408c01612263565b60808201526101608b01356fffffffffffffffffffffffffffffffff811681146125db57600080fd5b60a082015292506125ef6101808b01612218565b91506125ff8b6101a08c01612408565b90509295985092959850929598565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008282101561264f5761264f61260e565b500390565b600067ffffffffffffffff8083168185168083038211156126775761267761260e565b01949350505050565b60006020828403121561269257600080fd5b815161225c816123f9565b6000602082840312156126af57600080fd5b815167ffffffffffffffff808211156126c757600080fd5b818401915084601f8301126126db57600080fd5b8151818111156126ed576126ed6123a1565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715612733576127336123a1565b8160405282815287602084870101111561274c57600080fd5b61275d8360208301602088016122aa565b979650505050505050565b600063ffffffff8083168185168083038211156126775761267761260e565b600063ffffffff808416806127c5577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b92169190910492915050565b600063ffffffff808316818516818304811182151516156127f4576127f461260e565b0294935050505056fea164736f6c634300080f000a"; ++ hex"608060405234801561001057600080fd5b50600436106102de5760003560e01c8063a711986911610186578063e0e2016d116100e3578063f2fde38b11610097578063f8c68de011610071578063f8c68de0146106e2578063fd32aa0f146106ea578063ffa1ad74146106f257600080fd5b8063f2fde38b146106b2578063f45e65d8146106c5578063f68016b7146106ce57600080fd5b8063e81b2c6d116100c8578063e81b2c6d14610681578063ec7075171461068a578063f2b4e617146106aa57600080fd5b8063e0e2016d14610671578063e2a3285c1461067957600080fd5b8063c9b26f611161013a578063d84447151161011f578063d84447151461064e578063dac6e63a14610656578063db9040fa1461065e57600080fd5b8063c9b26f6114610507578063cc731b021461051a57600080fd5b8063bc49ce5f1161016b578063bc49ce5f146104c6578063bfb14fb7146104ce578063c4e8ddfa146104ff57600080fd5b8063a7119869146104ab578063b40a817c146104b357600080fd5b80634397dfef1161023f578063550fcdc9116101f35780638da5cb5b116101cd5780638da5cb5b14610472578063935f029e146104905780639b7d7f0a146104a357600080fd5b8063550fcdc91461045a5780635d73369c14610462578063715018a61461046a57600080fd5b80634add321d116102245780634add321d146103e95780634f16540b146103f157806354fd4d501461041857600080fd5b80634397dfef146103ab57806348cd4cb1146103e157600080fd5b806318d13918116102965780631fd19ee11161027b5780631fd19ee114610378578063213268491461038057806321d7fde51461039857600080fd5b806318d139181461035b57806319f5cea81461037057600080fd5b80630a49cb03116102c75780630a49cb031461032b5780630ae14b1b146103335780630c18c1621461035257600080fd5b806306c92657146102e3578063078f29cf146102fe575b600080fd5b6102eb6106fa565b6040519081526020015b60405180910390f35b610306610728565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016102f5565b610306610761565b630bebc2005b60405167ffffffffffffffff90911681526020016102f5565b6102eb60655481565b61036e610369366004612241565b610791565b005b6102eb6107a5565b6103066107d0565b6103886107fa565b60405190151581526020016102f5565b61036e6103a6366004612277565b610839565b6103b361084f565b6040805173ffffffffffffffffffffffffffffffffffffffff909316835260ff9091166020830152016102f5565b6102eb610863565b610339610893565b6102eb7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c0881565b60408051808201909152600c81527f322e332e302d626574612e33000000000000000000000000000000000000000060208201525b6040516102f59190612320565b61044d6108b9565b6102eb6108c3565b61036e6108ee565b60335473ffffffffffffffffffffffffffffffffffffffff16610306565b61036e61049e366004612333565b610902565b610306610914565b610306610944565b61036e6104c136600461236d565b610974565b6102eb610985565b6068546104ea9068010000000000000000900463ffffffff1681565b60405163ffffffff90911681526020016102f5565b6103066109b0565b61036e610515366004612388565b6109e0565b6105de6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152506040805160c08101825260695463ffffffff8082168352640100000000820460ff9081166020850152650100000000008304169383019390935266010000000000008104831660608301526a0100000000000000000000810490921660808201526e0100000000000000000000000000009091046fffffffffffffffffffffffffffffffff1660a082015290565b6040516102f59190600060c08201905063ffffffff80845116835260ff602085015116602084015260ff6040850151166040840152806060850151166060840152806080850151166080840152506fffffffffffffffffffffffffffffffff60a08401511660a083015292915050565b61044d6109f1565b6103066109fb565b61036e61066c3660046124bb565b610a2b565b6102eb610e36565b6102eb610e61565b6102eb60675481565b6068546104ea906c01000000000000000000000000900463ffffffff1681565b610306610e8c565b61036e6106c0366004612241565b610ebc565b6102eb60665481565b6068546103399067ffffffffffffffff1681565b6102eb610f70565b6102eb610f9b565b6102eb600081565b61072560017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d61263d565b81565b600061075c61075860017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad637761263d565b5490565b905090565b600061075c61075860017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad61263d565b610799611201565b6107a281611282565b50565b61072560017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a861263d565b600061075c7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c085490565b60008061080561084f565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b610841611201565b61084b828261133f565b5050565b60008061085a611184565b90939092509050565b600061075c61075860017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a061263d565b60695460009061075c9063ffffffff6a0100000000000000000000820481169116612654565b606061075c61147d565b61072560017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce958063761263d565b6108f6611201565b610900600061153e565b565b61090a611201565b61084b82826115b5565b600061075c61075860017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d61263d565b600061075c61075860017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce958063761263d565b61097c611201565b6107a28161168b565b61072560017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc59861263d565b600061075c61075860017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a861263d565b6109e8611201565b6107a2816117e1565b606061075c611809565b600061075c61075860017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc59861263d565b600054610100900460ff1615808015610a4b5750600054600160ff909116105b80610a655750303b158015610a65575060005460ff166001145b610af6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610b5457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610b5c6118bf565b610b658a610ebc565b610b6e876117e1565b610b78898961133f565b610b818661168b565b610baa7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08869055565b610bdd610bd860017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc59861263d565b849055565b610c11610c0b60017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce958063761263d565b83519055565b610c48610c3f60017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a861263d565b60208401519055565b610c7f610c7660017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad637761263d565b60408401519055565b610cb6610cad60017f52322a25d9f59ea17656545543306b7aef62bc0cc53a0e65ccfa0c75b97aa90761263d565b60608401519055565b610ced610ce460017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad61263d565b60808401519055565b610d24610d1b60017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d61263d565b60a08401519055565b610d2c61195e565b610d398260c001516119c6565b610d4284611cd0565b610d4a610893565b67ffffffffffffffff168667ffffffffffffffff161015610dc7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77006044820152606401610aed565b8015610e2a57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050505050565b61072560017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a061263d565b61072560017f52322a25d9f59ea17656545543306b7aef62bc0cc53a0e65ccfa0c75b97aa90761263d565b600061075c61075860017f52322a25d9f59ea17656545543306b7aef62bc0cc53a0e65ccfa0c75b97aa90761263d565b610ec4611201565b73ffffffffffffffffffffffffffffffffffffffff8116610f67576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610aed565b6107a28161153e565b61072560017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad637761263d565b61072560017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad61263d565b9055565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b600060208251111561107a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f476173506179696e67546f6b656e3a20737472696e672063616e6e6f7420626560448201527f2067726561746572207468616e203332206279746573000000000000000000006064820152608401610aed565b6110838261115b565b92915050565b6110ef6110b760017f04adb1412b2ddc16fcc0d4538d5c8f07cf9c83abecc6b41f6f69037b708fbcec61263d565b74ff000000000000000000000000000000000000000060a086901b1673ffffffffffffffffffffffffffffffffffffffff8716179055565b61112261111d60017f657c3582c29b3176614e3a33ddd1ec48352696a04e92b3c0566d72010fa8863d61263d565b839055565b61115561115060017fa48b38a4b44951360fbdcbfaaeae5ed6ae92585412e9841b70ec72ed8cd0576461263d565b829055565b50505050565b8051602181106111735763ec92f9a36000526004601cfd5b9081015160209190910360031b1b90565b600080806111b661075860017f04adb1412b2ddc16fcc0d4538d5c8f07cf9c83abecc6b41f6f69037b708fbcec61263d565b73ffffffffffffffffffffffffffffffffffffffff811693509050826111f5575073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee92601292509050565b60a081901c9150509091565b60335473ffffffffffffffffffffffffffffffffffffffff163314610900576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610aed565b6112ab7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08829055565b6040805173ffffffffffffffffffffffffffffffffffffffff8316602082015260009101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060035b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be836040516113339190612320565b60405180910390a35050565b606880547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff166801000000000000000063ffffffff8581169182027fffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffff16929092176c0100000000000000000000000092851692909202919091179091557f0100000000000000000000000000000000000000000000000000000000000000602083811b67ffffffff000000001690921717606681905560655460408051938401919091528201526000906060015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529050600160007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be836040516114709190612320565b60405180910390a3505050565b60606000611489611184565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff82160161150257505060408051808201909152600381527f4554480000000000000000000000000000000000000000000000000000000000602082015290565b61153861153361075860017fa48b38a4b44951360fbdcbfaaeae5ed6ae92585412e9841b70ec72ed8cd0576461263d565b612144565b91505090565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b7fff00000000000000000000000000000000000000000000000000000000000000811615611665576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f53797374656d436f6e6669673a207363616c61722065786365656473206d617860448201527f2e000000000000000000000000000000000000000000000000000000000000006064820152608401610aed565b60658290556066819055604080516020810184905290810182905260009060600161140d565b611693610893565b67ffffffffffffffff168167ffffffffffffffff161015611710576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77006044820152606401610aed565b630bebc20067ffffffffffffffff82161115611788576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f20686967686044820152606401610aed565b606880547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff83169081179091556040805160208082019390935281518082039093018352810190526002611302565b6067819055604080516020808201849052825180830390910181529082019091526000611302565b60606000611815611184565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff82160161188e57505060408051808201909152600581527f4574686572000000000000000000000000000000000000000000000000000000602082015290565b61153861153361075860017f657c3582c29b3176614e3a33ddd1ec48352696a04e92b3c0566d72010fa8863d61263d565b600054610100900460ff16611956576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610aed565b610900612178565b61198c61075860017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a061263d565b600003610900576109006119c160017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a061263d565b439055565b73ffffffffffffffffffffffffffffffffffffffff811615801590611a15575073ffffffffffffffffffffffffffffffffffffffff811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14155b8015611a265750611a246107fa565b155b156107a257601260ff168173ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a9f9190612680565b60ff1614611b2f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f53797374656d436f6e6669673a2062616420646563696d616c73206f6620676160448201527f7320706179696e6720746f6b656e0000000000000000000000000000000000006064820152608401610aed565b6000611bca8273ffffffffffffffffffffffffffffffffffffffff166306fdde036040518163ffffffff1660e01b8152600401600060405180830381865afa158015611b7f573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611bc5919081019061269d565b610fe6565b90506000611c1c8373ffffffffffffffffffffffffffffffffffffffff166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015611b7f573d6000803e3d6000fd5b9050611c2b8360128484611089565b611c33610761565b6040517f71cfaa3f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015260126024830152604482018590526064820184905291909116906371cfaa3f90608401600060405180830381600087803b158015611cb357600080fd5b505af1158015611cc7573d6000803e3d6000fd5b50505050505050565b8060a001516fffffffffffffffffffffffffffffffff16816060015163ffffffff161115611d80576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f53797374656d436f6e6669673a206d696e206261736520666565206d7573742060448201527f6265206c657373207468616e206d6178206261736500000000000000000000006064820152608401610aed565b6001816040015160ff1611611e17576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f53797374656d436f6e6669673a2064656e6f6d696e61746f72206d757374206260448201527f65206c6172676572207468616e203100000000000000000000000000000000006064820152608401610aed565b6068546080820151825167ffffffffffffffff90921691611e389190612768565b63ffffffff161115611ea6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77006044820152606401610aed565b6000816020015160ff1611611f3d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f53797374656d436f6e6669673a20656c6173746963697479206d756c7469706c60448201527f6965722063616e6e6f74206265203000000000000000000000000000000000006064820152608401610aed565b8051602082015163ffffffff82169160ff90911690611f5d908290612787565b611f6791906127d1565b63ffffffff1614611ffa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f53797374656d436f6e6669673a20707265636973696f6e206c6f73732077697460448201527f6820746172676574207265736f75726365206c696d69740000000000000000006064820152608401610aed565b805160698054602084015160408501516060860151608087015160a09097015163ffffffff9687167fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009095169490941764010000000060ff94851602177fffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffff166501000000000093909216929092027fffffffffffffffffffffffffffffffffffffffffffff00000000ffffffffffff1617660100000000000091851691909102177fffff0000000000000000000000000000000000000000ffffffffffffffffffff166a010000000000000000000093909416929092027fffff00000000000000000000000000000000ffffffffffffffffffffffffffff16929092176e0100000000000000000000000000006fffffffffffffffffffffffffffffffff90921691909102179055565b60405160005b82811a1561215a5760010161214a565b80825260208201838152600082820152505060408101604052919050565b600054610100900460ff1661220f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610aed565b6109003361153e565b803573ffffffffffffffffffffffffffffffffffffffff8116811461223c57600080fd5b919050565b60006020828403121561225357600080fd5b61225c82612218565b9392505050565b803563ffffffff8116811461223c57600080fd5b6000806040838503121561228a57600080fd5b61229383612263565b91506122a160208401612263565b90509250929050565b60005b838110156122c55781810151838201526020016122ad565b838111156111555750506000910152565b600081518084526122ee8160208601602086016122aa565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061225c60208301846122d6565b6000806040838503121561234657600080fd5b50508035926020909101359150565b803567ffffffffffffffff8116811461223c57600080fd5b60006020828403121561237f57600080fd5b61225c82612355565b60006020828403121561239a57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160c0810167ffffffffffffffff811182821017156123f3576123f36123a1565b60405290565b60ff811681146107a257600080fd5b600060e0828403121561241a57600080fd5b60405160e0810181811067ffffffffffffffff8211171561243d5761243d6123a1565b60405290508061244c83612218565b815261245a60208401612218565b602082015261246b60408401612218565b604082015261247c60608401612218565b606082015261248d60808401612218565b608082015261249e60a08401612218565b60a08201526124af60c08401612218565b60c08201525092915050565b6000806000806000806000806000898b036102808112156124db57600080fd5b6124e48b612218565b99506124f260208c01612263565b985061250060408c01612263565b975060608b0135965061251560808c01612355565b955061252360a08c01612218565b945060c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff408201121561255557600080fd5b5061255e6123d0565b61256a60c08c01612263565b815260e08b013561257a816123f9565b60208201526101008b013561258e816123f9565b60408201526125a06101208c01612263565b60608201526125b26101408c01612263565b60808201526101608b01356fffffffffffffffffffffffffffffffff811681146125db57600080fd5b60a082015292506125ef6101808b01612218565b91506125ff8b6101a08c01612408565b90509295985092959850929598565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008282101561264f5761264f61260e565b500390565b600067ffffffffffffffff8083168185168083038211156126775761267761260e565b01949350505050565b60006020828403121561269257600080fd5b815161225c816123f9565b6000602082840312156126af57600080fd5b815167ffffffffffffffff808211156126c757600080fd5b818401915084601f8301126126db57600080fd5b8151818111156126ed576126ed6123a1565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715612733576127336123a1565b8160405282815287602084870101111561274c57600080fd5b61275d8360208301602088016122aa565b979650505050505050565b600063ffffffff8083168185168083038211156126775761267761260e565b600063ffffffff808416806127c5577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b92169190910492915050565b600063ffffffff808316818516818304811182151516156127f4576127f461260e565b0294935050505056fea164736f6c634300080f000a"; bytes internal constant l1StandardBridgeCode = -@@ -55,7 +55,7 @@ hex"6080604052600436106101845760003560e01c80637f46ddb2116100d65780639a2ac6d51161007f578063c0c53b8b11610059578063c0c53b8b14610529578063c89701a214610549578063e11013dd1461057657600080fd5b80639a2ac6d5146104e3578063a9f9e675146104f6578063b1a1a8821461051657600080fd5b80638f601f66116100b05780638f601f661461047257806391c49bf814610407578063927ede2d146104b857600080fd5b80637f46ddb214610407578063838b252014610432578063870876231461045257600080fd5b806335e80ab31161013857806354fd4d501161011257806354fd4d501461036c57806358a997f6146103c25780635c975abb146103e257600080fd5b806335e80ab3146102f25780633cb747bf1461031f578063540abf731461034c57600080fd5b80631532ec34116101695780631532ec34146102755780631635f5fd1461028857806333d7e2bd1461029b57600080fd5b80630166a07a1461024257806309fc88431461026257600080fd5b3661023d57333b1561021d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084015b60405180910390fd5b61023b333362030d40604051806020016040528060008152506105a5565b005b600080fd5b34801561024e57600080fd5b5061023b61025d366004612991565b6105b8565b61023b610270366004612a42565b6109d2565b61023b610283366004612a95565b610aa9565b61023b610296366004612a95565b610abd565b3480156102a757600080fd5b506033546102c89073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156102fe57600080fd5b506032546102c89073ffffffffffffffffffffffffffffffffffffffff1681565b34801561032b57600080fd5b506003546102c89073ffffffffffffffffffffffffffffffffffffffff1681565b34801561035857600080fd5b5061023b610367366004612b08565b61101b565b34801561037857600080fd5b506103b56040518060400160405280600581526020017f322e322e3000000000000000000000000000000000000000000000000000000081525081565b6040516102e99190612bf5565b3480156103ce57600080fd5b5061023b6103dd366004612c08565b611060565b3480156103ee57600080fd5b506103f7611134565b60405190151581526020016102e9565b34801561041357600080fd5b5060045473ffffffffffffffffffffffffffffffffffffffff166102c8565b34801561043e57600080fd5b5061023b61044d366004612b08565b6111cd565b34801561045e57600080fd5b5061023b61046d366004612c08565b611212565b34801561047e57600080fd5b506104aa61048d366004612c8b565b600260209081526000928352604080842090915290825290205481565b6040519081526020016102e9565b3480156104c457600080fd5b5060035473ffffffffffffffffffffffffffffffffffffffff166102c8565b61023b6104f1366004612cc4565b6112e6565b34801561050257600080fd5b5061023b610511366004612991565b611328565b61023b610524366004612a42565b611337565b34801561053557600080fd5b5061023b610544366004612d27565b611408565b34801561055557600080fd5b506004546102c89073ffffffffffffffffffffffffffffffffffffffff1681565b61023b610584366004612cc4565b611607565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6105b2848434858561164a565b50505050565b60035473ffffffffffffffffffffffffffffffffffffffff163314801561068b575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa15801561064f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106739190612d72565b73ffffffffffffffffffffffffffffffffffffffff16145b61073d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a401610214565b610745611134565b156107ac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616e646172644272696467653a20706175736564000000000000000000006044820152606401610214565b6107b5876118a9565b15610903576107c4878761190b565b610876576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a401610214565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590528816906340c10f1990604401600060405180830381600087803b1580156108e657600080fd5b505af11580156108fa573d6000803e3d6000fd5b50505050610985565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054610941908490612dbe565b73ffffffffffffffffffffffffffffffffffffffff8089166000818152600260209081526040808320948c1683529390529190912091909155610985908585611a2b565b6109c9878787878787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611aff92505050565b50505050505050565b333b15610a61576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610214565b610aa43333348686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061164a92505050565b505050565b610ab68585858585610abd565b5050505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610b90575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa158015610b54573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b789190612d72565b73ffffffffffffffffffffffffffffffffffffffff16145b610c42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a401610214565b610c4a611134565b15610cb1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616e646172644272696467653a20706175736564000000000000000000006044820152606401610214565b610cb9611b8d565b15610d46576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e0000000000000000006064820152608401610214565b823414610dd5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5374616e646172644272696467653a20616d6f756e742073656e7420646f657360448201527f206e6f74206d6174636820616d6f756e742072657175697265640000000000006064820152608401610214565b3073ffffffffffffffffffffffffffffffffffffffff851603610e7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f207360448201527f656c6600000000000000000000000000000000000000000000000000000000006064820152608401610214565b60035473ffffffffffffffffffffffffffffffffffffffff90811690851603610f25576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f206d60448201527f657373656e6765720000000000000000000000000000000000000000000000006064820152608401610214565b610f6785858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611bcc92505050565b6000610f84855a8660405180602001604052806000815250611c3f565b905080611013576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a20455448207472616e736665722066616960448201527f6c656400000000000000000000000000000000000000000000000000000000006064820152608401610214565b505050505050565b6109c987873388888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611c5792505050565b333b156110ef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610214565b61101386863333888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061201092505050565b603254604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa1580156111a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111c89190612dd5565b905090565b6109c987873388888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061201092505050565b333b156112a1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610214565b61101386863333888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611c5792505050565b6105b233858585858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506105a592505050565b6109c9878787878787876105b8565b333b156113c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610214565b610aa433338585858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506105a592505050565b600054610100900460ff16158080156114285750600054600160ff909116105b806114425750303b158015611442575060005460ff166001145b6114ce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610214565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561152c57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6032805473ffffffffffffffffffffffffffffffffffffffff8086167fffffffffffffffffffffffff000000000000000000000000000000000000000092831617909255603380549285169290911691909117905561159f8473420000000000000000000000000000000000001061201f565b80156105b257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150505050565b6105b23385348686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061164a92505050565b611652611b8d565b156116df576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e0000000000000000006064820152608401610214565b82341461176e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5374616e646172644272696467653a206272696467696e6720455448206d757360448201527f7420696e636c7564652073756666696369656e74204554482076616c756500006064820152608401610214565b61177a85858584612109565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9287929116907f1635f5fd00000000000000000000000000000000000000000000000000000000906117dd908b908b9086908a90602401612df7565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b909216825261187092918890600401612e40565b6000604051808303818588803b15801561188957600080fd5b505af115801561189d573d6000803e3d6000fd5b50505050505050505050565b60006118d5827f1d1d8b630000000000000000000000000000000000000000000000000000000061217c565b806119055750611905827fec4fc8e30000000000000000000000000000000000000000000000000000000061217c565b92915050565b6000611937837f1d1d8b630000000000000000000000000000000000000000000000000000000061217c565b156119e0578273ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015611987573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ab9190612d72565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050611905565b8273ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611987573d6000803e3d6000fd5b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052610aa49084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915261219f565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f3ceee06c1e37648fcbb6ed52e17b3e1f275a1f8c7b22a84b2b84732431e046b3868686604051611b7793929190612e85565b60405180910390a46110138686868686866122ab565b600080611b98612333565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2ac69ee804d9a7a0984249f508dfab7cb2534b465b6ce1580f99a38ba9c5e6318484604051611c2b929190612ec3565b60405180910390a36105b2848484846123d0565b6000806000835160208501868989f195945050505050565b3415611ce5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5374616e646172644272696467653a2063616e6e6f742073656e642076616c7560448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610214565b611cee876118a9565b15611e3c57611cfd878761190b565b611daf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a401610214565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015260248201859052881690639dc29fac90604401600060405180830381600087803b158015611e1f57600080fd5b505af1158015611e33573d6000803e3d6000fd5b50505050611ed0565b611e5e73ffffffffffffffffffffffffffffffffffffffff881686308661243d565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054611e9c908490612edc565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152600260209081526040808320938b16835292905220555b611ede87878787878661249b565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9216907f0166a07a0000000000000000000000000000000000000000000000000000000090611f42908b908d908c908c908c908b90602401612ef4565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e085901b9092168252611fd592918790600401612e40565b600060405180830381600087803b158015611fef57600080fd5b505af1158015612003573d6000803e3d6000fd5b5050505050505050505050565b6109c987878787878787611c57565b600054610100900460ff166120b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610214565b6003805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560048054929093169116179055565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f35d79ab81f2b2017e19afb5c5571778877782d7a8786f5907f93b0f4702f4f238484604051612168929190612ec3565b60405180910390a36105b284848484612529565b600061218783612588565b8015612198575061219883836125ec565b9392505050565b6000612201826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166126bb9092919063ffffffff16565b805190915015610aa4578080602001905181019061221f9190612dd5565b610aa4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610214565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fd59c65b35445225835c83f50b6ede06a7be047d22e357073e250d9af537518cd86868660405161232393929190612e85565b60405180910390a4505050505050565b603354604080517f4397dfef0000000000000000000000000000000000000000000000000000000081528151600093849373ffffffffffffffffffffffffffffffffffffffff90911692634397dfef92600480830193928290030181865afa1580156123a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123c79190612f4f565b90939092509050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f31b2166ff604fc5672ea5df08a78081d2bc6d746cadce880747f3643d819e83d848460405161242f929190612ec3565b60405180910390a350505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526105b29085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611a7d565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f718594027abd4eaed59f95162563e0cc6d0e8d5b86b1c7be8b1b0ac3343d039686868660405161251393929190612e85565b60405180910390a46110138686868686866126d2565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2849b43074093a05396b6f2a937dee8565b15a48a7b3d4bffb732a5017380af5848460405161242f929190612ec3565b60006125b4827f01ffc9a7000000000000000000000000000000000000000000000000000000006125ec565b801561190557506125e5827fffffffff000000000000000000000000000000000000000000000000000000006125ec565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d915060005190508280156126a4575060208210155b80156126b05750600081115b979650505050505050565b60606126ca848460008561274a565b949350505050565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f7ff126db8024424bbfd9826e8ab82ff59136289ea440b04b39a0df1b03b9cabf86868660405161232393929190612e85565b6060824710156127dc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610214565b73ffffffffffffffffffffffffffffffffffffffff85163b61285a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610214565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516128839190612f84565b60006040518083038185875af1925050503d80600081146128c0576040519150601f19603f3d011682016040523d82523d6000602084013e6128c5565b606091505b50915091506126b0828286606083156128df575081612198565b8251156128ef5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102149190612bf5565b73ffffffffffffffffffffffffffffffffffffffff8116811461294557600080fd5b50565b60008083601f84011261295a57600080fd5b50813567ffffffffffffffff81111561297257600080fd5b60208301915083602082850101111561298a57600080fd5b9250929050565b600080600080600080600060c0888a0312156129ac57600080fd5b87356129b781612923565b965060208801356129c781612923565b955060408801356129d781612923565b945060608801356129e781612923565b93506080880135925060a088013567ffffffffffffffff811115612a0a57600080fd5b612a168a828b01612948565b989b979a50959850939692959293505050565b803563ffffffff81168114612a3d57600080fd5b919050565b600080600060408486031215612a5757600080fd5b612a6084612a29565b9250602084013567ffffffffffffffff811115612a7c57600080fd5b612a8886828701612948565b9497909650939450505050565b600080600080600060808688031215612aad57600080fd5b8535612ab881612923565b94506020860135612ac881612923565b935060408601359250606086013567ffffffffffffffff811115612aeb57600080fd5b612af788828901612948565b969995985093965092949392505050565b600080600080600080600060c0888a031215612b2357600080fd5b8735612b2e81612923565b96506020880135612b3e81612923565b95506040880135612b4e81612923565b945060608801359350612b6360808901612a29565b925060a088013567ffffffffffffffff811115612a0a57600080fd5b60005b83811015612b9a578181015183820152602001612b82565b838111156105b25750506000910152565b60008151808452612bc3816020860160208601612b7f565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006121986020830184612bab565b60008060008060008060a08789031215612c2157600080fd5b8635612c2c81612923565b95506020870135612c3c81612923565b945060408701359350612c5160608801612a29565b9250608087013567ffffffffffffffff811115612c6d57600080fd5b612c7989828a01612948565b979a9699509497509295939492505050565b60008060408385031215612c9e57600080fd5b8235612ca981612923565b91506020830135612cb981612923565b809150509250929050565b60008060008060608587031215612cda57600080fd5b8435612ce581612923565b9350612cf360208601612a29565b9250604085013567ffffffffffffffff811115612d0f57600080fd5b612d1b87828801612948565b95989497509550505050565b600080600060608486031215612d3c57600080fd5b8335612d4781612923565b92506020840135612d5781612923565b91506040840135612d6781612923565b809150509250925092565b600060208284031215612d8457600080fd5b815161219881612923565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015612dd057612dd0612d8f565b500390565b600060208284031215612de757600080fd5b8151801515811461219857600080fd5b600073ffffffffffffffffffffffffffffffffffffffff808716835280861660208401525083604083015260806060830152612e366080830184612bab565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff84168152606060208201526000612e6f6060830185612bab565b905063ffffffff83166040830152949350505050565b73ffffffffffffffffffffffffffffffffffffffff84168152826020820152606060408201526000612eba6060830184612bab565b95945050505050565b8281526040602082015260006126ca6040830184612bab565b60008219821115612eef57612eef612d8f565b500190565b600073ffffffffffffffffffffffffffffffffffffffff80891683528088166020840152808716604084015280861660608401525083608083015260c060a0830152612f4360c0830184612bab565b98975050505050505050565b60008060408385031215612f6257600080fd5b8251612f6d81612923565b602084015190925060ff81168114612cb957600080fd5b60008251612f96818460208701612b7f565b919091019291505056fea164736f6c634300080f000a"; +- hex"6080604052600436106101845760003560e01c80637f46ddb2116100d65780639a2ac6d51161007f578063c0c53b8b11610059578063c0c53b8b14610529578063c89701a214610549578063e11013dd1461057657600080fd5b80639a2ac6d5146104e3578063a9f9e675146104f6578063b1a1a8821461051657600080fd5b80638f601f66116100b05780638f601f661461047257806391c49bf814610407578063927ede2d146104b857600080fd5b80637f46ddb214610407578063838b252014610432578063870876231461045257600080fd5b806335e80ab31161013857806354fd4d501161011257806354fd4d501461036c57806358a997f6146103c25780635c975abb146103e257600080fd5b806335e80ab3146102f25780633cb747bf1461031f578063540abf731461034c57600080fd5b80631532ec34116101695780631532ec34146102755780631635f5fd1461028857806333d7e2bd1461029b57600080fd5b80630166a07a1461024257806309fc88431461026257600080fd5b3661023d57333b1561021d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084015b60405180910390fd5b61023b333362030d40604051806020016040528060008152506105a5565b005b600080fd5b34801561024e57600080fd5b5061023b61025d366004612991565b6105b8565b61023b610270366004612a42565b6109d2565b61023b610283366004612a95565b610aa9565b61023b610296366004612a95565b610abd565b3480156102a757600080fd5b506033546102c89073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156102fe57600080fd5b506032546102c89073ffffffffffffffffffffffffffffffffffffffff1681565b34801561032b57600080fd5b506003546102c89073ffffffffffffffffffffffffffffffffffffffff1681565b34801561035857600080fd5b5061023b610367366004612b08565b61101b565b34801561037857600080fd5b506103b56040518060400160405280600581526020017f322e322e3000000000000000000000000000000000000000000000000000000081525081565b6040516102e99190612bf5565b3480156103ce57600080fd5b5061023b6103dd366004612c08565b611060565b3480156103ee57600080fd5b506103f7611134565b60405190151581526020016102e9565b34801561041357600080fd5b5060045473ffffffffffffffffffffffffffffffffffffffff166102c8565b34801561043e57600080fd5b5061023b61044d366004612b08565b6111cd565b34801561045e57600080fd5b5061023b61046d366004612c08565b611212565b34801561047e57600080fd5b506104aa61048d366004612c8b565b600260209081526000928352604080842090915290825290205481565b6040519081526020016102e9565b3480156104c457600080fd5b5060035473ffffffffffffffffffffffffffffffffffffffff166102c8565b61023b6104f1366004612cc4565b6112e6565b34801561050257600080fd5b5061023b610511366004612991565b611328565b61023b610524366004612a42565b611337565b34801561053557600080fd5b5061023b610544366004612d27565b611408565b34801561055557600080fd5b506004546102c89073ffffffffffffffffffffffffffffffffffffffff1681565b61023b610584366004612cc4565b611607565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6105b2848434858561164a565b50505050565b60035473ffffffffffffffffffffffffffffffffffffffff163314801561068b575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa15801561064f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106739190612d72565b73ffffffffffffffffffffffffffffffffffffffff16145b61073d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a401610214565b610745611134565b156107ac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616e646172644272696467653a20706175736564000000000000000000006044820152606401610214565b6107b5876118a9565b15610903576107c4878761190b565b610876576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a401610214565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590528816906340c10f1990604401600060405180830381600087803b1580156108e657600080fd5b505af11580156108fa573d6000803e3d6000fd5b50505050610985565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054610941908490612dbe565b73ffffffffffffffffffffffffffffffffffffffff8089166000818152600260209081526040808320948c1683529390529190912091909155610985908585611a2b565b6109c9878787878787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611aff92505050565b50505050505050565b333b15610a61576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610214565b610aa43333348686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061164a92505050565b505050565b610ab68585858585610abd565b5050505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610b90575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa158015610b54573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b789190612d72565b73ffffffffffffffffffffffffffffffffffffffff16145b610c42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a401610214565b610c4a611134565b15610cb1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616e646172644272696467653a20706175736564000000000000000000006044820152606401610214565b610cb9611b8d565b15610d46576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e0000000000000000006064820152608401610214565b823414610dd5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5374616e646172644272696467653a20616d6f756e742073656e7420646f657360448201527f206e6f74206d6174636820616d6f756e742072657175697265640000000000006064820152608401610214565b3073ffffffffffffffffffffffffffffffffffffffff851603610e7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f207360448201527f656c6600000000000000000000000000000000000000000000000000000000006064820152608401610214565b60035473ffffffffffffffffffffffffffffffffffffffff90811690851603610f25576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f206d60448201527f657373656e6765720000000000000000000000000000000000000000000000006064820152608401610214565b610f6785858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611bcc92505050565b6000610f84855a8660405180602001604052806000815250611c3f565b905080611013576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a20455448207472616e736665722066616960448201527f6c656400000000000000000000000000000000000000000000000000000000006064820152608401610214565b505050505050565b6109c987873388888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611c5792505050565b333b156110ef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610214565b61101386863333888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061201092505050565b603254604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa1580156111a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111c89190612dd5565b905090565b6109c987873388888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061201092505050565b333b156112a1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610214565b61101386863333888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611c5792505050565b6105b233858585858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506105a592505050565b6109c9878787878787876105b8565b333b156113c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610214565b610aa433338585858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506105a592505050565b600054610100900460ff16158080156114285750600054600160ff909116105b806114425750303b158015611442575060005460ff166001145b6114ce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610214565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561152c57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6032805473ffffffffffffffffffffffffffffffffffffffff8086167fffffffffffffffffffffffff000000000000000000000000000000000000000092831617909255603380549285169290911691909117905561159f8473420000000000000000000000000000000000001061201f565b80156105b257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150505050565b6105b23385348686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061164a92505050565b611652611b8d565b156116df576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e0000000000000000006064820152608401610214565b82341461176e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5374616e646172644272696467653a206272696467696e6720455448206d757360448201527f7420696e636c7564652073756666696369656e74204554482076616c756500006064820152608401610214565b61177a85858584612109565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9287929116907f1635f5fd00000000000000000000000000000000000000000000000000000000906117dd908b908b9086908a90602401612df7565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b909216825261187092918890600401612e40565b6000604051808303818588803b15801561188957600080fd5b505af115801561189d573d6000803e3d6000fd5b50505050505050505050565b60006118d5827f1d1d8b630000000000000000000000000000000000000000000000000000000061217c565b806119055750611905827fec4fc8e30000000000000000000000000000000000000000000000000000000061217c565b92915050565b6000611937837f1d1d8b630000000000000000000000000000000000000000000000000000000061217c565b156119e0578273ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015611987573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ab9190612d72565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050611905565b8273ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611987573d6000803e3d6000fd5b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052610aa49084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915261219f565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f3ceee06c1e37648fcbb6ed52e17b3e1f275a1f8c7b22a84b2b84732431e046b3868686604051611b7793929190612e85565b60405180910390a46110138686868686866122ab565b600080611b98612333565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2ac69ee804d9a7a0984249f508dfab7cb2534b465b6ce1580f99a38ba9c5e6318484604051611c2b929190612ec3565b60405180910390a36105b2848484846123d0565b6000806000835160208501868989f195945050505050565b3415611ce5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5374616e646172644272696467653a2063616e6e6f742073656e642076616c7560448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610214565b611cee876118a9565b15611e3c57611cfd878761190b565b611daf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a401610214565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015260248201859052881690639dc29fac90604401600060405180830381600087803b158015611e1f57600080fd5b505af1158015611e33573d6000803e3d6000fd5b50505050611ed0565b611e5e73ffffffffffffffffffffffffffffffffffffffff881686308661243d565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054611e9c908490612edc565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152600260209081526040808320938b16835292905220555b611ede87878787878661249b565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9216907f0166a07a0000000000000000000000000000000000000000000000000000000090611f42908b908d908c908c908c908b90602401612ef4565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e085901b9092168252611fd592918790600401612e40565b600060405180830381600087803b158015611fef57600080fd5b505af1158015612003573d6000803e3d6000fd5b5050505050505050505050565b6109c987878787878787611c57565b600054610100900460ff166120b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610214565b6003805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560048054929093169116179055565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f35d79ab81f2b2017e19afb5c5571778877782d7a8786f5907f93b0f4702f4f238484604051612168929190612ec3565b60405180910390a36105b284848484612529565b600061218783612588565b8015612198575061219883836125ec565b9392505050565b6000612201826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166126bb9092919063ffffffff16565b805190915015610aa4578080602001905181019061221f9190612dd5565b610aa4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610214565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fd59c65b35445225835c83f50b6ede06a7be047d22e357073e250d9af537518cd86868660405161232393929190612e85565b60405180910390a4505050505050565b603354604080517f4397dfef0000000000000000000000000000000000000000000000000000000081528151600093849373ffffffffffffffffffffffffffffffffffffffff90911692634397dfef92600480830193928290030181865afa1580156123a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123c79190612f4f565b90939092509050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f31b2166ff604fc5672ea5df08a78081d2bc6d746cadce880747f3643d819e83d848460405161242f929190612ec3565b60405180910390a350505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526105b29085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611a7d565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f718594027abd4eaed59f95162563e0cc6d0e8d5b86b1c7be8b1b0ac3343d039686868660405161251393929190612e85565b60405180910390a46110138686868686866126d2565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2849b43074093a05396b6f2a937dee8565b15a48a7b3d4bffb732a5017380af5848460405161242f929190612ec3565b60006125b4827f01ffc9a7000000000000000000000000000000000000000000000000000000006125ec565b801561190557506125e5827fffffffff000000000000000000000000000000000000000000000000000000006125ec565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d915060005190508280156126a4575060208210155b80156126b05750600081115b979650505050505050565b60606126ca848460008561274a565b949350505050565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f7ff126db8024424bbfd9826e8ab82ff59136289ea440b04b39a0df1b03b9cabf86868660405161232393929190612e85565b6060824710156127dc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610214565b73ffffffffffffffffffffffffffffffffffffffff85163b61285a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610214565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516128839190612f84565b60006040518083038185875af1925050503d80600081146128c0576040519150601f19603f3d011682016040523d82523d6000602084013e6128c5565b606091505b50915091506126b0828286606083156128df575081612198565b8251156128ef5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102149190612bf5565b73ffffffffffffffffffffffffffffffffffffffff8116811461294557600080fd5b50565b60008083601f84011261295a57600080fd5b50813567ffffffffffffffff81111561297257600080fd5b60208301915083602082850101111561298a57600080fd5b9250929050565b600080600080600080600060c0888a0312156129ac57600080fd5b87356129b781612923565b965060208801356129c781612923565b955060408801356129d781612923565b945060608801356129e781612923565b93506080880135925060a088013567ffffffffffffffff811115612a0a57600080fd5b612a168a828b01612948565b989b979a50959850939692959293505050565b803563ffffffff81168114612a3d57600080fd5b919050565b600080600060408486031215612a5757600080fd5b612a6084612a29565b9250602084013567ffffffffffffffff811115612a7c57600080fd5b612a8886828701612948565b9497909650939450505050565b600080600080600060808688031215612aad57600080fd5b8535612ab881612923565b94506020860135612ac881612923565b935060408601359250606086013567ffffffffffffffff811115612aeb57600080fd5b612af788828901612948565b969995985093965092949392505050565b600080600080600080600060c0888a031215612b2357600080fd5b8735612b2e81612923565b96506020880135612b3e81612923565b95506040880135612b4e81612923565b945060608801359350612b6360808901612a29565b925060a088013567ffffffffffffffff811115612a0a57600080fd5b60005b83811015612b9a578181015183820152602001612b82565b838111156105b25750506000910152565b60008151808452612bc3816020860160208601612b7f565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006121986020830184612bab565b60008060008060008060a08789031215612c2157600080fd5b8635612c2c81612923565b95506020870135612c3c81612923565b945060408701359350612c5160608801612a29565b9250608087013567ffffffffffffffff811115612c6d57600080fd5b612c7989828a01612948565b979a9699509497509295939492505050565b60008060408385031215612c9e57600080fd5b8235612ca981612923565b91506020830135612cb981612923565b809150509250929050565b60008060008060608587031215612cda57600080fd5b8435612ce581612923565b9350612cf360208601612a29565b9250604085013567ffffffffffffffff811115612d0f57600080fd5b612d1b87828801612948565b95989497509550505050565b600080600060608486031215612d3c57600080fd5b8335612d4781612923565b92506020840135612d5781612923565b91506040840135612d6781612923565b809150509250925092565b600060208284031215612d8457600080fd5b815161219881612923565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015612dd057612dd0612d8f565b500390565b600060208284031215612de757600080fd5b8151801515811461219857600080fd5b600073ffffffffffffffffffffffffffffffffffffffff808716835280861660208401525083604083015260806060830152612e366080830184612bab565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff84168152606060208201526000612e6f6060830185612bab565b905063ffffffff83166040830152949350505050565b73ffffffffffffffffffffffffffffffffffffffff84168152826020820152606060408201526000612eba6060830184612bab565b95945050505050565b8281526040602082015260006126ca6040830184612bab565b60008219821115612eef57612eef612d8f565b500190565b600073ffffffffffffffffffffffffffffffffffffffff80891683528088166020840152808716604084015280861660608401525083608083015260c060a0830152612f4360c0830184612bab565b98975050505050505050565b60008060408385031215612f6257600080fd5b8251612f6d81612923565b602084015190925060ff81168114612cb957600080fd5b60008251612f96818460208701612b7f565b919091019291505056fea164736f6c634300080f000a"; ++ hex"6080604052600436106101845760003560e01c80637f46ddb2116100d65780639a2ac6d51161007f578063c0c53b8b11610059578063c0c53b8b14610529578063c89701a214610549578063e11013dd1461057657600080fd5b80639a2ac6d5146104e3578063a9f9e675146104f6578063b1a1a8821461051657600080fd5b80638f601f66116100b05780638f601f661461047257806391c49bf814610407578063927ede2d146104b857600080fd5b80637f46ddb214610407578063838b252014610432578063870876231461045257600080fd5b806335e80ab31161013857806354fd4d501161011257806354fd4d501461036c57806358a997f6146103c25780635c975abb146103e257600080fd5b806335e80ab3146102f25780633cb747bf1461031f578063540abf731461034c57600080fd5b80631532ec34116101695780631532ec34146102755780631635f5fd1461028857806333d7e2bd1461029b57600080fd5b80630166a07a1461024257806309fc88431461026257600080fd5b3661023d57333b1561021d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084015b60405180910390fd5b61023b333362030d40604051806020016040528060008152506105a5565b005b600080fd5b34801561024e57600080fd5b5061023b61025d366004612991565b6105b8565b61023b610270366004612a42565b6109d2565b61023b610283366004612a95565b610aa9565b61023b610296366004612a95565b610abd565b3480156102a757600080fd5b506033546102c89073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156102fe57600080fd5b506032546102c89073ffffffffffffffffffffffffffffffffffffffff1681565b34801561032b57600080fd5b506003546102c89073ffffffffffffffffffffffffffffffffffffffff1681565b34801561035857600080fd5b5061023b610367366004612b08565b61101b565b34801561037857600080fd5b506103b56040518060400160405280600c81526020017f322e322e312d626574612e31000000000000000000000000000000000000000081525081565b6040516102e99190612bf5565b3480156103ce57600080fd5b5061023b6103dd366004612c08565b611060565b3480156103ee57600080fd5b506103f7611134565b60405190151581526020016102e9565b34801561041357600080fd5b5060045473ffffffffffffffffffffffffffffffffffffffff166102c8565b34801561043e57600080fd5b5061023b61044d366004612b08565b6111cd565b34801561045e57600080fd5b5061023b61046d366004612c08565b611212565b34801561047e57600080fd5b506104aa61048d366004612c8b565b600260209081526000928352604080842090915290825290205481565b6040519081526020016102e9565b3480156104c457600080fd5b5060035473ffffffffffffffffffffffffffffffffffffffff166102c8565b61023b6104f1366004612cc4565b6112e6565b34801561050257600080fd5b5061023b610511366004612991565b611328565b61023b610524366004612a42565b611337565b34801561053557600080fd5b5061023b610544366004612d27565b611408565b34801561055557600080fd5b506004546102c89073ffffffffffffffffffffffffffffffffffffffff1681565b61023b610584366004612cc4565b611607565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b6105b2848434858561164a565b50505050565b60035473ffffffffffffffffffffffffffffffffffffffff163314801561068b575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa15801561064f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106739190612d72565b73ffffffffffffffffffffffffffffffffffffffff16145b61073d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a401610214565b610745611134565b156107ac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616e646172644272696467653a20706175736564000000000000000000006044820152606401610214565b6107b5876118a9565b15610903576107c4878761190b565b610876576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a401610214565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590528816906340c10f1990604401600060405180830381600087803b1580156108e657600080fd5b505af11580156108fa573d6000803e3d6000fd5b50505050610985565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054610941908490612dbe565b73ffffffffffffffffffffffffffffffffffffffff8089166000818152600260209081526040808320948c1683529390529190912091909155610985908585611a2b565b6109c9878787878787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611aff92505050565b50505050505050565b333b15610a61576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610214565b610aa43333348686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061164a92505050565b505050565b610ab68585858585610abd565b5050505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610b90575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa158015610b54573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b789190612d72565b73ffffffffffffffffffffffffffffffffffffffff16145b610c42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a401610214565b610c4a611134565b15610cb1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f5374616e646172644272696467653a20706175736564000000000000000000006044820152606401610214565b610cb9611b8d565b15610d46576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e0000000000000000006064820152608401610214565b823414610dd5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5374616e646172644272696467653a20616d6f756e742073656e7420646f657360448201527f206e6f74206d6174636820616d6f756e742072657175697265640000000000006064820152608401610214565b3073ffffffffffffffffffffffffffffffffffffffff851603610e7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f207360448201527f656c6600000000000000000000000000000000000000000000000000000000006064820152608401610214565b60035473ffffffffffffffffffffffffffffffffffffffff90811690851603610f25576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f206d60448201527f657373656e6765720000000000000000000000000000000000000000000000006064820152608401610214565b610f6785858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611bcc92505050565b6000610f84855a8660405180602001604052806000815250611c3f565b905080611013576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a20455448207472616e736665722066616960448201527f6c656400000000000000000000000000000000000000000000000000000000006064820152608401610214565b505050505050565b6109c987873388888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611c5792505050565b333b156110ef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610214565b61101386863333888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061201092505050565b603254604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa1580156111a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111c89190612dd5565b905090565b6109c987873388888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061201092505050565b333b156112a1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610214565b61101386863333888888888080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611c5792505050565b6105b233858585858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506105a592505050565b6109c9878787878787876105b8565b333b156113c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f410000000000000000006064820152608401610214565b610aa433338585858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506105a592505050565b600054610100900460ff16158080156114285750600054600160ff909116105b806114425750303b158015611442575060005460ff166001145b6114ce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610214565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561152c57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6032805473ffffffffffffffffffffffffffffffffffffffff8086167fffffffffffffffffffffffff000000000000000000000000000000000000000092831617909255603380549285169290911691909117905561159f8473420000000000000000000000000000000000001061201f565b80156105b257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150505050565b6105b23385348686868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061164a92505050565b611652611b8d565b156116df576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e0000000000000000006064820152608401610214565b82341461176e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5374616e646172644272696467653a206272696467696e6720455448206d757360448201527f7420696e636c7564652073756666696369656e74204554482076616c756500006064820152608401610214565b61177a85858584612109565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9287929116907f1635f5fd00000000000000000000000000000000000000000000000000000000906117dd908b908b9086908a90602401612df7565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b909216825261187092918890600401612e40565b6000604051808303818588803b15801561188957600080fd5b505af115801561189d573d6000803e3d6000fd5b50505050505050505050565b60006118d5827f1d1d8b630000000000000000000000000000000000000000000000000000000061217c565b806119055750611905827fec4fc8e30000000000000000000000000000000000000000000000000000000061217c565b92915050565b6000611937837f1d1d8b630000000000000000000000000000000000000000000000000000000061217c565b156119e0578273ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015611987573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ab9190612d72565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050611905565b8273ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611987573d6000803e3d6000fd5b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052610aa49084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915261219f565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f3ceee06c1e37648fcbb6ed52e17b3e1f275a1f8c7b22a84b2b84732431e046b3868686604051611b7793929190612e85565b60405180910390a46110138686868686866122ab565b600080611b98612333565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2ac69ee804d9a7a0984249f508dfab7cb2534b465b6ce1580f99a38ba9c5e6318484604051611c2b929190612ec3565b60405180910390a36105b2848484846123d0565b6000806000835160208501868989f195945050505050565b3415611ce5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5374616e646172644272696467653a2063616e6e6f742073656e642076616c7560448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610214565b611cee876118a9565b15611e3c57611cfd878761190b565b611daf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a401610214565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015260248201859052881690639dc29fac90604401600060405180830381600087803b158015611e1f57600080fd5b505af1158015611e33573d6000803e3d6000fd5b50505050611ed0565b611e5e73ffffffffffffffffffffffffffffffffffffffff881686308661243d565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054611e9c908490612edc565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152600260209081526040808320938b16835292905220555b611ede87878787878661249b565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9216907f0166a07a0000000000000000000000000000000000000000000000000000000090611f42908b908d908c908c908c908b90602401612ef4565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e085901b9092168252611fd592918790600401612e40565b600060405180830381600087803b158015611fef57600080fd5b505af1158015612003573d6000803e3d6000fd5b5050505050505050505050565b6109c987878787878787611c57565b600054610100900460ff166120b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610214565b6003805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560048054929093169116179055565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f35d79ab81f2b2017e19afb5c5571778877782d7a8786f5907f93b0f4702f4f238484604051612168929190612ec3565b60405180910390a36105b284848484612529565b600061218783612588565b8015612198575061219883836125ec565b9392505050565b6000612201826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166126bb9092919063ffffffff16565b805190915015610aa4578080602001905181019061221f9190612dd5565b610aa4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610214565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fd59c65b35445225835c83f50b6ede06a7be047d22e357073e250d9af537518cd86868660405161232393929190612e85565b60405180910390a4505050505050565b603354604080517f4397dfef0000000000000000000000000000000000000000000000000000000081528151600093849373ffffffffffffffffffffffffffffffffffffffff90911692634397dfef92600480830193928290030181865afa1580156123a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123c79190612f4f565b90939092509050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f31b2166ff604fc5672ea5df08a78081d2bc6d746cadce880747f3643d819e83d848460405161242f929190612ec3565b60405180910390a350505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526105b29085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611a7d565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f718594027abd4eaed59f95162563e0cc6d0e8d5b86b1c7be8b1b0ac3343d039686868660405161251393929190612e85565b60405180910390a46110138686868686866126d2565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2849b43074093a05396b6f2a937dee8565b15a48a7b3d4bffb732a5017380af5848460405161242f929190612ec3565b60006125b4827f01ffc9a7000000000000000000000000000000000000000000000000000000006125ec565b801561190557506125e5827fffffffff000000000000000000000000000000000000000000000000000000006125ec565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d915060005190508280156126a4575060208210155b80156126b05750600081115b979650505050505050565b60606126ca848460008561274a565b949350505050565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f7ff126db8024424bbfd9826e8ab82ff59136289ea440b04b39a0df1b03b9cabf86868660405161232393929190612e85565b6060824710156127dc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610214565b73ffffffffffffffffffffffffffffffffffffffff85163b61285a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610214565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516128839190612f84565b60006040518083038185875af1925050503d80600081146128c0576040519150601f19603f3d011682016040523d82523d6000602084013e6128c5565b606091505b50915091506126b0828286606083156128df575081612198565b8251156128ef5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102149190612bf5565b73ffffffffffffffffffffffffffffffffffffffff8116811461294557600080fd5b50565b60008083601f84011261295a57600080fd5b50813567ffffffffffffffff81111561297257600080fd5b60208301915083602082850101111561298a57600080fd5b9250929050565b600080600080600080600060c0888a0312156129ac57600080fd5b87356129b781612923565b965060208801356129c781612923565b955060408801356129d781612923565b945060608801356129e781612923565b93506080880135925060a088013567ffffffffffffffff811115612a0a57600080fd5b612a168a828b01612948565b989b979a50959850939692959293505050565b803563ffffffff81168114612a3d57600080fd5b919050565b600080600060408486031215612a5757600080fd5b612a6084612a29565b9250602084013567ffffffffffffffff811115612a7c57600080fd5b612a8886828701612948565b9497909650939450505050565b600080600080600060808688031215612aad57600080fd5b8535612ab881612923565b94506020860135612ac881612923565b935060408601359250606086013567ffffffffffffffff811115612aeb57600080fd5b612af788828901612948565b969995985093965092949392505050565b600080600080600080600060c0888a031215612b2357600080fd5b8735612b2e81612923565b96506020880135612b3e81612923565b95506040880135612b4e81612923565b945060608801359350612b6360808901612a29565b925060a088013567ffffffffffffffff811115612a0a57600080fd5b60005b83811015612b9a578181015183820152602001612b82565b838111156105b25750506000910152565b60008151808452612bc3816020860160208601612b7f565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006121986020830184612bab565b60008060008060008060a08789031215612c2157600080fd5b8635612c2c81612923565b95506020870135612c3c81612923565b945060408701359350612c5160608801612a29565b9250608087013567ffffffffffffffff811115612c6d57600080fd5b612c7989828a01612948565b979a9699509497509295939492505050565b60008060408385031215612c9e57600080fd5b8235612ca981612923565b91506020830135612cb981612923565b809150509250929050565b60008060008060608587031215612cda57600080fd5b8435612ce581612923565b9350612cf360208601612a29565b9250604085013567ffffffffffffffff811115612d0f57600080fd5b612d1b87828801612948565b95989497509550505050565b600080600060608486031215612d3c57600080fd5b8335612d4781612923565b92506020840135612d5781612923565b91506040840135612d6781612923565b809150509250925092565b600060208284031215612d8457600080fd5b815161219881612923565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015612dd057612dd0612d8f565b500390565b600060208284031215612de757600080fd5b8151801515811461219857600080fd5b600073ffffffffffffffffffffffffffffffffffffffff808716835280861660208401525083604083015260806060830152612e366080830184612bab565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff84168152606060208201526000612e6f6060830185612bab565b905063ffffffff83166040830152949350505050565b73ffffffffffffffffffffffffffffffffffffffff84168152826020820152606060408201526000612eba6060830184612bab565b95945050505050565b8281526040602082015260006126ca6040830184612bab565b60008219821115612eef57612eef612d8f565b500190565b600073ffffffffffffffffffffffffffffffffffffffff80891683528088166020840152808716604084015280861660608401525083608083015260c060a0830152612f4360c0830184612bab565b98975050505050505050565b60008060408385031215612f6257600080fd5b8251612f6d81612923565b602084015190925060ff81168114612cb957600080fd5b60008251612f96818460208701612b7f565b919091019291505056fea164736f6c634300080f000a"; bytes internal constant l1ERC721BridgeCode = - hex"608060405234801561001057600080fd5b50600436106100d45760003560e01c80635d93a3fc11610081578063927ede2d1161005b578063927ede2d14610231578063aa5574521461024f578063c89701a21461026257600080fd5b80635d93a3fc146101cc578063761f4493146102005780637f46ddb21461021357600080fd5b8063485cc955116100b2578063485cc9551461015857806354fd4d501461016b5780635c975abb146101b457600080fd5b806335e80ab3146100d95780633687011a146101235780633cb747bf14610138575b600080fd5b6032546100f99073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b610136610131366004610fe1565b610282565b005b6001546100f99073ffffffffffffffffffffffffffffffffffffffff1681565b610136610166366004611064565b61032e565b6101a76040518060400160405280600c81526020017f322e312e312b626574612e31000000000000000000000000000000000000000081525081565b60405161011a9190611108565b6101bc610518565b604051901515815260200161011a565b6101bc6101da366004611122565b603160209081526000938452604080852082529284528284209052825290205460ff1681565b61013661020e366004611163565b6105b1565b60025473ffffffffffffffffffffffffffffffffffffffff166100f9565b60015473ffffffffffffffffffffffffffffffffffffffff166100f9565b61013661025d3660046111fb565b610a58565b6002546100f99073ffffffffffffffffffffffffffffffffffffffff1681565b333b15610316576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4552433732314272696467653a206163636f756e74206973206e6f742065787460448201527f65726e616c6c79206f776e65640000000000000000000000000000000000000060648201526084015b60405180910390fd5b6103268686333388888888610b30565b505050505050565b600054610100900460ff161580801561034e5750600054600160ff909116105b806103685750303b158015610368575060005460ff166001145b6103f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161030d565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561045257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84161790556104b083734200000000000000000000000000000000000014610e70565b801561051357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b603254604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa158015610588573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ac9190611272565b905090565b60015473ffffffffffffffffffffffffffffffffffffffff16331480156106865750600254600154604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9384169390921691636e296e45916004808201926020929091908290030181865afa15801561064a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061066e9190611294565b73ffffffffffffffffffffffffffffffffffffffff16145b610712576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4552433732314272696467653a2066756e6374696f6e2063616e206f6e6c792060448201527f62652063616c6c65642066726f6d20746865206f746865722062726964676500606482015260840161030d565b61071a610518565b15610781576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4c314552433732314272696467653a2070617573656400000000000000000000604482015260640161030d565b3073ffffffffffffffffffffffffffffffffffffffff881603610826576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4c314552433732314272696467653a206c6f63616c20746f6b656e2063616e6e60448201527f6f742062652073656c6600000000000000000000000000000000000000000000606482015260840161030d565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152603160209081526040808320938a1683529281528282208683529052205460ff1615156001146108f5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4c314552433732314272696467653a20546f6b656e204944206973206e6f742060448201527f657363726f77656420696e20746865204c312042726964676500000000000000606482015260840161030d565b73ffffffffffffffffffffffffffffffffffffffff87811660008181526031602090815260408083208b8616845282528083208884529091529081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517f42842e0e000000000000000000000000000000000000000000000000000000008152306004820152918616602483015260448201859052906342842e0e90606401600060405180830381600087803b1580156109b557600080fd5b505af11580156109c9573d6000803e3d6000fd5b505050508473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff167f1f39bf6707b5d608453e0ae4c067b562bcc4c85c0f562ef5d2c774d2e7f131ac87878787604051610a4794939291906112fa565b60405180910390a450505050505050565b73ffffffffffffffffffffffffffffffffffffffff8516610afb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4552433732314272696467653a206e667420726563697069656e742063616e6e60448201527f6f74206265206164647265737328302900000000000000000000000000000000606482015260840161030d565b610b0b8787338888888888610b30565b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b73ffffffffffffffffffffffffffffffffffffffff8716610bd3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f4c314552433732314272696467653a2072656d6f746520746f6b656e2063616e60448201527f6e6f742062652061646472657373283029000000000000000000000000000000606482015260840161030d565b600063761f449360e01b888a8989898888604051602401610bfa979695949392919061133a565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000959095169490941790935273ffffffffffffffffffffffffffffffffffffffff8c81166000818152603186528381208e8416825286528381208b82529095529382902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905590517f23b872dd000000000000000000000000000000000000000000000000000000008152908a166004820152306024820152604481018890529092506323b872dd90606401600060405180830381600087803b158015610d3a57600080fd5b505af1158015610d4e573d6000803e3d6000fd5b50506001546002546040517f3dbb202b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9283169450633dbb202b9350610db1929091169085908990600401611397565b600060405180830381600087803b158015610dcb57600080fd5b505af1158015610ddf573d6000803e3d6000fd5b505050508673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff167fb7460e2a880f256ebef3406116ff3eee0cee51ebccdc2a40698f87ebb2e9c1a589898888604051610e5d94939291906112fa565b60405180910390a4505050505050505050565b600054610100900460ff16610f07576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161030d565b6001805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560028054929093169116179055565b73ffffffffffffffffffffffffffffffffffffffff81168114610f7c57600080fd5b50565b803563ffffffff81168114610f9357600080fd5b919050565b60008083601f840112610faa57600080fd5b50813567ffffffffffffffff811115610fc257600080fd5b602083019150836020828501011115610fda57600080fd5b9250929050565b60008060008060008060a08789031215610ffa57600080fd5b863561100581610f5a565b9550602087013561101581610f5a565b94506040870135935061102a60608801610f7f565b9250608087013567ffffffffffffffff81111561104657600080fd5b61105289828a01610f98565b979a9699509497509295939492505050565b6000806040838503121561107757600080fd5b823561108281610f5a565b9150602083013561109281610f5a565b809150509250929050565b6000815180845260005b818110156110c3576020818501810151868301820152016110a7565b818111156110d5576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061111b602083018461109d565b9392505050565b60008060006060848603121561113757600080fd5b833561114281610f5a565b9250602084013561115281610f5a565b929592945050506040919091013590565b600080600080600080600060c0888a03121561117e57600080fd5b873561118981610f5a565b9650602088013561119981610f5a565b955060408801356111a981610f5a565b945060608801356111b981610f5a565b93506080880135925060a088013567ffffffffffffffff8111156111dc57600080fd5b6111e88a828b01610f98565b989b979a50959850939692959293505050565b600080600080600080600060c0888a03121561121657600080fd5b873561122181610f5a565b9650602088013561123181610f5a565b9550604088013561124181610f5a565b94506060880135935061125660808901610f7f565b925060a088013567ffffffffffffffff8111156111dc57600080fd5b60006020828403121561128457600080fd5b8151801515811461111b57600080fd5b6000602082840312156112a657600080fd5b815161111b81610f5a565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff851681528360208201526060604082015260006113306060830184866112b1565b9695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff808a1683528089166020840152808816604084015280871660608401525084608083015260c060a083015261138a60c0830184866112b1565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006113c6606083018561109d565b905063ffffffff8316604083015294935050505056fea164736f6c634300080f000a"; +- hex"608060405234801561001057600080fd5b50600436106100d45760003560e01c80635d93a3fc11610081578063927ede2d1161005b578063927ede2d14610231578063aa5574521461024f578063c89701a21461026257600080fd5b80635d93a3fc146101cc578063761f4493146102005780637f46ddb21461021357600080fd5b8063485cc955116100b2578063485cc9551461015857806354fd4d501461016b5780635c975abb146101b457600080fd5b806335e80ab3146100d95780633687011a146101235780633cb747bf14610138575b600080fd5b6032546100f99073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b610136610131366004610fe1565b610282565b005b6001546100f99073ffffffffffffffffffffffffffffffffffffffff1681565b610136610166366004611064565b61032e565b6101a76040518060400160405280600c81526020017f322e312e312b626574612e31000000000000000000000000000000000000000081525081565b60405161011a9190611108565b6101bc610518565b604051901515815260200161011a565b6101bc6101da366004611122565b603160209081526000938452604080852082529284528284209052825290205460ff1681565b61013661020e366004611163565b6105b1565b60025473ffffffffffffffffffffffffffffffffffffffff166100f9565b60015473ffffffffffffffffffffffffffffffffffffffff166100f9565b61013661025d3660046111fb565b610a58565b6002546100f99073ffffffffffffffffffffffffffffffffffffffff1681565b333b15610316576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4552433732314272696467653a206163636f756e74206973206e6f742065787460448201527f65726e616c6c79206f776e65640000000000000000000000000000000000000060648201526084015b60405180910390fd5b6103268686333388888888610b30565b505050505050565b600054610100900460ff161580801561034e5750600054600160ff909116105b806103685750303b158015610368575060005460ff166001145b6103f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161030d565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561045257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84161790556104b083734200000000000000000000000000000000000014610e70565b801561051357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b603254604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa158015610588573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ac9190611272565b905090565b60015473ffffffffffffffffffffffffffffffffffffffff16331480156106865750600254600154604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9384169390921691636e296e45916004808201926020929091908290030181865afa15801561064a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061066e9190611294565b73ffffffffffffffffffffffffffffffffffffffff16145b610712576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4552433732314272696467653a2066756e6374696f6e2063616e206f6e6c792060448201527f62652063616c6c65642066726f6d20746865206f746865722062726964676500606482015260840161030d565b61071a610518565b15610781576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4c314552433732314272696467653a2070617573656400000000000000000000604482015260640161030d565b3073ffffffffffffffffffffffffffffffffffffffff881603610826576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4c314552433732314272696467653a206c6f63616c20746f6b656e2063616e6e60448201527f6f742062652073656c6600000000000000000000000000000000000000000000606482015260840161030d565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152603160209081526040808320938a1683529281528282208683529052205460ff1615156001146108f5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4c314552433732314272696467653a20546f6b656e204944206973206e6f742060448201527f657363726f77656420696e20746865204c312042726964676500000000000000606482015260840161030d565b73ffffffffffffffffffffffffffffffffffffffff87811660008181526031602090815260408083208b8616845282528083208884529091529081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517f42842e0e000000000000000000000000000000000000000000000000000000008152306004820152918616602483015260448201859052906342842e0e90606401600060405180830381600087803b1580156109b557600080fd5b505af11580156109c9573d6000803e3d6000fd5b505050508473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff167f1f39bf6707b5d608453e0ae4c067b562bcc4c85c0f562ef5d2c774d2e7f131ac87878787604051610a4794939291906112fa565b60405180910390a450505050505050565b73ffffffffffffffffffffffffffffffffffffffff8516610afb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4552433732314272696467653a206e667420726563697069656e742063616e6e60448201527f6f74206265206164647265737328302900000000000000000000000000000000606482015260840161030d565b610b0b8787338888888888610b30565b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b73ffffffffffffffffffffffffffffffffffffffff8716610bd3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f4c314552433732314272696467653a2072656d6f746520746f6b656e2063616e60448201527f6e6f742062652061646472657373283029000000000000000000000000000000606482015260840161030d565b600063761f449360e01b888a8989898888604051602401610bfa979695949392919061133a565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000959095169490941790935273ffffffffffffffffffffffffffffffffffffffff8c81166000818152603186528381208e8416825286528381208b82529095529382902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905590517f23b872dd000000000000000000000000000000000000000000000000000000008152908a166004820152306024820152604481018890529092506323b872dd90606401600060405180830381600087803b158015610d3a57600080fd5b505af1158015610d4e573d6000803e3d6000fd5b50506001546002546040517f3dbb202b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9283169450633dbb202b9350610db1929091169085908990600401611397565b600060405180830381600087803b158015610dcb57600080fd5b505af1158015610ddf573d6000803e3d6000fd5b505050508673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff167fb7460e2a880f256ebef3406116ff3eee0cee51ebccdc2a40698f87ebb2e9c1a589898888604051610e5d94939291906112fa565b60405180910390a4505050505050505050565b600054610100900460ff16610f07576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161030d565b6001805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560028054929093169116179055565b73ffffffffffffffffffffffffffffffffffffffff81168114610f7c57600080fd5b50565b803563ffffffff81168114610f9357600080fd5b919050565b60008083601f840112610faa57600080fd5b50813567ffffffffffffffff811115610fc257600080fd5b602083019150836020828501011115610fda57600080fd5b9250929050565b60008060008060008060a08789031215610ffa57600080fd5b863561100581610f5a565b9550602087013561101581610f5a565b94506040870135935061102a60608801610f7f565b9250608087013567ffffffffffffffff81111561104657600080fd5b61105289828a01610f98565b979a9699509497509295939492505050565b6000806040838503121561107757600080fd5b823561108281610f5a565b9150602083013561109281610f5a565b809150509250929050565b6000815180845260005b818110156110c3576020818501810151868301820152016110a7565b818111156110d5576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061111b602083018461109d565b9392505050565b60008060006060848603121561113757600080fd5b833561114281610f5a565b9250602084013561115281610f5a565b929592945050506040919091013590565b600080600080600080600060c0888a03121561117e57600080fd5b873561118981610f5a565b9650602088013561119981610f5a565b955060408801356111a981610f5a565b945060608801356111b981610f5a565b93506080880135925060a088013567ffffffffffffffff8111156111dc57600080fd5b6111e88a828b01610f98565b989b979a50959850939692959293505050565b600080600080600080600060c0888a03121561121657600080fd5b873561122181610f5a565b9650602088013561123181610f5a565b9550604088013561124181610f5a565b94506060880135935061125660808901610f7f565b925060a088013567ffffffffffffffff8111156111dc57600080fd5b60006020828403121561128457600080fd5b8151801515811461111b57600080fd5b6000602082840312156112a657600080fd5b815161111b81610f5a565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff851681528360208201526060604082015260006113306060830184866112b1565b9695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff808a1683528089166020840152808816604084015280871660608401525084608083015260c060a083015261138a60c0830184866112b1565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006113c6606083018561109d565b905063ffffffff8316604083015294935050505056fea164736f6c634300080f000a"; ++ hex"608060405234801561001057600080fd5b50600436106100d45760003560e01c80635d93a3fc11610081578063927ede2d1161005b578063927ede2d14610231578063aa5574521461024f578063c89701a21461026257600080fd5b80635d93a3fc146101cc578063761f4493146102005780637f46ddb21461021357600080fd5b8063485cc955116100b2578063485cc9551461015857806354fd4d501461016b5780635c975abb146101b457600080fd5b806335e80ab3146100d95780633687011a146101235780633cb747bf14610138575b600080fd5b6032546100f99073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b610136610131366004610fe1565b610282565b005b6001546100f99073ffffffffffffffffffffffffffffffffffffffff1681565b610136610166366004611064565b61032e565b6101a76040518060400160405280600c81526020017f322e312e312d626574612e32000000000000000000000000000000000000000081525081565b60405161011a9190611108565b6101bc610518565b604051901515815260200161011a565b6101bc6101da366004611122565b603160209081526000938452604080852082529284528284209052825290205460ff1681565b61013661020e366004611163565b6105b1565b60025473ffffffffffffffffffffffffffffffffffffffff166100f9565b60015473ffffffffffffffffffffffffffffffffffffffff166100f9565b61013661025d3660046111fb565b610a58565b6002546100f99073ffffffffffffffffffffffffffffffffffffffff1681565b333b15610316576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4552433732314272696467653a206163636f756e74206973206e6f742065787460448201527f65726e616c6c79206f776e65640000000000000000000000000000000000000060648201526084015b60405180910390fd5b6103268686333388888888610b30565b505050505050565b600054610100900460ff161580801561034e5750600054600160ff909116105b806103685750303b158015610368575060005460ff166001145b6103f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161030d565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561045257600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84161790556104b083734200000000000000000000000000000000000014610e70565b801561051357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b603254604080517f5c975abb000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff1691635c975abb9160048083019260209291908290030181865afa158015610588573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ac9190611272565b905090565b60015473ffffffffffffffffffffffffffffffffffffffff16331480156106865750600254600154604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9384169390921691636e296e45916004808201926020929091908290030181865afa15801561064a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061066e9190611294565b73ffffffffffffffffffffffffffffffffffffffff16145b610712576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4552433732314272696467653a2066756e6374696f6e2063616e206f6e6c792060448201527f62652063616c6c65642066726f6d20746865206f746865722062726964676500606482015260840161030d565b61071a610518565b15610781576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4c314552433732314272696467653a2070617573656400000000000000000000604482015260640161030d565b3073ffffffffffffffffffffffffffffffffffffffff881603610826576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4c314552433732314272696467653a206c6f63616c20746f6b656e2063616e6e60448201527f6f742062652073656c6600000000000000000000000000000000000000000000606482015260840161030d565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152603160209081526040808320938a1683529281528282208683529052205460ff1615156001146108f5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4c314552433732314272696467653a20546f6b656e204944206973206e6f742060448201527f657363726f77656420696e20746865204c312042726964676500000000000000606482015260840161030d565b73ffffffffffffffffffffffffffffffffffffffff87811660008181526031602090815260408083208b8616845282528083208884529091529081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517f42842e0e000000000000000000000000000000000000000000000000000000008152306004820152918616602483015260448201859052906342842e0e90606401600060405180830381600087803b1580156109b557600080fd5b505af11580156109c9573d6000803e3d6000fd5b505050508473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff167f1f39bf6707b5d608453e0ae4c067b562bcc4c85c0f562ef5d2c774d2e7f131ac87878787604051610a4794939291906112fa565b60405180910390a450505050505050565b73ffffffffffffffffffffffffffffffffffffffff8516610afb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4552433732314272696467653a206e667420726563697069656e742063616e6e60448201527f6f74206265206164647265737328302900000000000000000000000000000000606482015260840161030d565b610b0b8787338888888888610b30565b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b73ffffffffffffffffffffffffffffffffffffffff8716610bd3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f4c314552433732314272696467653a2072656d6f746520746f6b656e2063616e60448201527f6e6f742062652061646472657373283029000000000000000000000000000000606482015260840161030d565b600063761f449360e01b888a8989898888604051602401610bfa979695949392919061133a565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000959095169490941790935273ffffffffffffffffffffffffffffffffffffffff8c81166000818152603186528381208e8416825286528381208b82529095529382902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905590517f23b872dd000000000000000000000000000000000000000000000000000000008152908a166004820152306024820152604481018890529092506323b872dd90606401600060405180830381600087803b158015610d3a57600080fd5b505af1158015610d4e573d6000803e3d6000fd5b50506001546002546040517f3dbb202b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9283169450633dbb202b9350610db1929091169085908990600401611397565b600060405180830381600087803b158015610dcb57600080fd5b505af1158015610ddf573d6000803e3d6000fd5b505050508673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff167fb7460e2a880f256ebef3406116ff3eee0cee51ebccdc2a40698f87ebb2e9c1a589898888604051610e5d94939291906112fa565b60405180910390a4505050505050505050565b600054610100900460ff16610f07576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161030d565b6001805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560028054929093169116179055565b73ffffffffffffffffffffffffffffffffffffffff81168114610f7c57600080fd5b50565b803563ffffffff81168114610f9357600080fd5b919050565b60008083601f840112610faa57600080fd5b50813567ffffffffffffffff811115610fc257600080fd5b602083019150836020828501011115610fda57600080fd5b9250929050565b60008060008060008060a08789031215610ffa57600080fd5b863561100581610f5a565b9550602087013561101581610f5a565b94506040870135935061102a60608801610f7f565b9250608087013567ffffffffffffffff81111561104657600080fd5b61105289828a01610f98565b979a9699509497509295939492505050565b6000806040838503121561107757600080fd5b823561108281610f5a565b9150602083013561109281610f5a565b809150509250929050565b6000815180845260005b818110156110c3576020818501810151868301820152016110a7565b818111156110d5576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061111b602083018461109d565b9392505050565b60008060006060848603121561113757600080fd5b833561114281610f5a565b9250602084013561115281610f5a565b929592945050506040919091013590565b600080600080600080600060c0888a03121561117e57600080fd5b873561118981610f5a565b9650602088013561119981610f5a565b955060408801356111a981610f5a565b945060608801356111b981610f5a565b93506080880135925060a088013567ffffffffffffffff8111156111dc57600080fd5b6111e88a828b01610f98565b989b979a50959850939692959293505050565b600080600080600080600060c0888a03121561121657600080fd5b873561122181610f5a565b9650602088013561123181610f5a565b9550604088013561124181610f5a565b94506060880135935061125660808901610f7f565b925060a088013567ffffffffffffffff8111156111dc57600080fd5b60006020828403121561128457600080fd5b8151801515811461111b57600080fd5b6000602082840312156112a657600080fd5b815161111b81610f5a565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff851681528360208201526060604082015260006113306060830184866112b1565b9695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff808a1683528089166020840152808816604084015280871660608401525084608083015260c060a083015261138a60c0830184866112b1565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006113c6606083018561109d565b905063ffffffff8316604083015294935050505056fea164736f6c634300080f000a"; bytes internal constant optimismPortalCode = - hex"6080604052600436106101635760003560e01c80638c3152e9116100c0578063b69ef8a811610074578063cff0ab9611610059578063cff0ab9614610444578063e965084c146104e5578063e9e05c421461057157600080fd5b8063b69ef8a814610401578063c0c53b8b1461042457600080fd5b80639bf62d82116100a55780639bf62d821461036b578063a14238e714610398578063a35d99df146103c857600080fd5b80638c3152e91461031e5780639b5f694a1461033e57600080fd5b806354fd4d50116101175780636dbffb78116100fc5780636dbffb78146102de57806371cfaa3f146102fe5780638b4c40b01461018857600080fd5b806354fd4d501461026d5780635c975abb146102b957600080fd5b806335e80ab31161014857806335e80ab314610206578063452a9320146102385780634870496f1461024d57600080fd5b8063149f2f221461018f57806333d7e2bd146101af57600080fd5b3661018a576101883334620186a060006040518060200160405280600081525061057f565b005b600080fd5b34801561019b57600080fd5b506101886101aa366004614b97565b610624565b3480156101bb57600080fd5b506037546101dc9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561021257600080fd5b506035546101dc90610100900473ffffffffffffffffffffffffffffffffffffffff1681565b34801561024457600080fd5b506101dc610865565b34801561025957600080fd5b50610188610268366004614ccb565b6108fd565b34801561027957600080fd5b50604080518082018252600c81527f322e382e312d626574612e310000000000000000000000000000000000000000602082015290516101fd9190614e1d565b3480156102c557600080fd5b506102ce610eaa565b60405190151581526020016101fd565b3480156102ea57600080fd5b506102ce6102f9366004614e30565b610f3d565b34801561030a57600080fd5b50610188610319366004614e58565b610ff8565b34801561032a57600080fd5b50610188610339366004614e9e565b6111ba565b34801561034a57600080fd5b506036546101dc9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561037757600080fd5b506032546101dc9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156103a457600080fd5b506102ce6103b3366004614e30565b60336020526000908152604090205460ff1681565b3480156103d457600080fd5b506103e86103e3366004614edb565b611c3c565b60405167ffffffffffffffff90911681526020016101fd565b34801561040d57600080fd5b50610416611c55565b6040519081526020016101fd565b34801561043057600080fd5b5061018861043f366004614ef6565b611caf565b34801561045057600080fd5b506001546104ac906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff92831660208501529116908201526060016101fd565b3480156104f157600080fd5b50610543610500366004614e30565b603460205260009081526040902080546001909101546fffffffffffffffffffffffffffffffff8082169170010000000000000000000000000000000090041683565b604080519384526fffffffffffffffffffffffffffffffff92831660208501529116908201526060016101fd565b61018861057f366004614f41565b8260005a9050600061058f611f19565b50905073ffffffffffffffffffffffffffffffffffffffff811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee148015906105cb57503415155b15610602576040517ff2365b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610610883489898989611fb6565b5061061b8282612162565b50505050505050565b8260005a90506000610634611f19565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8216016106a6576040517f0eaf3c0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87603d60008282546106b89190614fed565b90915550506040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa15801561072a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061074e9190615005565b905061077273ffffffffffffffffffffffffffffffffffffffff831633308c61242f565b61077c8982614fed565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa1580156107e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061080a9190615005565b14610841576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61084f8a8a8a8a8a8a611fb6565b505061085b8282612162565b5050505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f8919061501e565b905090565b610905610eaa565b1561093c576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff16036109a5576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6036546040517fa25ae5570000000000000000000000000000000000000000000000000000000081526004810186905260009173ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa158015610a15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a39919061505b565b519050610a53610a4e368690038601866150c0565b61250b565b8114610ae6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f7074696d69736d506f7274616c3a20696e76616c6964206f7574707574207260448201527f6f6f742070726f6f66000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000610af187612567565b6000818152603460209081526040918290208251606081018452815481526001909101546fffffffffffffffffffffffffffffffff8082169383018490527001000000000000000000000000000000009091041692810192909252919250901580610c075750805160365460408084015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff909116600482015273ffffffffffffffffffffffffffffffffffffffff9091169063a25ae55790602401606060405180830381865afa158015610bdf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c03919061505b565b5114155b610c93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173682060448201527f68617320616c7265616479206265656e2070726f76656e0000000000000000006064820152608401610add565b60408051602081018490526000918101829052606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201209083018190529250610d5c9101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152600182527f0100000000000000000000000000000000000000000000000000000000000000602083015290610d52888a615126565b8a60400135612597565b610de8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a20696e76616c696420776974686472617760448201527f616c20696e636c7573696f6e2070726f6f6600000000000000000000000000006064820152608401610add565b604080516060810182528581526fffffffffffffffffffffffffffffffff42811660208084019182528c831684860190815260008981526034835286812095518655925190518416700100000000000000000000000000000000029316929092176001909301929092558b830151908c0151925173ffffffffffffffffffffffffffffffffffffffff918216939091169186917f67a6208cfcc0801d50f6cbe764733f4fddf66ac0b04442061a8a8c0cb6b63f629190a4505050505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f19573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f891906151aa565b6036546040517fa25ae55700000000000000000000000000000000000000000000000000000000815260048101839052600091610ff29173ffffffffffffffffffffffffffffffffffffffff9091169063a25ae55790602401606060405180830381865afa158015610fb3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fd7919061505b565b602001516fffffffffffffffffffffffffffffffff166125bb565b92915050565b60375473ffffffffffffffffffffffffffffffffffffffff163314611049576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61105562030d40612661565b60405173ffffffffffffffffffffffffffffffffffffffff8516602482015260ff8416604482015260648101839052608481018290526000907342000000000000000000000000000000000000159073deaddeaddeaddeaddeaddeaddeaddeaddead0001907fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32908490819062030d4090829060a401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f71cfaa3f000000000000000000000000000000000000000000000000000000001790529051611172969594939291016151c7565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526111aa91614e1d565b60405180910390a450505050565b565b6111c2610eaa565b156111f9576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60325473ffffffffffffffffffffffffffffffffffffffff1661dead1461124c576040517f9396d15600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061125782612567565b60008181526034602090815260408083208151606081018352815481526001909101546fffffffffffffffffffffffffffffffff80821694830185905270010000000000000000000000000000000090910416918101919091529293509003611342576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206e60448201527f6f74206265656e2070726f76656e2079657400000000000000000000000000006064820152608401610add565b603660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663887862726040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113d39190615005565b81602001516fffffffffffffffffffffffffffffffff16101561149e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604b60248201527f4f7074696d69736d506f7274616c3a207769746864726177616c2074696d657360448201527f74616d70206c657373207468616e204c32204f7261636c65207374617274696e60648201527f672074696d657374616d70000000000000000000000000000000000000000000608482015260a401610add565b6114bd81602001516fffffffffffffffffffffffffffffffff166125bb565b61156f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604560248201527f4f7074696d69736d506f7274616c3a2070726f76656e2077697468647261776160448201527f6c2066696e616c697a6174696f6e20706572696f6420686173206e6f7420656c60648201527f6170736564000000000000000000000000000000000000000000000000000000608482015260a401610add565b60365460408281015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff909116600482015260009173ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa1580156115f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061161a919061505b565b82518151919250146116d4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604960248201527f4f7074696d69736d506f7274616c3a206f757470757420726f6f742070726f7660448201527f656e206973206e6f74207468652073616d652061732063757272656e74206f7560648201527f7470757420726f6f740000000000000000000000000000000000000000000000608482015260a401610add565b6116f381602001516fffffffffffffffffffffffffffffffff166125bb565b6117a5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f4f7074696d69736d506f7274616c3a206f75747075742070726f706f73616c2060448201527f66696e616c697a6174696f6e20706572696f6420686173206e6f7420656c617060648201527f7365640000000000000000000000000000000000000000000000000000000000608482015260a401610add565b60008381526033602052604090205460ff1615611844576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206160448201527f6c7265616479206265656e2066696e616c697a656400000000000000000000006064820152608401610add565b6000838152603360209081526040822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558501516032805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff0000000000000000000000000000000000000000909216919091179055806118cf611f19565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8216016119325761192b8660400151876080015188606001518960a001516126c3565b9150611b85565b8073ffffffffffffffffffffffffffffffffffffffff16866040015173ffffffffffffffffffffffffffffffffffffffff160361199b576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606086015115611b5c578560600151603d60008282546119bb919061522c565b90915550506040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015611a2d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a519190615005565b9050611a86876040015188606001518473ffffffffffffffffffffffffffffffffffffffff166127219092919063ffffffff16565b6060870151611a95908261522c565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa158015611aff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b239190615005565b14611b5a576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b60a08601515115611b805761192b8660400151876080015160008960a001516126c3565b600191505b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405185907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b90611be790851515815260200190565b60405180910390a281158015611bfd5750326001145b15611c34576040517feeae4ed300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000611c49826010615243565b610ff290615208615273565b600080611c60611f19565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff821601611ca7574791505090565b5050603d5490565b600054610100900460ff1615808015611ccf5750600054600160ff909116105b80611ce95750303b158015611ce9575060005460ff166001145b611d75576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610add565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015611dd357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603680547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff8781169190911790925560378054909116858316179055603580547fffffffffffffffffffffff0000000000000000000000000000000000000000ff166101008584160217905560325416611e8c57603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790555b611e9461277c565b8015611ef757600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b603754604080517f4397dfef0000000000000000000000000000000000000000000000000000000081528151600093849373ffffffffffffffffffffffffffffffffffffffff90911692634397dfef92600480830193928290030181865afa158015611f89573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fad919061529f565b90939092509050565b818015611fd8575073ffffffffffffffffffffffffffffffffffffffff861615155b1561200f576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6120198151611c3c565b67ffffffffffffffff168367ffffffffffffffff161015612066576040517f4929b80800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6201d4c0815111156120a4576040517f73052b0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b333281146120c5575033731111000000000000000000000000000000001111015b600086868686866040516020016120e09594939291906151c7565b604051602081830303815290604052905060008873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32846040516121509190614e1d565b60405180910390a45050505050505050565b600154600090612198907801000000000000000000000000000000000000000000000000900467ffffffffffffffff164361522c565b905060006121a461288f565b90506000816020015160ff16826000015163ffffffff166121c59190615308565b905082156122fc576001546000906121fc908390700100000000000000000000000000000000900467ffffffffffffffff16615370565b90506000836040015160ff168361221391906153e4565b6001546122339084906fffffffffffffffffffffffffffffffff166153e4565b61223d9190615308565b60015490915060009061228e906122679084906fffffffffffffffffffffffffffffffff166154a0565b866060015163ffffffff168760a001516fffffffffffffffffffffffffffffffff16612950565b905060018611156122bd576122ba61226782876040015160ff1660018a6122b5919061522c565b61296f565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760015550505b6001805486919060109061232f908490700100000000000000000000000000000000900467ffffffffffffffff16615273565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550816000015163ffffffff16600160000160109054906101000a900467ffffffffffffffff1667ffffffffffffffff1613156123bc576040517f77ebef4d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001546000906123e8906fffffffffffffffffffffffffffffffff1667ffffffffffffffff8816615514565b905060006123fa48633b9aca006129c4565b6124049083615551565b905060005a612413908861522c565b90508082111561085b5761085b61242a828461522c565b6129db565b60405173ffffffffffffffffffffffffffffffffffffffff80851660248301528316604482015260648101829052611ef79085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152612a04565b6000816000015182602001518360400151846060015160405160200161254a949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b80516020808301516040808501516060860151608087015160a0880151935160009761254a979096959101615565565b6000806125a386612b10565b90506125b181868686612b42565b9695505050505050565b603654604080517ff4daa291000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163f4daa2919160048083019260209291908290030181865afa15801561262b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061264f9190615005565b6126599083614fed565b421192915050565b6001805463ffffffff8316919060109061269a908490700100000000000000000000000000000000900467ffffffffffffffff16615273565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555050565b60008060006126d3866000612b72565b905080612709576308c379a06000526020805278185361666543616c6c3a204e6f7420656e6f756768206761736058526064601cfd5b600080855160208701888b5af1979650505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526127779084907fa9059cbb0000000000000000000000000000000000000000000000000000000090606401612489565b505050565b600054610100900460ff16612813576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610add565b6001547801000000000000000000000000000000000000000000000000900467ffffffffffffffff166000036111b85760408051606081018252633b9aca00808252600060208301524367ffffffffffffffff169190920181905278010000000000000000000000000000000000000000000000000217600155565b6040805160c08082018352600080835260208301819052828401819052606083018190526080830181905260a083015260375483517fcc731b020000000000000000000000000000000000000000000000000000000081529351929373ffffffffffffffffffffffffffffffffffffffff9091169263cc731b02926004808401939192918290030181865afa15801561292c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f891906155d0565b600061296561295f8585612b90565b83612ba0565b90505b9392505050565b6000670de0b6b3a76400006129b06129878583615308565b61299990670de0b6b3a7640000615370565b6129ab85670de0b6b3a76400006153e4565b612baf565b6129ba90866153e4565b6129659190615308565b6000818310156129d45781612968565b5090919050565b6000805a90505b825a6129ee908361522c565b1015612777576129fd82615673565b91506129e2565b6000612a66826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612be09092919063ffffffff16565b8051909150156127775780806020019051810190612a8491906151aa565b612777576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610add565b60608180519060200120604051602001612b2c91815260200190565b6040516020818303038152906040529050919050565b6000612b6984612b53878686612bef565b8051602091820120825192909101919091201490565b95945050505050565b600080603f83619c4001026040850201603f5a021015949350505050565b6000818312156129d45781612968565b60008183126129d45781612968565b6000612968670de0b6b3a764000083612bc78661366d565b612bd191906153e4565b612bdb9190615308565b6138b1565b60606129658484600085613af0565b60606000845111612c5c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4d65726b6c65547269653a20656d707479206b657900000000000000000000006044820152606401610add565b6000612c6784613c86565b90506000612c7486613d72565b9050600084604051602001612c8b91815260200190565b60405160208183030381529060405290506000805b84518110156135e4576000858281518110612cbd57612cbd6156ab565b602002602001015190508451831115612d58576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4d65726b6c65547269653a206b657920696e646578206578636565647320746f60448201527f74616c206b6579206c656e6774680000000000000000000000000000000000006064820152608401610add565b82600003612e115780518051602091820120604051612da692612d8092910190815260200190565b604051602081830303815290604052858051602091820120825192909101919091201490565b612e0c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4d65726b6c65547269653a20696e76616c696420726f6f7420686173680000006044820152606401610add565b612f68565b805151602011612ec75780518051602091820120604051612e3b92612d8092910190815260200190565b612e0c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d65726b6c65547269653a20696e76616c6964206c6172676520696e7465726e60448201527f616c2068617368000000000000000000000000000000000000000000000000006064820152608401610add565b805184516020808701919091208251919092012014612f68576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4d65726b6c65547269653a20696e76616c696420696e7465726e616c206e6f6460448201527f65206861736800000000000000000000000000000000000000000000000000006064820152608401610add565b612f7460106001614fed565b8160200151510361315057845183036130e857612fae8160200151601081518110612fa157612fa16156ab565b6020026020010151613dd5565b96506000875111613041576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603b60248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286272616e63682900000000006064820152608401610add565b6001865161304f919061522c565b82146130dd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286272616e6368290000000000006064820152608401610add565b505050505050612968565b60008584815181106130fc576130fc6156ab565b602001015160f81c60f81b60f81c9050600082602001518260ff1681518110613127576131276156ab565b6020026020010151905061313a81613e89565b9550613147600186614fed565b945050506135d1565b60028160200151510361354957600061316882613eae565b905060008160008151811061317f5761317f6156ab565b016020015160f81c905060006131966002836156da565b6131a19060026156fc565b905060006131b2848360ff16613ed2565b905060006131c08a89613ed2565b905060006131ce8383613f08565b905080835114613260576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a20706174682072656d61696e646572206d7573742060448201527f736861726520616c6c206e6962626c65732077697468206b65790000000000006064820152608401610add565b60ff851660021480613275575060ff85166003145b15613464578082511461330a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f4d65726b6c65547269653a206b65792072656d61696e646572206d757374206260448201527f65206964656e746963616c20746f20706174682072656d61696e6465720000006064820152608401610add565b6133248760200151600181518110612fa157612fa16156ab565b9c5060008d51116133b7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286c65616629000000000000006064820152608401610add565b60018c516133c5919061522c565b8814613453576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286c6561662900000000000000006064820152608401610add565b505050505050505050505050612968565b60ff85161580613477575060ff85166001145b156134b6576134a38760200151600181518110613496576134966156ab565b6020026020010151613e89565b99506134af818a614fed565b985061353e565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4d65726b6c65547269653a2072656365697665642061206e6f6465207769746860448201527f20616e20756e6b6e6f776e2070726566697800000000000000000000000000006064820152608401610add565b5050505050506135d1565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4d65726b6c65547269653a20726563656976656420616e20756e70617273656160448201527f626c65206e6f64650000000000000000000000000000000000000000000000006064820152608401610add565b50806135dc81615673565b915050612ca0565b506040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4d65726b6c65547269653a2072616e206f7574206f662070726f6f6620656c6560448201527f6d656e74730000000000000000000000000000000000000000000000000000006064820152608401610add565b60008082136136d8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401610add565b600060606136e584613fbc565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c182136138e257506000919050565b680755bf798b4a1bf1e58212613954576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4558505f4f564552464c4f5700000000000000000000000000000000000000006044820152606401610add565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b606082471015613b82576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610add565b73ffffffffffffffffffffffffffffffffffffffff85163b613c00576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610add565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051613c29919061571f565b60006040518083038185875af1925050503d8060008114613c66576040519150601f19603f3d011682016040523d82523d6000602084013e613c6b565b606091505b5091509150613c7b828286614092565b979650505050505050565b80516060908067ffffffffffffffff811115613ca457613ca4614a8b565b604051908082528060200260200182016040528015613ce957816020015b6040805180820190915260608082526020820152815260200190600190039081613cc25790505b50915060005b81811015613d6b576040518060400160405280858381518110613d1457613d146156ab565b60200260200101518152602001613d43868481518110613d3657613d366156ab565b60200260200101516140e5565b815250838281518110613d5857613d586156ab565b6020908102919091010152600101613cef565b5050919050565b606080604051905082518060011b603f8101601f1916830160405280835250602084016020830160005b83811015613dca578060011b82018184015160001a8060041c8253600f811660018301535050600101613d9c565b509295945050505050565b60606000806000613de5856140f8565b919450925090506000816001811115613e0057613e0061573b565b14613e37576040517f1ff9b2e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613e418284614fed565b855114613e7a576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612b6985602001518484614596565b60606020826000015110613ea557613ea082613dd5565b610ff2565b610ff28261462a565b6060610ff2613ecd8360200151600081518110612fa157612fa16156ab565b613d72565b606082518210613ef15750604080516020810190915260008152610ff2565b6129688383848651613f03919061522c565b614640565b6000808251845110613f1b578251613f1e565b83515b90505b8082108015613fa55750828281518110613f3d57613f3d6156ab565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916848381518110613f7c57613f7c6156ab565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b15613fb557816001019150613f21565b5092915050565b6000808211614027576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401610add565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b606083156140a1575081612968565b8251156140b15782518084602001fd5b816040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610add9190614e1d565b6060610ff26140f383614818565b614885565b6000806000836000015160000361413b576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020840151805160001a607f811161416057600060016000945094509450505061458f565b60b7811161427657600061417560808361522c565b9050808760000151116141b4576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001838101517fff0000000000000000000000000000000000000000000000000000000000000016908214801561422c57507f80000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000008216105b15614263576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506001955093506000925061458f915050565b60bf81116143d457600061428b60b78361522c565b9050808760000151116142ca576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff0000000000000000000000000000000000000000000000000000000000000016600081900361432c576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c60378111614374576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61437e8184614fed565b8951116143b7576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6143c2836001614fed565b975095506000945061458f9350505050565b60f781116144395760006143e960c08361522c565b905080876000015111614428576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60019550935084925061458f915050565b600061444660f78361522c565b905080876000015111614485576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff000000000000000000000000000000000000000000000000000000000000001660008190036144e7576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c6037811161452f576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6145398184614fed565b895111614572576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61457d836001614fed565b975095506001945061458f9350505050565b9193909250565b60608167ffffffffffffffff8111156145b1576145b1614a8b565b6040519080825280601f01601f1916602001820160405280156145db576020820181803683370190505b50905081156129685760006145f08486614fed565b90506020820160005b848110156146115782810151828201526020016145f9565b84811115614620576000858301525b5050509392505050565b6060610ff2826020015160008460000151614596565b60608182601f0110156146af576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610add565b82828401101561471b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610add565b81830184511015614788576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401610add565b6060821580156147a7576040519150600082526020820160405261480f565b6040519150601f8416801560200281840101858101878315602002848b0101015b818310156147e05780518352602092830192016147c8565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b60408051808201909152600080825260208201528151600003614867576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50604080518082019091528151815260209182019181019190915290565b60606000806000614895856140f8565b9194509250905060018160018111156148b0576148b061573b565b146148e7576040517f4b9c6abe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84516148f38385614fed565b1461492a576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516020808252610420820190925290816020015b60408051808201909152600080825260208201528152602001906001900390816149415790505093506000835b8651811015614a2f576000806149b46040518060400160405280858c60000151614998919061522c565b8152602001858c602001516149ad9190614fed565b90526140f8565b5091509150604051806040016040528083836149d09190614fed565b8152602001848b602001516149e59190614fed565b8152508885815181106149fa576149fa6156ab565b6020908102919091010152614a10600185614fed565b9350614a1c8183614fed565b614a269084614fed565b9250505061496e565b50845250919392505050565b73ffffffffffffffffffffffffffffffffffffffff81168114614a5d57600080fd5b50565b803567ffffffffffffffff81168114614a7857600080fd5b919050565b8015158114614a5d57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614b0157614b01614a8b565b604052919050565b600082601f830112614b1a57600080fd5b813567ffffffffffffffff811115614b3457614b34614a8b565b614b6560207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601614aba565b818152846020838601011115614b7a57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060008060c08789031215614bb057600080fd5b8635614bbb81614a3b565b95506020870135945060408701359350614bd760608801614a60565b92506080870135614be781614a7d565b915060a087013567ffffffffffffffff811115614c0357600080fd5b614c0f89828a01614b09565b9150509295509295509295565b600060c08284031215614c2e57600080fd5b60405160c0810167ffffffffffffffff8282108183111715614c5257614c52614a8b565b816040528293508435835260208501359150614c6d82614a3b565b81602084015260408501359150614c8382614a3b565b816040840152606085013560608401526080850135608084015260a0850135915080821115614cb157600080fd5b50614cbe85828601614b09565b60a0830152505092915050565b600080600080600085870360e0811215614ce457600080fd5b863567ffffffffffffffff80821115614cfc57600080fd5b614d088a838b01614c1c565b97506020890135965060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc084011215614d4157600080fd5b60408901955060c0890135925080831115614d5b57600080fd5b828901925089601f840112614d6f57600080fd5b8235915080821115614d8057600080fd5b508860208260051b8401011115614d9657600080fd5b959894975092955050506020019190565b60005b83811015614dc2578181015183820152602001614daa565b83811115611ef75750506000910152565b60008151808452614deb816020860160208601614da7565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006129686020830184614dd3565b600060208284031215614e4257600080fd5b5035919050565b60ff81168114614a5d57600080fd5b60008060008060808587031215614e6e57600080fd5b8435614e7981614a3b565b93506020850135614e8981614e49565b93969395505050506040820135916060013590565b600060208284031215614eb057600080fd5b813567ffffffffffffffff811115614ec757600080fd5b614ed384828501614c1c565b949350505050565b600060208284031215614eed57600080fd5b61296882614a60565b600080600060608486031215614f0b57600080fd5b8335614f1681614a3b565b92506020840135614f2681614a3b565b91506040840135614f3681614a3b565b809150509250925092565b600080600080600060a08688031215614f5957600080fd5b8535614f6481614a3b565b945060208601359350614f7960408701614a60565b92506060860135614f8981614a7d565b9150608086013567ffffffffffffffff811115614fa557600080fd5b614fb188828901614b09565b9150509295509295909350565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561500057615000614fbe565b500190565b60006020828403121561501757600080fd5b5051919050565b60006020828403121561503057600080fd5b815161296881614a3b565b80516fffffffffffffffffffffffffffffffff81168114614a7857600080fd5b60006060828403121561506d57600080fd5b6040516060810181811067ffffffffffffffff8211171561509057615090614a8b565b604052825181526150a36020840161503b565b60208201526150b46040840161503b565b60408201529392505050565b6000608082840312156150d257600080fd5b6040516080810181811067ffffffffffffffff821117156150f5576150f5614a8b565b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b600067ffffffffffffffff8084111561514157615141614a8b565b8360051b6020615152818301614aba565b86815291850191818101903684111561516a57600080fd5b865b8481101561519e578035868111156151845760008081fd5b61519036828b01614b09565b84525091830191830161516c565b50979650505050505050565b6000602082840312156151bc57600080fd5b815161296881614a7d565b8581528460208201527fffffffffffffffff0000000000000000000000000000000000000000000000008460c01b16604082015282151560f81b60488201526000825161521b816049850160208701614da7565b919091016049019695505050505050565b60008282101561523e5761523e614fbe565b500390565b600067ffffffffffffffff8083168185168183048111821515161561526a5761526a614fbe565b02949350505050565b600067ffffffffffffffff80831681851680830382111561529657615296614fbe565b01949350505050565b600080604083850312156152b257600080fd5b82516152bd81614a3b565b60208401519092506152ce81614e49565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082615317576153176152d9565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f80000000000000000000000000000000000000000000000000000000000000008314161561536b5761536b614fbe565b500590565b6000808312837f8000000000000000000000000000000000000000000000000000000000000000018312811516156153aa576153aa614fbe565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0183138116156153de576153de614fbe565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60008413600084138583048511828216161561542557615425614fbe565b7f8000000000000000000000000000000000000000000000000000000000000000600087128682058812818416161561546057615460614fbe565b6000871292508782058712848416161561547c5761547c614fbe565b8785058712818416161561549257615492614fbe565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038413811516156154da576154da614fbe565b827f800000000000000000000000000000000000000000000000000000000000000003841281161561550e5761550e614fbe565b50500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561554c5761554c614fbe565b500290565b600082615560576155606152d9565b500490565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a08301526155b060c0830184614dd3565b98975050505050505050565b805163ffffffff81168114614a7857600080fd5b600060c082840312156155e257600080fd5b60405160c0810181811067ffffffffffffffff8211171561560557615605614a8b565b604052615611836155bc565b8152602083015161562181614e49565b6020820152604083015161563481614e49565b6040820152615645606084016155bc565b6060820152615656608084016155bc565b608082015261566760a0840161503b565b60a08201529392505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036156a4576156a4614fbe565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060ff8316806156ed576156ed6152d9565b8060ff84160691505092915050565b600060ff821660ff84168082101561571657615716614fbe565b90039392505050565b60008251615731818460208701614da7565b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea164736f6c634300080f000a"; -+ hex"6080604052600436106101635760003560e01c80638c3152e9116100c0578063b69ef8a811610074578063cff0ab9611610059578063cff0ab9614610444578063e965084c146104e5578063e9e05c421461057157600080fd5b8063b69ef8a814610401578063cf756fdf1461042457600080fd5b80639bf62d82116100a55780639bf62d821461036b578063a14238e714610398578063a35d99df146103c857600080fd5b80638c3152e91461031e5780639b5f694a1461033e57600080fd5b806354fd4d50116101175780636dbffb78116100fc5780636dbffb78146102de57806371cfaa3f146102fe5780638b4c40b01461018857600080fd5b806354fd4d501461026d5780635c975abb146102b957600080fd5b806335e80ab31161014857806335e80ab314610206578063452a9320146102385780634870496f1461024d57600080fd5b8063149f2f221461018f57806333d7e2bd146101af57600080fd5b3661018a576101883334620186a060006040518060200160405280600081525061057f565b005b600080fd5b34801561019b57600080fd5b506101886101aa366004614ba3565b610624565b3480156101bb57600080fd5b506037546101dc9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561021257600080fd5b506035546101dc90610100900473ffffffffffffffffffffffffffffffffffffffff1681565b34801561024457600080fd5b506101dc610865565b34801561025957600080fd5b50610188610268366004614cd7565b6108fd565b34801561027957600080fd5b50604080518082018252600c81527f322e382e312d626574612e310000000000000000000000000000000000000000602082015290516101fd9190614e29565b3480156102c557600080fd5b506102ce610eaa565b60405190151581526020016101fd565b3480156102ea57600080fd5b506102ce6102f9366004614e3c565b610f3d565b34801561030a57600080fd5b50610188610319366004614e64565b610ff8565b34801561032a57600080fd5b50610188610339366004614eaa565b6111ba565b34801561034a57600080fd5b506036546101dc9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561037757600080fd5b506032546101dc9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156103a457600080fd5b506102ce6103b3366004614e3c565b60336020526000908152604090205460ff1681565b3480156103d457600080fd5b506103e86103e3366004614ee7565b611c3c565b60405167ffffffffffffffff90911681526020016101fd565b34801561040d57600080fd5b50610416611c55565b6040519081526020016101fd565b34801561043057600080fd5b5061018861043f366004614f02565b611caf565b34801561045057600080fd5b506001546104ac906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff92831660208501529116908201526060016101fd565b3480156104f157600080fd5b50610543610500366004614e3c565b603460205260009081526040902080546001909101546fffffffffffffffffffffffffffffffff8082169170010000000000000000000000000000000090041683565b604080519384526fffffffffffffffffffffffffffffffff92831660208501529116908201526060016101fd565b61018861057f366004614f53565b8260005a9050600061058f611f1f565b50905073ffffffffffffffffffffffffffffffffffffffff811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee148015906105cb57503415155b15610602576040517ff2365b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610610883489898989611fbc565b5061061b8282612168565b50505050505050565b8260005a90506000610634611f1f565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8216016106a6576040517f0eaf3c0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87603d60008282546106b89190614fff565b90915550506040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa15801561072a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061074e9190615017565b905061077273ffffffffffffffffffffffffffffffffffffffff831633308c612435565b61077c8982614fff565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa1580156107e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061080a9190615017565b14610841576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61084f8a8a8a8a8a8a611fbc565b505061085b8282612168565b5050505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f89190615030565b905090565b610905610eaa565b1561093c576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff16036109a5576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6036546040517fa25ae5570000000000000000000000000000000000000000000000000000000081526004810186905260009173ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa158015610a15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a39919061506d565b519050610a53610a4e368690038601866150d2565b612517565b8114610ae6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f7074696d69736d506f7274616c3a20696e76616c6964206f7574707574207260448201527f6f6f742070726f6f66000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000610af187612573565b6000818152603460209081526040918290208251606081018452815481526001909101546fffffffffffffffffffffffffffffffff8082169383018490527001000000000000000000000000000000009091041692810192909252919250901580610c075750805160365460408084015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff909116600482015273ffffffffffffffffffffffffffffffffffffffff9091169063a25ae55790602401606060405180830381865afa158015610bdf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c03919061506d565b5114155b610c93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173682060448201527f68617320616c7265616479206265656e2070726f76656e0000000000000000006064820152608401610add565b60408051602081018490526000918101829052606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201209083018190529250610d5c9101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152600182527f0100000000000000000000000000000000000000000000000000000000000000602083015290610d52888a615138565b8a604001356125a3565b610de8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a20696e76616c696420776974686472617760448201527f616c20696e636c7573696f6e2070726f6f6600000000000000000000000000006064820152608401610add565b604080516060810182528581526fffffffffffffffffffffffffffffffff42811660208084019182528c831684860190815260008981526034835286812095518655925190518416700100000000000000000000000000000000029316929092176001909301929092558b830151908c0151925173ffffffffffffffffffffffffffffffffffffffff918216939091169186917f67a6208cfcc0801d50f6cbe764733f4fddf66ac0b04442061a8a8c0cb6b63f629190a4505050505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f19573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f891906151bc565b6036546040517fa25ae55700000000000000000000000000000000000000000000000000000000815260048101839052600091610ff29173ffffffffffffffffffffffffffffffffffffffff9091169063a25ae55790602401606060405180830381865afa158015610fb3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fd7919061506d565b602001516fffffffffffffffffffffffffffffffff166125c7565b92915050565b60375473ffffffffffffffffffffffffffffffffffffffff163314611049576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61105562030d4061266d565b60405173ffffffffffffffffffffffffffffffffffffffff8516602482015260ff8416604482015260648101839052608481018290526000907342000000000000000000000000000000000000159073deaddeaddeaddeaddeaddeaddeaddeaddead0001907fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32908490819062030d4090829060a401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f71cfaa3f000000000000000000000000000000000000000000000000000000001790529051611172969594939291016151d9565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526111aa91614e29565b60405180910390a450505050565b565b6111c2610eaa565b156111f9576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60325473ffffffffffffffffffffffffffffffffffffffff1661dead1461124c576040517f9396d15600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061125782612573565b60008181526034602090815260408083208151606081018352815481526001909101546fffffffffffffffffffffffffffffffff80821694830185905270010000000000000000000000000000000090910416918101919091529293509003611342576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206e60448201527f6f74206265656e2070726f76656e2079657400000000000000000000000000006064820152608401610add565b603660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663887862726040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113d39190615017565b81602001516fffffffffffffffffffffffffffffffff16101561149e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604b60248201527f4f7074696d69736d506f7274616c3a207769746864726177616c2074696d657360448201527f74616d70206c657373207468616e204c32204f7261636c65207374617274696e60648201527f672074696d657374616d70000000000000000000000000000000000000000000608482015260a401610add565b6114bd81602001516fffffffffffffffffffffffffffffffff166125c7565b61156f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604560248201527f4f7074696d69736d506f7274616c3a2070726f76656e2077697468647261776160448201527f6c2066696e616c697a6174696f6e20706572696f6420686173206e6f7420656c60648201527f6170736564000000000000000000000000000000000000000000000000000000608482015260a401610add565b60365460408281015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff909116600482015260009173ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa1580156115f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061161a919061506d565b82518151919250146116d4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604960248201527f4f7074696d69736d506f7274616c3a206f757470757420726f6f742070726f7660448201527f656e206973206e6f74207468652073616d652061732063757272656e74206f7560648201527f7470757420726f6f740000000000000000000000000000000000000000000000608482015260a401610add565b6116f381602001516fffffffffffffffffffffffffffffffff166125c7565b6117a5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f4f7074696d69736d506f7274616c3a206f75747075742070726f706f73616c2060448201527f66696e616c697a6174696f6e20706572696f6420686173206e6f7420656c617060648201527f7365640000000000000000000000000000000000000000000000000000000000608482015260a401610add565b60008381526033602052604090205460ff1615611844576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206160448201527f6c7265616479206265656e2066696e616c697a656400000000000000000000006064820152608401610add565b6000838152603360209081526040822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558501516032805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff0000000000000000000000000000000000000000909216919091179055806118cf611f1f565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8216016119325761192b8660400151876080015188606001518960a001516126cf565b9150611b85565b8073ffffffffffffffffffffffffffffffffffffffff16866040015173ffffffffffffffffffffffffffffffffffffffff160361199b576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606086015115611b5c578560600151603d60008282546119bb919061523e565b90915550506040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015611a2d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a519190615017565b9050611a86876040015188606001518473ffffffffffffffffffffffffffffffffffffffff1661272d9092919063ffffffff16565b6060870151611a95908261523e565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa158015611aff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b239190615017565b14611b5a576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b60a08601515115611b805761192b8660400151876080015160008960a001516126cf565b600191505b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405185907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b90611be790851515815260200190565b60405180910390a281158015611bfd5750326001145b15611c34576040517feeae4ed300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000611c49826010615255565b610ff290615208615285565b600080611c60611f1f565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff821601611ca7574791505090565b5050603d5490565b600054610100900460ff1615808015611ccf5750600054600160ff909116105b80611ce95750303b158015611ce9575060005460ff166001145b611d75576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610add565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015611dd357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603680547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff8881169190911790925560378054909116868316179055603580547fffffffffffffffffffffff0000000000000000000000000000000000000000ff166101008684160217905560325416611e8c57603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790555b603d829055611e99612788565b8015611efc57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b603754604080517f4397dfef0000000000000000000000000000000000000000000000000000000081528151600093849373ffffffffffffffffffffffffffffffffffffffff90911692634397dfef92600480830193928290030181865afa158015611f8f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fb391906152b1565b90939092509050565b818015611fde575073ffffffffffffffffffffffffffffffffffffffff861615155b15612015576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61201f8151611c3c565b67ffffffffffffffff168367ffffffffffffffff16101561206c576040517f4929b80800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6201d4c0815111156120aa576040517f73052b0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b333281146120cb575033731111000000000000000000000000000000001111015b600086868686866040516020016120e69594939291906151d9565b604051602081830303815290604052905060008873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32846040516121569190614e29565b60405180910390a45050505050505050565b60015460009061219e907801000000000000000000000000000000000000000000000000900467ffffffffffffffff164361523e565b905060006121aa61289b565b90506000816020015160ff16826000015163ffffffff166121cb919061531a565b9050821561230257600154600090612202908390700100000000000000000000000000000000900467ffffffffffffffff16615382565b90506000836040015160ff168361221991906153f6565b6001546122399084906fffffffffffffffffffffffffffffffff166153f6565b612243919061531a565b6001549091506000906122949061226d9084906fffffffffffffffffffffffffffffffff166154b2565b866060015163ffffffff168760a001516fffffffffffffffffffffffffffffffff1661295c565b905060018611156122c3576122c061226d82876040015160ff1660018a6122bb919061523e565b61297b565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760015550505b60018054869190601090612335908490700100000000000000000000000000000000900467ffffffffffffffff16615285565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550816000015163ffffffff16600160000160109054906101000a900467ffffffffffffffff1667ffffffffffffffff1613156123c2576040517f77ebef4d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001546000906123ee906fffffffffffffffffffffffffffffffff1667ffffffffffffffff8816615526565b9050600061240048633b9aca006129d0565b61240a9083615563565b905060005a612419908861523e565b90508082111561085b5761085b612430828461523e565b6129e7565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526125119085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152612a10565b50505050565b60008160000151826020015183604001518460600151604051602001612556949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b80516020808301516040808501516060860151608087015160a08801519351600097612556979096959101615577565b6000806125af86612b1c565b90506125bd81868686612b4e565b9695505050505050565b603654604080517ff4daa291000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163f4daa2919160048083019260209291908290030181865afa158015612637573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061265b9190615017565b6126659083614fff565b421192915050565b6001805463ffffffff831691906010906126a6908490700100000000000000000000000000000000900467ffffffffffffffff16615285565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555050565b60008060006126df866000612b7e565b905080612715576308c379a06000526020805278185361666543616c6c3a204e6f7420656e6f756768206761736058526064601cfd5b600080855160208701888b5af1979650505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526127839084907fa9059cbb000000000000000000000000000000000000000000000000000000009060640161248f565b505050565b600054610100900460ff1661281f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610add565b6001547801000000000000000000000000000000000000000000000000900467ffffffffffffffff166000036111b85760408051606081018252633b9aca00808252600060208301524367ffffffffffffffff169190920181905278010000000000000000000000000000000000000000000000000217600155565b6040805160c08082018352600080835260208301819052828401819052606083018190526080830181905260a083015260375483517fcc731b020000000000000000000000000000000000000000000000000000000081529351929373ffffffffffffffffffffffffffffffffffffffff9091169263cc731b02926004808401939192918290030181865afa158015612938573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f891906155e2565b600061297161296b8585612b9c565b83612bac565b90505b9392505050565b6000670de0b6b3a76400006129bc612993858361531a565b6129a590670de0b6b3a7640000615382565b6129b785670de0b6b3a76400006153f6565b612bbb565b6129c690866153f6565b612971919061531a565b6000818310156129e05781612974565b5090919050565b6000805a90505b825a6129fa908361523e565b101561278357612a0982615685565b91506129ee565b6000612a72826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612bec9092919063ffffffff16565b8051909150156127835780806020019051810190612a9091906151bc565b612783576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610add565b60608180519060200120604051602001612b3891815260200190565b6040516020818303038152906040529050919050565b6000612b7584612b5f878686612bfb565b8051602091820120825192909101919091201490565b95945050505050565b600080603f83619c4001026040850201603f5a021015949350505050565b6000818312156129e05781612974565b60008183126129e05781612974565b6000612974670de0b6b3a764000083612bd386613679565b612bdd91906153f6565b612be7919061531a565b6138bd565b60606129718484600085613afc565b60606000845111612c68576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4d65726b6c65547269653a20656d707479206b657900000000000000000000006044820152606401610add565b6000612c7384613c92565b90506000612c8086613d7e565b9050600084604051602001612c9791815260200190565b60405160208183030381529060405290506000805b84518110156135f0576000858281518110612cc957612cc96156bd565b602002602001015190508451831115612d64576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4d65726b6c65547269653a206b657920696e646578206578636565647320746f60448201527f74616c206b6579206c656e6774680000000000000000000000000000000000006064820152608401610add565b82600003612e1d5780518051602091820120604051612db292612d8c92910190815260200190565b604051602081830303815290604052858051602091820120825192909101919091201490565b612e18576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4d65726b6c65547269653a20696e76616c696420726f6f7420686173680000006044820152606401610add565b612f74565b805151602011612ed35780518051602091820120604051612e4792612d8c92910190815260200190565b612e18576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d65726b6c65547269653a20696e76616c6964206c6172676520696e7465726e60448201527f616c2068617368000000000000000000000000000000000000000000000000006064820152608401610add565b805184516020808701919091208251919092012014612f74576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4d65726b6c65547269653a20696e76616c696420696e7465726e616c206e6f6460448201527f65206861736800000000000000000000000000000000000000000000000000006064820152608401610add565b612f8060106001614fff565b8160200151510361315c57845183036130f457612fba8160200151601081518110612fad57612fad6156bd565b6020026020010151613de1565b9650600087511161304d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603b60248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286272616e63682900000000006064820152608401610add565b6001865161305b919061523e565b82146130e9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286272616e6368290000000000006064820152608401610add565b505050505050612974565b6000858481518110613108576131086156bd565b602001015160f81c60f81b60f81c9050600082602001518260ff1681518110613133576131336156bd565b6020026020010151905061314681613e95565b9550613153600186614fff565b945050506135dd565b60028160200151510361355557600061317482613eba565b905060008160008151811061318b5761318b6156bd565b016020015160f81c905060006131a26002836156ec565b6131ad90600261570e565b905060006131be848360ff16613ede565b905060006131cc8a89613ede565b905060006131da8383613f14565b90508083511461326c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a20706174682072656d61696e646572206d7573742060448201527f736861726520616c6c206e6962626c65732077697468206b65790000000000006064820152608401610add565b60ff851660021480613281575060ff85166003145b156134705780825114613316576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f4d65726b6c65547269653a206b65792072656d61696e646572206d757374206260448201527f65206964656e746963616c20746f20706174682072656d61696e6465720000006064820152608401610add565b6133308760200151600181518110612fad57612fad6156bd565b9c5060008d51116133c3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286c65616629000000000000006064820152608401610add565b60018c516133d1919061523e565b881461345f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286c6561662900000000000000006064820152608401610add565b505050505050505050505050612974565b60ff85161580613483575060ff85166001145b156134c2576134af87602001516001815181106134a2576134a26156bd565b6020026020010151613e95565b99506134bb818a614fff565b985061354a565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4d65726b6c65547269653a2072656365697665642061206e6f6465207769746860448201527f20616e20756e6b6e6f776e2070726566697800000000000000000000000000006064820152608401610add565b5050505050506135dd565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4d65726b6c65547269653a20726563656976656420616e20756e70617273656160448201527f626c65206e6f64650000000000000000000000000000000000000000000000006064820152608401610add565b50806135e881615685565b915050612cac565b506040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4d65726b6c65547269653a2072616e206f7574206f662070726f6f6620656c6560448201527f6d656e74730000000000000000000000000000000000000000000000000000006064820152608401610add565b60008082136136e4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401610add565b600060606136f184613fc8565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c182136138ee57506000919050565b680755bf798b4a1bf1e58212613960576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4558505f4f564552464c4f5700000000000000000000000000000000000000006044820152606401610add565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b606082471015613b8e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610add565b73ffffffffffffffffffffffffffffffffffffffff85163b613c0c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610add565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051613c359190615731565b60006040518083038185875af1925050503d8060008114613c72576040519150601f19603f3d011682016040523d82523d6000602084013e613c77565b606091505b5091509150613c8782828661409e565b979650505050505050565b80516060908067ffffffffffffffff811115613cb057613cb0614a97565b604051908082528060200260200182016040528015613cf557816020015b6040805180820190915260608082526020820152815260200190600190039081613cce5790505b50915060005b81811015613d77576040518060400160405280858381518110613d2057613d206156bd565b60200260200101518152602001613d4f868481518110613d4257613d426156bd565b60200260200101516140f1565b815250838281518110613d6457613d646156bd565b6020908102919091010152600101613cfb565b5050919050565b606080604051905082518060011b603f8101601f1916830160405280835250602084016020830160005b83811015613dd6578060011b82018184015160001a8060041c8253600f811660018301535050600101613da8565b509295945050505050565b60606000806000613df185614104565b919450925090506000816001811115613e0c57613e0c61574d565b14613e43576040517f1ff9b2e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613e4d8284614fff565b855114613e86576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612b75856020015184846145a2565b60606020826000015110613eb157613eac82613de1565b610ff2565b610ff282614636565b6060610ff2613ed98360200151600081518110612fad57612fad6156bd565b613d7e565b606082518210613efd5750604080516020810190915260008152610ff2565b6129748383848651613f0f919061523e565b61464c565b6000808251845110613f27578251613f2a565b83515b90505b8082108015613fb15750828281518110613f4957613f496156bd565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916848381518110613f8857613f886156bd565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b15613fc157816001019150613f2d565b5092915050565b6000808211614033576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401610add565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b606083156140ad575081612974565b8251156140bd5782518084602001fd5b816040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610add9190614e29565b6060610ff26140ff83614824565b614891565b60008060008360000151600003614147576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020840151805160001a607f811161416c57600060016000945094509450505061459b565b60b7811161428257600061418160808361523e565b9050808760000151116141c0576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001838101517fff0000000000000000000000000000000000000000000000000000000000000016908214801561423857507f80000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000008216105b1561426f576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506001955093506000925061459b915050565b60bf81116143e057600061429760b78361523e565b9050808760000151116142d6576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614338576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c60378111614380576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61438a8184614fff565b8951116143c3576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6143ce836001614fff565b975095506000945061459b9350505050565b60f781116144455760006143f560c08361523e565b905080876000015111614434576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60019550935084925061459b915050565b600061445260f78361523e565b905080876000015111614491576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff000000000000000000000000000000000000000000000000000000000000001660008190036144f3576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c6037811161453b576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6145458184614fff565b89511161457e576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614589836001614fff565b975095506001945061459b9350505050565b9193909250565b60608167ffffffffffffffff8111156145bd576145bd614a97565b6040519080825280601f01601f1916602001820160405280156145e7576020820181803683370190505b50905081156129745760006145fc8486614fff565b90506020820160005b8481101561461d578281015182820152602001614605565b8481111561462c576000858301525b5050509392505050565b6060610ff28260200151600084600001516145a2565b60608182601f0110156146bb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610add565b828284011015614727576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610add565b81830184511015614794576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401610add565b6060821580156147b3576040519150600082526020820160405261481b565b6040519150601f8416801560200281840101858101878315602002848b0101015b818310156147ec5780518352602092830192016147d4565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b60408051808201909152600080825260208201528151600003614873576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50604080518082019091528151815260209182019181019190915290565b606060008060006148a185614104565b9194509250905060018160018111156148bc576148bc61574d565b146148f3576040517f4b9c6abe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84516148ff8385614fff565b14614936576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516020808252610420820190925290816020015b604080518082019091526000808252602082015281526020019060019003908161494d5790505093506000835b8651811015614a3b576000806149c06040518060400160405280858c600001516149a4919061523e565b8152602001858c602001516149b99190614fff565b9052614104565b5091509150604051806040016040528083836149dc9190614fff565b8152602001848b602001516149f19190614fff565b815250888581518110614a0657614a066156bd565b6020908102919091010152614a1c600185614fff565b9350614a288183614fff565b614a329084614fff565b9250505061497a565b50845250919392505050565b73ffffffffffffffffffffffffffffffffffffffff81168114614a6957600080fd5b50565b803567ffffffffffffffff81168114614a8457600080fd5b919050565b8015158114614a6957600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614b0d57614b0d614a97565b604052919050565b600082601f830112614b2657600080fd5b813567ffffffffffffffff811115614b4057614b40614a97565b614b7160207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601614ac6565b818152846020838601011115614b8657600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060008060c08789031215614bbc57600080fd5b8635614bc781614a47565b95506020870135945060408701359350614be360608801614a6c565b92506080870135614bf381614a89565b915060a087013567ffffffffffffffff811115614c0f57600080fd5b614c1b89828a01614b15565b9150509295509295509295565b600060c08284031215614c3a57600080fd5b60405160c0810167ffffffffffffffff8282108183111715614c5e57614c5e614a97565b816040528293508435835260208501359150614c7982614a47565b81602084015260408501359150614c8f82614a47565b816040840152606085013560608401526080850135608084015260a0850135915080821115614cbd57600080fd5b50614cca85828601614b15565b60a0830152505092915050565b600080600080600085870360e0811215614cf057600080fd5b863567ffffffffffffffff80821115614d0857600080fd5b614d148a838b01614c28565b97506020890135965060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc084011215614d4d57600080fd5b60408901955060c0890135925080831115614d6757600080fd5b828901925089601f840112614d7b57600080fd5b8235915080821115614d8c57600080fd5b508860208260051b8401011115614da257600080fd5b959894975092955050506020019190565b60005b83811015614dce578181015183820152602001614db6565b838111156125115750506000910152565b60008151808452614df7816020860160208601614db3565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006129746020830184614ddf565b600060208284031215614e4e57600080fd5b5035919050565b60ff81168114614a6957600080fd5b60008060008060808587031215614e7a57600080fd5b8435614e8581614a47565b93506020850135614e9581614e55565b93969395505050506040820135916060013590565b600060208284031215614ebc57600080fd5b813567ffffffffffffffff811115614ed357600080fd5b614edf84828501614c28565b949350505050565b600060208284031215614ef957600080fd5b61297482614a6c565b60008060008060808587031215614f1857600080fd5b8435614f2381614a47565b93506020850135614f3381614a47565b92506040850135614f4381614a47565b9396929550929360600135925050565b600080600080600060a08688031215614f6b57600080fd5b8535614f7681614a47565b945060208601359350614f8b60408701614a6c565b92506060860135614f9b81614a89565b9150608086013567ffffffffffffffff811115614fb757600080fd5b614fc388828901614b15565b9150509295509295909350565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561501257615012614fd0565b500190565b60006020828403121561502957600080fd5b5051919050565b60006020828403121561504257600080fd5b815161297481614a47565b80516fffffffffffffffffffffffffffffffff81168114614a8457600080fd5b60006060828403121561507f57600080fd5b6040516060810181811067ffffffffffffffff821117156150a2576150a2614a97565b604052825181526150b56020840161504d565b60208201526150c66040840161504d565b60408201529392505050565b6000608082840312156150e457600080fd5b6040516080810181811067ffffffffffffffff8211171561510757615107614a97565b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b600067ffffffffffffffff8084111561515357615153614a97565b8360051b6020615164818301614ac6565b86815291850191818101903684111561517c57600080fd5b865b848110156151b0578035868111156151965760008081fd5b6151a236828b01614b15565b84525091830191830161517e565b50979650505050505050565b6000602082840312156151ce57600080fd5b815161297481614a89565b8581528460208201527fffffffffffffffff0000000000000000000000000000000000000000000000008460c01b16604082015282151560f81b60488201526000825161522d816049850160208701614db3565b919091016049019695505050505050565b60008282101561525057615250614fd0565b500390565b600067ffffffffffffffff8083168185168183048111821515161561527c5761527c614fd0565b02949350505050565b600067ffffffffffffffff8083168185168083038211156152a8576152a8614fd0565b01949350505050565b600080604083850312156152c457600080fd5b82516152cf81614a47565b60208401519092506152e081614e55565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082615329576153296152eb565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f80000000000000000000000000000000000000000000000000000000000000008314161561537d5761537d614fd0565b500590565b6000808312837f8000000000000000000000000000000000000000000000000000000000000000018312811516156153bc576153bc614fd0565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0183138116156153f0576153f0614fd0565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60008413600084138583048511828216161561543757615437614fd0565b7f8000000000000000000000000000000000000000000000000000000000000000600087128682058812818416161561547257615472614fd0565b6000871292508782058712848416161561548e5761548e614fd0565b878505871281841616156154a4576154a4614fd0565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038413811516156154ec576154ec614fd0565b827f800000000000000000000000000000000000000000000000000000000000000003841281161561552057615520614fd0565b50500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561555e5761555e614fd0565b500290565b600082615572576155726152eb565b500490565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a08301526155c260c0830184614ddf565b98975050505050505050565b805163ffffffff81168114614a8457600080fd5b600060c082840312156155f457600080fd5b60405160c0810181811067ffffffffffffffff8211171561561757615617614a97565b604052615623836155ce565b8152602083015161563381614e55565b6020820152604083015161564681614e55565b6040820152615657606084016155ce565b6060820152615668608084016155ce565b608082015261567960a0840161504d565b60a08201529392505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036156b6576156b6614fd0565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060ff8316806156ff576156ff6152eb565b8060ff84160691505092915050565b600060ff821660ff84168082101561572857615728614fd0565b90039392505050565b60008251615743818460208701614db3565b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea164736f6c634300080f000a"; ++ hex"6080604052600436106101635760003560e01c80638c3152e9116100c0578063b69ef8a811610074578063cff0ab9611610059578063cff0ab9614610444578063e965084c146104e5578063e9e05c421461057157600080fd5b8063b69ef8a814610401578063c0c53b8b1461042457600080fd5b80639bf62d82116100a55780639bf62d821461036b578063a14238e714610398578063a35d99df146103c857600080fd5b80638c3152e91461031e5780639b5f694a1461033e57600080fd5b806354fd4d50116101175780636dbffb78116100fc5780636dbffb78146102de57806371cfaa3f146102fe5780638b4c40b01461018857600080fd5b806354fd4d501461026d5780635c975abb146102b957600080fd5b806335e80ab31161014857806335e80ab314610206578063452a9320146102385780634870496f1461024d57600080fd5b8063149f2f221461018f57806333d7e2bd146101af57600080fd5b3661018a576101883334620186a060006040518060200160405280600081525061057f565b005b600080fd5b34801561019b57600080fd5b506101886101aa366004614c13565b610624565b3480156101bb57600080fd5b506037546101dc9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561021257600080fd5b506035546101dc90610100900473ffffffffffffffffffffffffffffffffffffffff1681565b34801561024457600080fd5b506101dc610865565b34801561025957600080fd5b50610188610268366004614d47565b6108fd565b34801561027957600080fd5b50604080518082018252600c81527f322e382e312d626574612e320000000000000000000000000000000000000000602082015290516101fd9190614e99565b3480156102c557600080fd5b506102ce610eaa565b60405190151581526020016101fd565b3480156102ea57600080fd5b506102ce6102f9366004614eac565b610f3d565b34801561030a57600080fd5b50610188610319366004614ed4565b610ff8565b34801561032a57600080fd5b50610188610339366004614f1a565b6111ba565b34801561034a57600080fd5b506036546101dc9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561037757600080fd5b506032546101dc9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156103a457600080fd5b506102ce6103b3366004614eac565b60336020526000908152604090205460ff1681565b3480156103d457600080fd5b506103e86103e3366004614f57565b611c3c565b60405167ffffffffffffffff90911681526020016101fd565b34801561040d57600080fd5b50610416611c55565b6040519081526020016101fd565b34801561043057600080fd5b5061018861043f366004614f72565b611caf565b34801561045057600080fd5b506001546104ac906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff92831660208501529116908201526060016101fd565b3480156104f157600080fd5b50610543610500366004614eac565b603460205260009081526040902080546001909101546fffffffffffffffffffffffffffffffff8082169170010000000000000000000000000000000090041683565b604080519384526fffffffffffffffffffffffffffffffff92831660208501529116908201526060016101fd565b61018861057f366004614fbd565b8260005a9050600061058f611f19565b50905073ffffffffffffffffffffffffffffffffffffffff811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee148015906105cb57503415155b15610602576040517ff2365b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610610883489898989611fb6565b5061061b8282612162565b50505050505050565b8260005a90506000610634611f19565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8216016106a6576040517f0eaf3c0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87603d60008282546106b89190615069565b90915550506040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa15801561072a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061074e9190615081565b905061077273ffffffffffffffffffffffffffffffffffffffff831633308c61242f565b61077c8982615069565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa1580156107e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061080a9190615081565b14610841576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61084f8a8a8a8a8a8a611fb6565b505061085b8282612162565b5050505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f8919061509a565b905090565b610905610eaa565b1561093c576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff16036109a5576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6036546040517fa25ae5570000000000000000000000000000000000000000000000000000000081526004810186905260009173ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa158015610a15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a3991906150d7565b519050610a53610a4e3686900386018661513c565b61250b565b8114610ae6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f7074696d69736d506f7274616c3a20696e76616c6964206f7574707574207260448201527f6f6f742070726f6f66000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000610af187612567565b6000818152603460209081526040918290208251606081018452815481526001909101546fffffffffffffffffffffffffffffffff8082169383018490527001000000000000000000000000000000009091041692810192909252919250901580610c075750805160365460408084015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff909116600482015273ffffffffffffffffffffffffffffffffffffffff9091169063a25ae55790602401606060405180830381865afa158015610bdf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c0391906150d7565b5114155b610c93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173682060448201527f68617320616c7265616479206265656e2070726f76656e0000000000000000006064820152608401610add565b60408051602081018490526000918101829052606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201209083018190529250610d5c9101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152600182527f0100000000000000000000000000000000000000000000000000000000000000602083015290610d52888a6151a2565b8a60400135612597565b610de8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a20696e76616c696420776974686472617760448201527f616c20696e636c7573696f6e2070726f6f6600000000000000000000000000006064820152608401610add565b604080516060810182528581526fffffffffffffffffffffffffffffffff42811660208084019182528c831684860190815260008981526034835286812095518655925190518416700100000000000000000000000000000000029316929092176001909301929092558b830151908c0151925173ffffffffffffffffffffffffffffffffffffffff918216939091169186917f67a6208cfcc0801d50f6cbe764733f4fddf66ac0b04442061a8a8c0cb6b63f629190a4505050505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f19573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f89190615226565b6036546040517fa25ae55700000000000000000000000000000000000000000000000000000000815260048101839052600091610ff29173ffffffffffffffffffffffffffffffffffffffff9091169063a25ae55790602401606060405180830381865afa158015610fb3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fd791906150d7565b602001516fffffffffffffffffffffffffffffffff166125bb565b92915050565b60375473ffffffffffffffffffffffffffffffffffffffff163314611049576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61105562030d40612661565b60405173ffffffffffffffffffffffffffffffffffffffff8516602482015260ff8416604482015260648101839052608481018290526000907342000000000000000000000000000000000000159073deaddeaddeaddeaddeaddeaddeaddeaddead0001907fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32908490819062030d4090829060a401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f71cfaa3f00000000000000000000000000000000000000000000000000000000179052905161117296959493929101615243565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290526111aa91614e99565b60405180910390a450505050565b565b6111c2610eaa565b156111f9576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60325473ffffffffffffffffffffffffffffffffffffffff1661dead1461124c576040517f9396d15600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061125782612567565b60008181526034602090815260408083208151606081018352815481526001909101546fffffffffffffffffffffffffffffffff80821694830185905270010000000000000000000000000000000090910416918101919091529293509003611342576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206e60448201527f6f74206265656e2070726f76656e2079657400000000000000000000000000006064820152608401610add565b603660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663887862726040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113d39190615081565b81602001516fffffffffffffffffffffffffffffffff16101561149e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604b60248201527f4f7074696d69736d506f7274616c3a207769746864726177616c2074696d657360448201527f74616d70206c657373207468616e204c32204f7261636c65207374617274696e60648201527f672074696d657374616d70000000000000000000000000000000000000000000608482015260a401610add565b6114bd81602001516fffffffffffffffffffffffffffffffff166125bb565b61156f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604560248201527f4f7074696d69736d506f7274616c3a2070726f76656e2077697468647261776160448201527f6c2066696e616c697a6174696f6e20706572696f6420686173206e6f7420656c60648201527f6170736564000000000000000000000000000000000000000000000000000000608482015260a401610add565b60365460408281015190517fa25ae5570000000000000000000000000000000000000000000000000000000081526fffffffffffffffffffffffffffffffff909116600482015260009173ffffffffffffffffffffffffffffffffffffffff169063a25ae55790602401606060405180830381865afa1580156115f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061161a91906150d7565b82518151919250146116d4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604960248201527f4f7074696d69736d506f7274616c3a206f757470757420726f6f742070726f7660448201527f656e206973206e6f74207468652073616d652061732063757272656e74206f7560648201527f7470757420726f6f740000000000000000000000000000000000000000000000608482015260a401610add565b6116f381602001516fffffffffffffffffffffffffffffffff166125bb565b6117a5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f4f7074696d69736d506f7274616c3a206f75747075742070726f706f73616c2060448201527f66696e616c697a6174696f6e20706572696f6420686173206e6f7420656c617060648201527f7365640000000000000000000000000000000000000000000000000000000000608482015260a401610add565b60008381526033602052604090205460ff1615611844576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4f7074696d69736d506f7274616c3a207769746864726177616c20686173206160448201527f6c7265616479206265656e2066696e616c697a656400000000000000000000006064820152608401610add565b6000838152603360209081526040822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558501516032805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff0000000000000000000000000000000000000000909216919091179055806118cf611f19565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8216016119325761192b8660400151876080015188606001518960a001516126c3565b9150611b85565b8073ffffffffffffffffffffffffffffffffffffffff16866040015173ffffffffffffffffffffffffffffffffffffffff160361199b576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606086015115611b5c578560600151603d60008282546119bb91906152a8565b90915550506040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015611a2d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a519190615081565b9050611a86876040015188606001518473ffffffffffffffffffffffffffffffffffffffff166127219092919063ffffffff16565b6060870151611a9590826152a8565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa158015611aff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b239190615081565b14611b5a576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b60a08601515115611b805761192b8660400151876080015160008960a001516126c3565b600191505b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405185907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b90611be790851515815260200190565b60405180910390a281158015611bfd5750326001145b15611c34576040517feeae4ed300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000611c498260106152bf565b610ff2906152086152ef565b600080611c60611f19565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff821601611ca7574791505090565b5050603d5490565b600054610100900460ff1615808015611ccf5750600054600160ff909116105b80611ce95750303b158015611ce9575060005460ff166001145b611d75576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610add565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015611dd357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603680547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff8781169190911790925560378054909116858316179055603580547fffffffffffffffffffffff0000000000000000000000000000000000000000ff166101008584160217905560325416611e8c57603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead1790555b611e9461277c565b8015611ef757600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b603754604080517f4397dfef0000000000000000000000000000000000000000000000000000000081528151600093849373ffffffffffffffffffffffffffffffffffffffff90911692634397dfef92600480830193928290030181865afa158015611f89573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fad919061531b565b90939092509050565b818015611fd8575073ffffffffffffffffffffffffffffffffffffffff861615155b1561200f576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6120198151611c3c565b67ffffffffffffffff168367ffffffffffffffff161015612066576040517f4929b80800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6201d4c0815111156120a4576040517f73052b0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b333281146120c5575033731111000000000000000000000000000000001111015b600086868686866040516020016120e0959493929190615243565b604051602081830303815290604052905060008873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32846040516121509190614e99565b60405180910390a45050505050505050565b600154600090612198907801000000000000000000000000000000000000000000000000900467ffffffffffffffff16436152a8565b905060006121a461288f565b90506000816020015160ff16826000015163ffffffff166121c59190615384565b905082156122fc576001546000906121fc908390700100000000000000000000000000000000900467ffffffffffffffff166153ec565b90506000836040015160ff16836122139190615460565b6001546122339084906fffffffffffffffffffffffffffffffff16615460565b61223d9190615384565b60015490915060009061228e906122679084906fffffffffffffffffffffffffffffffff1661551c565b866060015163ffffffff168760a001516fffffffffffffffffffffffffffffffff166129cc565b905060018611156122bd576122ba61226782876040015160ff1660018a6122b591906152a8565b6129eb565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760015550505b6001805486919060109061232f908490700100000000000000000000000000000000900467ffffffffffffffff166152ef565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550816000015163ffffffff16600160000160109054906101000a900467ffffffffffffffff1667ffffffffffffffff1613156123bc576040517f77ebef4d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001546000906123e8906fffffffffffffffffffffffffffffffff1667ffffffffffffffff8816615590565b905060006123fa48633b9aca00612a40565b61240490836155cd565b905060005a61241390886152a8565b90508082111561085b5761085b61242a82846152a8565b612a57565b60405173ffffffffffffffffffffffffffffffffffffffff80851660248301528316604482015260648101829052611ef79085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152612a80565b6000816000015182602001518360400151846060015160405160200161254a949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b80516020808301516040808501516060860151608087015160a0880151935160009761254a9790969591016155e1565b6000806125a386612b8c565b90506125b181868686612bbe565b9695505050505050565b603654604080517ff4daa291000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163f4daa2919160048083019260209291908290030181865afa15801561262b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061264f9190615081565b6126599083615069565b421192915050565b6001805463ffffffff8316919060109061269a908490700100000000000000000000000000000000900467ffffffffffffffff166152ef565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555050565b60008060006126d3866000612bee565b905080612709576308c379a06000526020805278185361666543616c6c3a204e6f7420656e6f756768206761736058526064601cfd5b600080855160208701888b5af1979650505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526127779084907fa9059cbb0000000000000000000000000000000000000000000000000000000090606401612489565b505050565b600054610100900460ff16612813576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610add565b6001547801000000000000000000000000000000000000000000000000900467ffffffffffffffff166000036111b85760408051606081018252633b9aca00808252600060208301524367ffffffffffffffff169190920181905278010000000000000000000000000000000000000000000000000217600155565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152603754604080517fcc731b02000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163cc731b029160048083019260c09291908290030181865afa158015612931573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612955919061564c565b90506040518060c00160405280826000015163ffffffff168152602001826020015160ff168152602001826040015160ff168152602001826060015163ffffffff168152602001826080015163ffffffff1681526020018260a001516fffffffffffffffffffffffffffffffff1681525091505090565b60006129e16129db8585612c0c565b83612c1c565b90505b9392505050565b6000670de0b6b3a7640000612a2c612a038583615384565b612a1590670de0b6b3a76400006153ec565b612a2785670de0b6b3a7640000615460565b612c2b565b612a369086615460565b6129e19190615384565b600081831015612a5057816129e4565b5090919050565b6000805a90505b825a612a6a90836152a8565b101561277757612a79826156ef565b9150612a5e565b6000612ae2826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612c5c9092919063ffffffff16565b8051909150156127775780806020019051810190612b009190615226565b612777576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610add565b60608180519060200120604051602001612ba891815260200190565b6040516020818303038152906040529050919050565b6000612be584612bcf878686612c6b565b8051602091820120825192909101919091201490565b95945050505050565b600080603f83619c4001026040850201603f5a021015949350505050565b600081831215612a5057816129e4565b6000818312612a5057816129e4565b60006129e4670de0b6b3a764000083612c43866136e9565b612c4d9190615460565b612c579190615384565b61392d565b60606129e18484600085613b6c565b60606000845111612cd8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4d65726b6c65547269653a20656d707479206b657900000000000000000000006044820152606401610add565b6000612ce384613d02565b90506000612cf086613dee565b9050600084604051602001612d0791815260200190565b60405160208183030381529060405290506000805b8451811015613660576000858281518110612d3957612d39615727565b602002602001015190508451831115612dd4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4d65726b6c65547269653a206b657920696e646578206578636565647320746f60448201527f74616c206b6579206c656e6774680000000000000000000000000000000000006064820152608401610add565b82600003612e8d5780518051602091820120604051612e2292612dfc92910190815260200190565b604051602081830303815290604052858051602091820120825192909101919091201490565b612e88576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4d65726b6c65547269653a20696e76616c696420726f6f7420686173680000006044820152606401610add565b612fe4565b805151602011612f435780518051602091820120604051612eb792612dfc92910190815260200190565b612e88576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d65726b6c65547269653a20696e76616c6964206c6172676520696e7465726e60448201527f616c2068617368000000000000000000000000000000000000000000000000006064820152608401610add565b805184516020808701919091208251919092012014612fe4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4d65726b6c65547269653a20696e76616c696420696e7465726e616c206e6f6460448201527f65206861736800000000000000000000000000000000000000000000000000006064820152608401610add565b612ff060106001615069565b816020015151036131cc57845183036131645761302a816020015160108151811061301d5761301d615727565b6020026020010151613e51565b965060008751116130bd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603b60248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286272616e63682900000000006064820152608401610add565b600186516130cb91906152a8565b8214613159576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286272616e6368290000000000006064820152608401610add565b5050505050506129e4565b600085848151811061317857613178615727565b602001015160f81c60f81b60f81c9050600082602001518260ff16815181106131a3576131a3615727565b602002602001015190506131b681613f05565b95506131c3600186615069565b9450505061364d565b6002816020015151036135c55760006131e482613f2a565b90506000816000815181106131fb576131fb615727565b016020015160f81c90506000613212600283615756565b61321d906002615778565b9050600061322e848360ff16613f4e565b9050600061323c8a89613f4e565b9050600061324a8383613f84565b9050808351146132dc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a20706174682072656d61696e646572206d7573742060448201527f736861726520616c6c206e6962626c65732077697468206b65790000000000006064820152608401610add565b60ff8516600214806132f1575060ff85166003145b156134e05780825114613386576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f4d65726b6c65547269653a206b65792072656d61696e646572206d757374206260448201527f65206964656e746963616c20746f20706174682072656d61696e6465720000006064820152608401610add565b6133a0876020015160018151811061301d5761301d615727565b9c5060008d5111613433576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286c65616629000000000000006064820152608401610add565b60018c5161344191906152a8565b88146134cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286c6561662900000000000000006064820152608401610add565b5050505050505050505050506129e4565b60ff851615806134f3575060ff85166001145b156135325761351f876020015160018151811061351257613512615727565b6020026020010151613f05565b995061352b818a615069565b98506135ba565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4d65726b6c65547269653a2072656365697665642061206e6f6465207769746860448201527f20616e20756e6b6e6f776e2070726566697800000000000000000000000000006064820152608401610add565b50505050505061364d565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4d65726b6c65547269653a20726563656976656420616e20756e70617273656160448201527f626c65206e6f64650000000000000000000000000000000000000000000000006064820152608401610add565b5080613658816156ef565b915050612d1c565b506040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4d65726b6c65547269653a2072616e206f7574206f662070726f6f6620656c6560448201527f6d656e74730000000000000000000000000000000000000000000000000000006064820152608401610add565b6000808213613754576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401610add565b6000606061376184614038565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c1821361395e57506000919050565b680755bf798b4a1bf1e582126139d0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4558505f4f564552464c4f5700000000000000000000000000000000000000006044820152606401610add565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b606082471015613bfe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610add565b73ffffffffffffffffffffffffffffffffffffffff85163b613c7c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610add565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051613ca5919061579b565b60006040518083038185875af1925050503d8060008114613ce2576040519150601f19603f3d011682016040523d82523d6000602084013e613ce7565b606091505b5091509150613cf782828661410e565b979650505050505050565b80516060908067ffffffffffffffff811115613d2057613d20614b07565b604051908082528060200260200182016040528015613d6557816020015b6040805180820190915260608082526020820152815260200190600190039081613d3e5790505b50915060005b81811015613de7576040518060400160405280858381518110613d9057613d90615727565b60200260200101518152602001613dbf868481518110613db257613db2615727565b6020026020010151614161565b815250838281518110613dd457613dd4615727565b6020908102919091010152600101613d6b565b5050919050565b606080604051905082518060011b603f8101601f1916830160405280835250602084016020830160005b83811015613e46578060011b82018184015160001a8060041c8253600f811660018301535050600101613e18565b509295945050505050565b60606000806000613e6185614174565b919450925090506000816001811115613e7c57613e7c6157b7565b14613eb3576040517f1ff9b2e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613ebd8284615069565b855114613ef6576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612be585602001518484614612565b60606020826000015110613f2157613f1c82613e51565b610ff2565b610ff2826146a6565b6060610ff2613f49836020015160008151811061301d5761301d615727565b613dee565b606082518210613f6d5750604080516020810190915260008152610ff2565b6129e48383848651613f7f91906152a8565b6146bc565b6000808251845110613f97578251613f9a565b83515b90505b80821080156140215750828281518110613fb957613fb9615727565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916848381518110613ff857613ff8615727565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b1561403157816001019150613f9d565b5092915050565b60008082116140a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401610add565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b6060831561411d5750816129e4565b82511561412d5782518084602001fd5b816040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610add9190614e99565b6060610ff261416f83614894565b614901565b600080600083600001516000036141b7576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020840151805160001a607f81116141dc57600060016000945094509450505061460b565b60b781116142f25760006141f16080836152a8565b905080876000015111614230576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001838101517fff000000000000000000000000000000000000000000000000000000000000001690821480156142a857507f80000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000008216105b156142df576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506001955093506000925061460b915050565b60bf811161445057600061430760b7836152a8565b905080876000015111614346576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff000000000000000000000000000000000000000000000000000000000000001660008190036143a8576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c603781116143f0576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6143fa8184615069565b895111614433576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61443e836001615069565b975095506000945061460b9350505050565b60f781116144b557600061446560c0836152a8565b9050808760000151116144a4576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60019550935084925061460b915050565b60006144c260f7836152a8565b905080876000015111614501576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614563576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c603781116145ab576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6145b58184615069565b8951116145ee576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6145f9836001615069565b975095506001945061460b9350505050565b9193909250565b60608167ffffffffffffffff81111561462d5761462d614b07565b6040519080825280601f01601f191660200182016040528015614657576020820181803683370190505b50905081156129e457600061466c8486615069565b90506020820160005b8481101561468d578281015182820152602001614675565b8481111561469c576000858301525b5050509392505050565b6060610ff2826020015160008460000151614612565b60608182601f01101561472b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610add565b828284011015614797576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610add565b81830184511015614804576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401610add565b606082158015614823576040519150600082526020820160405261488b565b6040519150601f8416801560200281840101858101878315602002848b0101015b8183101561485c578051835260209283019201614844565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b604080518082019091526000808252602082015281516000036148e3576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50604080518082019091528151815260209182019181019190915290565b6060600080600061491185614174565b91945092509050600181600181111561492c5761492c6157b7565b14614963576040517f4b9c6abe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845161496f8385615069565b146149a6576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516020808252610420820190925290816020015b60408051808201909152600080825260208201528152602001906001900390816149bd5790505093506000835b8651811015614aab57600080614a306040518060400160405280858c60000151614a1491906152a8565b8152602001858c60200151614a299190615069565b9052614174565b509150915060405180604001604052808383614a4c9190615069565b8152602001848b60200151614a619190615069565b815250888581518110614a7657614a76615727565b6020908102919091010152614a8c600185615069565b9350614a988183615069565b614aa29084615069565b925050506149ea565b50845250919392505050565b73ffffffffffffffffffffffffffffffffffffffff81168114614ad957600080fd5b50565b803567ffffffffffffffff81168114614af457600080fd5b919050565b8015158114614ad957600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614b7d57614b7d614b07565b604052919050565b600082601f830112614b9657600080fd5b813567ffffffffffffffff811115614bb057614bb0614b07565b614be160207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601614b36565b818152846020838601011115614bf657600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060008060c08789031215614c2c57600080fd5b8635614c3781614ab7565b95506020870135945060408701359350614c5360608801614adc565b92506080870135614c6381614af9565b915060a087013567ffffffffffffffff811115614c7f57600080fd5b614c8b89828a01614b85565b9150509295509295509295565b600060c08284031215614caa57600080fd5b60405160c0810167ffffffffffffffff8282108183111715614cce57614cce614b07565b816040528293508435835260208501359150614ce982614ab7565b81602084015260408501359150614cff82614ab7565b816040840152606085013560608401526080850135608084015260a0850135915080821115614d2d57600080fd5b50614d3a85828601614b85565b60a0830152505092915050565b600080600080600085870360e0811215614d6057600080fd5b863567ffffffffffffffff80821115614d7857600080fd5b614d848a838b01614c98565b97506020890135965060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc084011215614dbd57600080fd5b60408901955060c0890135925080831115614dd757600080fd5b828901925089601f840112614deb57600080fd5b8235915080821115614dfc57600080fd5b508860208260051b8401011115614e1257600080fd5b959894975092955050506020019190565b60005b83811015614e3e578181015183820152602001614e26565b83811115611ef75750506000910152565b60008151808452614e67816020860160208601614e23565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006129e46020830184614e4f565b600060208284031215614ebe57600080fd5b5035919050565b60ff81168114614ad957600080fd5b60008060008060808587031215614eea57600080fd5b8435614ef581614ab7565b93506020850135614f0581614ec5565b93969395505050506040820135916060013590565b600060208284031215614f2c57600080fd5b813567ffffffffffffffff811115614f4357600080fd5b614f4f84828501614c98565b949350505050565b600060208284031215614f6957600080fd5b6129e482614adc565b600080600060608486031215614f8757600080fd5b8335614f9281614ab7565b92506020840135614fa281614ab7565b91506040840135614fb281614ab7565b809150509250925092565b600080600080600060a08688031215614fd557600080fd5b8535614fe081614ab7565b945060208601359350614ff560408701614adc565b9250606086013561500581614af9565b9150608086013567ffffffffffffffff81111561502157600080fd5b61502d88828901614b85565b9150509295509295909350565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561507c5761507c61503a565b500190565b60006020828403121561509357600080fd5b5051919050565b6000602082840312156150ac57600080fd5b81516129e481614ab7565b80516fffffffffffffffffffffffffffffffff81168114614af457600080fd5b6000606082840312156150e957600080fd5b6040516060810181811067ffffffffffffffff8211171561510c5761510c614b07565b6040528251815261511f602084016150b7565b6020820152615130604084016150b7565b60408201529392505050565b60006080828403121561514e57600080fd5b6040516080810181811067ffffffffffffffff8211171561517157615171614b07565b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b600067ffffffffffffffff808411156151bd576151bd614b07565b8360051b60206151ce818301614b36565b8681529185019181810190368411156151e657600080fd5b865b8481101561521a578035868111156152005760008081fd5b61520c36828b01614b85565b8452509183019183016151e8565b50979650505050505050565b60006020828403121561523857600080fd5b81516129e481614af9565b8581528460208201527fffffffffffffffff0000000000000000000000000000000000000000000000008460c01b16604082015282151560f81b604882015260008251615297816049850160208701614e23565b919091016049019695505050505050565b6000828210156152ba576152ba61503a565b500390565b600067ffffffffffffffff808316818516818304811182151516156152e6576152e661503a565b02949350505050565b600067ffffffffffffffff8083168185168083038211156153125761531261503a565b01949350505050565b6000806040838503121561532e57600080fd5b825161533981614ab7565b602084015190925061534a81614ec5565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261539357615393615355565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f8000000000000000000000000000000000000000000000000000000000000000831416156153e7576153e761503a565b500590565b6000808312837f8000000000000000000000000000000000000000000000000000000000000000018312811516156154265761542661503a565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01831381161561545a5761545a61503a565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6000841360008413858304851182821616156154a1576154a161503a565b7f800000000000000000000000000000000000000000000000000000000000000060008712868205881281841616156154dc576154dc61503a565b600087129250878205871284841616156154f8576154f861503a565b8785058712818416161561550e5761550e61503a565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038413811516156155565761555661503a565b827f800000000000000000000000000000000000000000000000000000000000000003841281161561558a5761558a61503a565b50500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156155c8576155c861503a565b500290565b6000826155dc576155dc615355565b500490565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a083015261562c60c0830184614e4f565b98975050505050505050565b805163ffffffff81168114614af457600080fd5b600060c0828403121561565e57600080fd5b60405160c0810181811067ffffffffffffffff8211171561568157615681614b07565b60405261568d83615638565b8152602083015161569d81614ec5565b602082015260408301516156b081614ec5565b60408201526156c160608401615638565b60608201526156d260808401615638565b60808201526156e360a084016150b7565b60a08201529392505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036157205761572061503a565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060ff83168061576957615769615355565b8060ff84160691505092915050565b600060ff821660ff8416808210156157925761579261503a565b90039392505050565b600082516157ad818460208701614e23565b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fdfea164736f6c634300080f000a"; bytes internal constant l2OutputOracleCode = - hex"60806040526004361061018a5760003560e01c806389c44cbb116100d6578063ce5db8d61161007f578063dcec334811610059578063dcec33481461049b578063e1a41bcf146104b0578063f4daa291146104c657600080fd5b8063ce5db8d614610445578063cf8e5cf01461045b578063d1de856c1461047b57600080fd5b8063a25ae557116100b0578063a25ae55714610391578063a8e4fb90146103ed578063bffa7f0f1461041a57600080fd5b806389c44cbb1461034857806393991af3146103685780639aaab6481461037e57600080fd5b806369f16eec1161013857806370872aa51161011257806370872aa5146102fc5780637f00642014610312578063887862721461033257600080fd5b806369f16eec146102a75780636abcf563146102bc5780636b4d98dd146102d157600080fd5b8063529933df11610169578063529933df146101ea578063534db0e2146101ff57806354fd4d501461025157600080fd5b80622134cc1461018f5780631c89c97d146101b35780634599c788146101d5575b600080fd5b34801561019b57600080fd5b506005545b6040519081526020015b60405180910390f35b3480156101bf57600080fd5b506101d36101ce3660046113a2565b6104db565b005b3480156101e157600080fd5b506101a06108b6565b3480156101f657600080fd5b506004546101a0565b34801561020b57600080fd5b5060065461022c9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101aa565b34801561025d57600080fd5b5061029a6040518060400160405280600581526020017f312e382e3000000000000000000000000000000000000000000000000000000081525081565b6040516101aa9190611405565b3480156102b357600080fd5b506101a0610929565b3480156102c857600080fd5b506003546101a0565b3480156102dd57600080fd5b5060065473ffffffffffffffffffffffffffffffffffffffff1661022c565b34801561030857600080fd5b506101a060015481565b34801561031e57600080fd5b506101a061032d366004611478565b61093b565b34801561033e57600080fd5b506101a060025481565b34801561035457600080fd5b506101d3610363366004611478565b610b4f565b34801561037457600080fd5b506101a060055481565b6101d361038c366004611491565b610de9565b34801561039d57600080fd5b506103b16103ac366004611478565b61124a565b60408051825181526020808401516fffffffffffffffffffffffffffffffff9081169183019190915292820151909216908201526060016101aa565b3480156103f957600080fd5b5060075461022c9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561042657600080fd5b5060075473ffffffffffffffffffffffffffffffffffffffff1661022c565b34801561045157600080fd5b506101a060085481565b34801561046757600080fd5b506103b1610476366004611478565b6112de565b34801561048757600080fd5b506101a0610496366004611478565b611316565b3480156104a757600080fd5b506101a0611346565b3480156104bc57600080fd5b506101a060045481565b3480156104d257600080fd5b506008546101a0565b600054610100900460ff16158080156104fb5750600054600160ff909116105b806105155750303b158015610515575060005460ff166001145b6105a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561060457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b60008811610694576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4c324f75747075744f7261636c653a207375626d697373696f6e20696e74657260448201527f76616c206d7573742062652067726561746572207468616e2030000000000000606482015260840161059d565b60008711610724576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4c324f75747075744f7261636c653a204c3220626c6f636b2074696d65206d7560448201527f73742062652067726561746572207468616e2030000000000000000000000000606482015260840161059d565b428511156107db576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526044602482018190527f4c324f75747075744f7261636c653a207374617274696e67204c322074696d65908201527f7374616d70206d757374206265206c657373207468616e2063757272656e742060648201527f74696d6500000000000000000000000000000000000000000000000000000000608482015260a40161059d565b60048890556005879055600186905560028590556007805473ffffffffffffffffffffffffffffffffffffffff8087167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179092556006805492861692909116919091179055600882905580156108ac57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b6003546000901561092057600380546108d1906001906114f2565b815481106108e1576108e1611509565b600091825260209091206002909102016001015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16919050565b6001545b905090565b600354600090610924906001906114f2565b60006109456108b6565b8211156109fa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f4c324f75747075744f7261636c653a2063616e6e6f7420676574206f7574707560448201527f7420666f72206120626c6f636b207468617420686173206e6f74206265656e2060648201527f70726f706f736564000000000000000000000000000000000000000000000000608482015260a40161059d565b600354610aaf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f4c324f75747075744f7261636c653a2063616e6e6f7420676574206f7574707560448201527f74206173206e6f206f7574707574732068617665206265656e2070726f706f7360648201527f6564207965740000000000000000000000000000000000000000000000000000608482015260a40161059d565b6003546000905b80821015610b485760006002610acc8385611538565b610ad69190611550565b90508460038281548110610aec57610aec611509565b600091825260209091206002909102016001015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff161015610b3e57610b37816001611538565b9250610b42565b8091505b50610ab6565b5092915050565b60065473ffffffffffffffffffffffffffffffffffffffff163314610bf6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f4c324f75747075744f7261636c653a206f6e6c7920746865206368616c6c656e60448201527f67657220616464726573732063616e2064656c657465206f7574707574730000606482015260840161059d565b6003548110610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f4c324f75747075744f7261636c653a2063616e6e6f742064656c657465206f7560448201527f747075747320616674657220746865206c6174657374206f757470757420696e60648201527f6465780000000000000000000000000000000000000000000000000000000000608482015260a40161059d565b60085460038281548110610cc357610cc3611509565b6000918252602090912060016002909202010154610cf3906fffffffffffffffffffffffffffffffff16426114f2565b10610da6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f4c324f75747075744f7261636c653a2063616e6e6f742064656c657465206f7560448201527f74707574732074686174206861766520616c7265616479206265656e2066696e60648201527f616c697a65640000000000000000000000000000000000000000000000000000608482015260a40161059d565b6000610db160035490565b90508160035581817f4ee37ac2c786ec85e87592d3c5c8a1dd66f8496dda3f125d9ea8ca5f657629b660405160405180910390a35050565b60075473ffffffffffffffffffffffffffffffffffffffff163314610eb6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f4c324f75747075744f7261636c653a206f6e6c79207468652070726f706f736560448201527f7220616464726573732063616e2070726f706f7365206e6577206f757470757460648201527f7300000000000000000000000000000000000000000000000000000000000000608482015260a40161059d565b610ebe611346565b8314610f72576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f4c324f75747075744f7261636c653a20626c6f636b206e756d626572206d757360448201527f7420626520657175616c20746f206e65787420657870656374656420626c6f6360648201527f6b206e756d626572000000000000000000000000000000000000000000000000608482015260a40161059d565b42610f7c84611316565b10611009576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f4c324f75747075744f7261636c653a2063616e6e6f742070726f706f7365204c60448201527f32206f757470757420696e207468652066757475726500000000000000000000606482015260840161059d565b83611096576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4c324f75747075744f7261636c653a204c32206f75747075742070726f706f7360448201527f616c2063616e6e6f7420626520746865207a65726f2068617368000000000000606482015260840161059d565b81156111525781814014611152576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604960248201527f4c324f75747075744f7261636c653a20626c6f636b206861736820646f65732060448201527f6e6f74206d61746368207468652068617368206174207468652065787065637460648201527f6564206865696768740000000000000000000000000000000000000000000000608482015260a40161059d565b8261115c60035490565b857fa7aaf2512769da4e444e3de247be2564225c2e7a8f74cfe528e46e17d24868e24260405161118e91815260200190565b60405180910390a45050604080516060810182529283526fffffffffffffffffffffffffffffffff4281166020850190815292811691840191825260038054600181018255600091909152935160029094027fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b810194909455915190518216700100000000000000000000000000000000029116177fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85c90910155565b60408051606081018252600080825260208201819052918101919091526003828154811061127a5761127a611509565b600091825260209182902060408051606081018252600290930290910180548352600101546fffffffffffffffffffffffffffffffff8082169484019490945270010000000000000000000000000000000090049092169181019190915292915050565b604080516060810182526000808252602082018190529181019190915260036113068361093b565b8154811061127a5761127a611509565b60006005546001548361132991906114f2565b611333919061158b565b6002546113409190611538565b92915050565b60006004546113536108b6565b6109249190611538565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b803573ffffffffffffffffffffffffffffffffffffffff8116811461139d57600080fd5b919050565b600080600080600080600060e0888a0312156113bd57600080fd5b873596506020880135955060408801359450606088013593506113e260808901611379565b92506113f060a08901611379565b915060c0880135905092959891949750929550565b600060208083528351808285015260005b8181101561143257858101830151858201604001528201611416565b81811115611444576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b60006020828403121561148a57600080fd5b5035919050565b600080600080608085870312156114a757600080fd5b5050823594602084013594506040840135936060013592509050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015611504576115046114c3565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000821982111561154b5761154b6114c3565b500190565b600082611586577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156115c3576115c36114c3565b50029056fea164736f6c634300080f000a"; - bytes internal constant optimismPortal2Code =
+- hex"60806040526004361061018a5760003560e01c806389c44cbb116100d6578063ce5db8d61161007f578063dcec334811610059578063dcec33481461049b578063e1a41bcf146104b0578063f4daa291146104c657600080fd5b8063ce5db8d614610445578063cf8e5cf01461045b578063d1de856c1461047b57600080fd5b8063a25ae557116100b0578063a25ae55714610391578063a8e4fb90146103ed578063bffa7f0f1461041a57600080fd5b806389c44cbb1461034857806393991af3146103685780639aaab6481461037e57600080fd5b806369f16eec1161013857806370872aa51161011257806370872aa5146102fc5780637f00642014610312578063887862721461033257600080fd5b806369f16eec146102a75780636abcf563146102bc5780636b4d98dd146102d157600080fd5b8063529933df11610169578063529933df146101ea578063534db0e2146101ff57806354fd4d501461025157600080fd5b80622134cc1461018f5780631c89c97d146101b35780634599c788146101d5575b600080fd5b34801561019b57600080fd5b506005545b6040519081526020015b60405180910390f35b3480156101bf57600080fd5b506101d36101ce3660046113a2565b6104db565b005b3480156101e157600080fd5b506101a06108b6565b3480156101f657600080fd5b506004546101a0565b34801561020b57600080fd5b5060065461022c9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101aa565b34801561025d57600080fd5b5061029a6040518060400160405280600581526020017f312e382e3000000000000000000000000000000000000000000000000000000081525081565b6040516101aa9190611405565b3480156102b357600080fd5b506101a0610929565b3480156102c857600080fd5b506003546101a0565b3480156102dd57600080fd5b5060065473ffffffffffffffffffffffffffffffffffffffff1661022c565b34801561030857600080fd5b506101a060015481565b34801561031e57600080fd5b506101a061032d366004611478565b61093b565b34801561033e57600080fd5b506101a060025481565b34801561035457600080fd5b506101d3610363366004611478565b610b4f565b34801561037457600080fd5b506101a060055481565b6101d361038c366004611491565b610de9565b34801561039d57600080fd5b506103b16103ac366004611478565b61124a565b60408051825181526020808401516fffffffffffffffffffffffffffffffff9081169183019190915292820151909216908201526060016101aa565b3480156103f957600080fd5b5060075461022c9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561042657600080fd5b5060075473ffffffffffffffffffffffffffffffffffffffff1661022c565b34801561045157600080fd5b506101a060085481565b34801561046757600080fd5b506103b1610476366004611478565b6112de565b34801561048757600080fd5b506101a0610496366004611478565b611316565b3480156104a757600080fd5b506101a0611346565b3480156104bc57600080fd5b506101a060045481565b3480156104d257600080fd5b506008546101a0565b600054610100900460ff16158080156104fb5750600054600160ff909116105b806105155750303b158015610515575060005460ff166001145b6105a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561060457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b60008811610694576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4c324f75747075744f7261636c653a207375626d697373696f6e20696e74657260448201527f76616c206d7573742062652067726561746572207468616e2030000000000000606482015260840161059d565b60008711610724576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4c324f75747075744f7261636c653a204c3220626c6f636b2074696d65206d7560448201527f73742062652067726561746572207468616e2030000000000000000000000000606482015260840161059d565b428511156107db576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526044602482018190527f4c324f75747075744f7261636c653a207374617274696e67204c322074696d65908201527f7374616d70206d757374206265206c657373207468616e2063757272656e742060648201527f74696d6500000000000000000000000000000000000000000000000000000000608482015260a40161059d565b60048890556005879055600186905560028590556007805473ffffffffffffffffffffffffffffffffffffffff8087167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179092556006805492861692909116919091179055600882905580156108ac57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b6003546000901561092057600380546108d1906001906114f2565b815481106108e1576108e1611509565b600091825260209091206002909102016001015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16919050565b6001545b905090565b600354600090610924906001906114f2565b60006109456108b6565b8211156109fa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f4c324f75747075744f7261636c653a2063616e6e6f7420676574206f7574707560448201527f7420666f72206120626c6f636b207468617420686173206e6f74206265656e2060648201527f70726f706f736564000000000000000000000000000000000000000000000000608482015260a40161059d565b600354610aaf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f4c324f75747075744f7261636c653a2063616e6e6f7420676574206f7574707560448201527f74206173206e6f206f7574707574732068617665206265656e2070726f706f7360648201527f6564207965740000000000000000000000000000000000000000000000000000608482015260a40161059d565b6003546000905b80821015610b485760006002610acc8385611538565b610ad69190611550565b90508460038281548110610aec57610aec611509565b600091825260209091206002909102016001015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff161015610b3e57610b37816001611538565b9250610b42565b8091505b50610ab6565b5092915050565b60065473ffffffffffffffffffffffffffffffffffffffff163314610bf6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f4c324f75747075744f7261636c653a206f6e6c7920746865206368616c6c656e60448201527f67657220616464726573732063616e2064656c657465206f7574707574730000606482015260840161059d565b6003548110610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f4c324f75747075744f7261636c653a2063616e6e6f742064656c657465206f7560448201527f747075747320616674657220746865206c6174657374206f757470757420696e60648201527f6465780000000000000000000000000000000000000000000000000000000000608482015260a40161059d565b60085460038281548110610cc357610cc3611509565b6000918252602090912060016002909202010154610cf3906fffffffffffffffffffffffffffffffff16426114f2565b10610da6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f4c324f75747075744f7261636c653a2063616e6e6f742064656c657465206f7560448201527f74707574732074686174206861766520616c7265616479206265656e2066696e60648201527f616c697a65640000000000000000000000000000000000000000000000000000608482015260a40161059d565b6000610db160035490565b90508160035581817f4ee37ac2c786ec85e87592d3c5c8a1dd66f8496dda3f125d9ea8ca5f657629b660405160405180910390a35050565b60075473ffffffffffffffffffffffffffffffffffffffff163314610eb6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f4c324f75747075744f7261636c653a206f6e6c79207468652070726f706f736560448201527f7220616464726573732063616e2070726f706f7365206e6577206f757470757460648201527f7300000000000000000000000000000000000000000000000000000000000000608482015260a40161059d565b610ebe611346565b8314610f72576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f4c324f75747075744f7261636c653a20626c6f636b206e756d626572206d757360448201527f7420626520657175616c20746f206e65787420657870656374656420626c6f6360648201527f6b206e756d626572000000000000000000000000000000000000000000000000608482015260a40161059d565b42610f7c84611316565b10611009576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f4c324f75747075744f7261636c653a2063616e6e6f742070726f706f7365204c60448201527f32206f757470757420696e207468652066757475726500000000000000000000606482015260840161059d565b83611096576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4c324f75747075744f7261636c653a204c32206f75747075742070726f706f7360448201527f616c2063616e6e6f7420626520746865207a65726f2068617368000000000000606482015260840161059d565b81156111525781814014611152576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604960248201527f4c324f75747075744f7261636c653a20626c6f636b206861736820646f65732060448201527f6e6f74206d61746368207468652068617368206174207468652065787065637460648201527f6564206865696768740000000000000000000000000000000000000000000000608482015260a40161059d565b8261115c60035490565b857fa7aaf2512769da4e444e3de247be2564225c2e7a8f74cfe528e46e17d24868e24260405161118e91815260200190565b60405180910390a45050604080516060810182529283526fffffffffffffffffffffffffffffffff4281166020850190815292811691840191825260038054600181018255600091909152935160029094027fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b810194909455915190518216700100000000000000000000000000000000029116177fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85c90910155565b60408051606081018252600080825260208201819052918101919091526003828154811061127a5761127a611509565b600091825260209182902060408051606081018252600290930290910180548352600101546fffffffffffffffffffffffffffffffff8082169484019490945270010000000000000000000000000000000090049092169181019190915292915050565b604080516060810182526000808252602082018190529181019190915260036113068361093b565b8154811061127a5761127a611509565b60006005546001548361132991906114f2565b611333919061158b565b6002546113409190611538565b92915050565b60006004546113536108b6565b6109249190611538565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b803573ffffffffffffffffffffffffffffffffffffffff8116811461139d57600080fd5b919050565b600080600080600080600060e0888a0312156113bd57600080fd5b873596506020880135955060408801359450606088013593506113e260808901611379565b92506113f060a08901611379565b915060c0880135905092959891949750929550565b600060208083528351808285015260005b8181101561143257858101830151858201604001528201611416565b81811115611444576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b60006020828403121561148a57600080fd5b5035919050565b600080600080608085870312156114a757600080fd5b5050823594602084013594506040840135936060013592509050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015611504576115046114c3565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000821982111561154b5761154b6114c3565b500190565b600082611586577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156115c3576115c36114c3565b50029056fea164736f6c634300080f000a"; ++ hex"60806040526004361061018a5760003560e01c806389c44cbb116100d6578063ce5db8d61161007f578063dcec334811610059578063dcec33481461049b578063e1a41bcf146104b0578063f4daa291146104c657600080fd5b8063ce5db8d614610445578063cf8e5cf01461045b578063d1de856c1461047b57600080fd5b8063a25ae557116100b0578063a25ae55714610391578063a8e4fb90146103ed578063bffa7f0f1461041a57600080fd5b806389c44cbb1461034857806393991af3146103685780639aaab6481461037e57600080fd5b806369f16eec1161013857806370872aa51161011257806370872aa5146102fc5780637f00642014610312578063887862721461033257600080fd5b806369f16eec146102a75780636abcf563146102bc5780636b4d98dd146102d157600080fd5b8063529933df11610169578063529933df146101ea578063534db0e2146101ff57806354fd4d501461025157600080fd5b80622134cc1461018f5780631c89c97d146101b35780634599c788146101d5575b600080fd5b34801561019b57600080fd5b506005545b6040519081526020015b60405180910390f35b3480156101bf57600080fd5b506101d36101ce3660046113a2565b6104db565b005b3480156101e157600080fd5b506101a06108b6565b3480156101f657600080fd5b506004546101a0565b34801561020b57600080fd5b5060065461022c9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101aa565b34801561025d57600080fd5b5061029a6040518060400160405280600c81526020017f312e382e312d626574612e31000000000000000000000000000000000000000081525081565b6040516101aa9190611405565b3480156102b357600080fd5b506101a0610929565b3480156102c857600080fd5b506003546101a0565b3480156102dd57600080fd5b5060065473ffffffffffffffffffffffffffffffffffffffff1661022c565b34801561030857600080fd5b506101a060015481565b34801561031e57600080fd5b506101a061032d366004611478565b61093b565b34801561033e57600080fd5b506101a060025481565b34801561035457600080fd5b506101d3610363366004611478565b610b4f565b34801561037457600080fd5b506101a060055481565b6101d361038c366004611491565b610de9565b34801561039d57600080fd5b506103b16103ac366004611478565b61124a565b60408051825181526020808401516fffffffffffffffffffffffffffffffff9081169183019190915292820151909216908201526060016101aa565b3480156103f957600080fd5b5060075461022c9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561042657600080fd5b5060075473ffffffffffffffffffffffffffffffffffffffff1661022c565b34801561045157600080fd5b506101a060085481565b34801561046757600080fd5b506103b1610476366004611478565b6112de565b34801561048757600080fd5b506101a0610496366004611478565b611316565b3480156104a757600080fd5b506101a0611346565b3480156104bc57600080fd5b506101a060045481565b3480156104d257600080fd5b506008546101a0565b600054610100900460ff16158080156104fb5750600054600160ff909116105b806105155750303b158015610515575060005460ff166001145b6105a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561060457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b60008811610694576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4c324f75747075744f7261636c653a207375626d697373696f6e20696e74657260448201527f76616c206d7573742062652067726561746572207468616e2030000000000000606482015260840161059d565b60008711610724576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4c324f75747075744f7261636c653a204c3220626c6f636b2074696d65206d7560448201527f73742062652067726561746572207468616e2030000000000000000000000000606482015260840161059d565b428511156107db576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526044602482018190527f4c324f75747075744f7261636c653a207374617274696e67204c322074696d65908201527f7374616d70206d757374206265206c657373207468616e2063757272656e742060648201527f74696d6500000000000000000000000000000000000000000000000000000000608482015260a40161059d565b60048890556005879055600186905560028590556007805473ffffffffffffffffffffffffffffffffffffffff8087167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179092556006805492861692909116919091179055600882905580156108ac57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b6003546000901561092057600380546108d1906001906114f2565b815481106108e1576108e1611509565b600091825260209091206002909102016001015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16919050565b6001545b905090565b600354600090610924906001906114f2565b60006109456108b6565b8211156109fa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f4c324f75747075744f7261636c653a2063616e6e6f7420676574206f7574707560448201527f7420666f72206120626c6f636b207468617420686173206e6f74206265656e2060648201527f70726f706f736564000000000000000000000000000000000000000000000000608482015260a40161059d565b600354610aaf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f4c324f75747075744f7261636c653a2063616e6e6f7420676574206f7574707560448201527f74206173206e6f206f7574707574732068617665206265656e2070726f706f7360648201527f6564207965740000000000000000000000000000000000000000000000000000608482015260a40161059d565b6003546000905b80821015610b485760006002610acc8385611538565b610ad69190611550565b90508460038281548110610aec57610aec611509565b600091825260209091206002909102016001015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff161015610b3e57610b37816001611538565b9250610b42565b8091505b50610ab6565b5092915050565b60065473ffffffffffffffffffffffffffffffffffffffff163314610bf6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f4c324f75747075744f7261636c653a206f6e6c7920746865206368616c6c656e60448201527f67657220616464726573732063616e2064656c657465206f7574707574730000606482015260840161059d565b6003548110610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f4c324f75747075744f7261636c653a2063616e6e6f742064656c657465206f7560448201527f747075747320616674657220746865206c6174657374206f757470757420696e60648201527f6465780000000000000000000000000000000000000000000000000000000000608482015260a40161059d565b60085460038281548110610cc357610cc3611509565b6000918252602090912060016002909202010154610cf3906fffffffffffffffffffffffffffffffff16426114f2565b10610da6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f4c324f75747075744f7261636c653a2063616e6e6f742064656c657465206f7560448201527f74707574732074686174206861766520616c7265616479206265656e2066696e60648201527f616c697a65640000000000000000000000000000000000000000000000000000608482015260a40161059d565b6000610db160035490565b90508160035581817f4ee37ac2c786ec85e87592d3c5c8a1dd66f8496dda3f125d9ea8ca5f657629b660405160405180910390a35050565b60075473ffffffffffffffffffffffffffffffffffffffff163314610eb6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f4c324f75747075744f7261636c653a206f6e6c79207468652070726f706f736560448201527f7220616464726573732063616e2070726f706f7365206e6577206f757470757460648201527f7300000000000000000000000000000000000000000000000000000000000000608482015260a40161059d565b610ebe611346565b8314610f72576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f4c324f75747075744f7261636c653a20626c6f636b206e756d626572206d757360448201527f7420626520657175616c20746f206e65787420657870656374656420626c6f6360648201527f6b206e756d626572000000000000000000000000000000000000000000000000608482015260a40161059d565b42610f7c84611316565b10611009576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f4c324f75747075744f7261636c653a2063616e6e6f742070726f706f7365204c60448201527f32206f757470757420696e207468652066757475726500000000000000000000606482015260840161059d565b83611096576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4c324f75747075744f7261636c653a204c32206f75747075742070726f706f7360448201527f616c2063616e6e6f7420626520746865207a65726f2068617368000000000000606482015260840161059d565b81156111525781814014611152576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604960248201527f4c324f75747075744f7261636c653a20626c6f636b206861736820646f65732060448201527f6e6f74206d61746368207468652068617368206174207468652065787065637460648201527f6564206865696768740000000000000000000000000000000000000000000000608482015260a40161059d565b8261115c60035490565b857fa7aaf2512769da4e444e3de247be2564225c2e7a8f74cfe528e46e17d24868e24260405161118e91815260200190565b60405180910390a45050604080516060810182529283526fffffffffffffffffffffffffffffffff4281166020850190815292811691840191825260038054600181018255600091909152935160029094027fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b810194909455915190518216700100000000000000000000000000000000029116177fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85c90910155565b60408051606081018252600080825260208201819052918101919091526003828154811061127a5761127a611509565b600091825260209182902060408051606081018252600290930290910180548352600101546fffffffffffffffffffffffffffffffff8082169484019490945270010000000000000000000000000000000090049092169181019190915292915050565b604080516060810182526000808252602082018190529181019190915260036113068361093b565b8154811061127a5761127a611509565b60006005546001548361132991906114f2565b611333919061158b565b6002546113409190611538565b92915050565b60006004546113536108b6565b6109249190611538565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b803573ffffffffffffffffffffffffffffffffffffffff8116811461139d57600080fd5b919050565b600080600080600080600060e0888a0312156113bd57600080fd5b873596506020880135955060408801359450606088013593506113e260808901611379565b92506113f060a08901611379565b915060c0880135905092959891949750929550565b600060208083528351808285015260005b8181101561143257858101830151858201604001528201611416565b81811115611444576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b60006020828403121561148a57600080fd5b5035919050565b600080600080608085870312156114a757600080fd5b5050823594602084013594506040840135936060013592509050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015611504576115046114c3565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000821982111561154b5761154b6114c3565b500190565b600082611586577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156115c3576115c36114c3565b50029056fea164736f6c634300080f000a"; + bytes internal constant optimismPortal2Code = +- hex"6080604052600436106101d15760003560e01c80637fc48504116100f7578063a35d99df11610095578063bf653a5c11610064578063bf653a5c14610697578063cff0ab96146106ca578063e9e05c421461076b578063f2b4e6171461077e57600080fd5b8063a35d99df1461059b578063a3860f48146105bb578063b69ef8a8146105db578063bb2c727e146105f057600080fd5b80638e819e54116100d15780638e819e54146104eb578063952b27971461050b5780639bf62d821461053e578063a14238e71461056b57600080fd5b80637fc48504146104ab5780638b4c40b0146101f65780638c3152e9146104cb57600080fd5b80634870496f1161016f5780635c975abb1161013e5780635c975abb1461043657806371c1566e1461044b57806371cfaa3f1461046b5780637d6be8dc1461048b57600080fd5b80634870496f1461034d5780634fd0434c1461036d578063513747ab146103af57806354fd4d50146103ea57600080fd5b80633c9f397c116101ab5780633c9f397c146102a657806343ca1c50146102d8578063452a9320146102f857806345884d321461030d57600080fd5b8063149f2f22146101fd57806333d7e2bd1461021d57806335e80ab31461027457600080fd5b366101f8576101f63334620186a06000604051806020016040528060008152506107ab565b005b600080fd5b34801561020957600080fd5b506101f6610218366004614fe6565b610850565b34801561022957600080fd5b5060375461024a9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561028057600080fd5b5060355461024a90610100900473ffffffffffffffffffffffffffffffffffffffff1681565b3480156102b257600080fd5b50603b546102c39063ffffffff1681565b60405163ffffffff909116815260200161026b565b3480156102e457600080fd5b506101f66102f336600461511c565b610a91565b34801561030457600080fd5b5061024a610f31565b34801561031957600080fd5b5061033d61032836600461516e565b603a6020526000908152604090205460ff1681565b604051901515815260200161026b565b34801561035957600080fd5b506101f661036836600461518b565b610fc9565b34801561037957600080fd5b50603b5461039690640100000000900467ffffffffffffffff1681565b60405167ffffffffffffffff909116815260200161026b565b3480156103bb57600080fd5b506103dc6103ca366004615267565b6000908152603c602052604090205490565b60405190815260200161026b565b3480156103f657600080fd5b50604080518082018252600d81527f332e31312e302d626574612e32000000000000000000000000000000000000006020820152905161026b91906152f6565b34801561044257600080fd5b5061033d611531565b34801561045757600080fd5b506101f6610466366004615309565b6115c4565b34801561047757600080fd5b506101f661048636600461533d565b611c7f565b34801561049757600080fd5b506101f66104a636600461516e565b611e3f565b3480156104b757600080fd5b506101f66104c6366004615395565b611f22565b3480156104d757600080fd5b506101f66104e63660046153b2565b61200e565b3480156104f757600080fd5b506101f66105063660046153ef565b61205a565b34801561051757600080fd5b507f00000000000000000000000000000000000000000000000000000000000000066103dc565b34801561054a57600080fd5b5060325461024a9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561057757600080fd5b5061033d610586366004615267565b60336020526000908152604090205460ff1681565b3480156105a757600080fd5b506103966105b636600461544b565b61230f565b3480156105c757600080fd5b5061024a6105d6366004615468565b61232e565b3480156105e757600080fd5b506103dc612373565b3480156105fc57600080fd5b5061066261060b366004615309565b603960209081526000928352604080842090915290825290205473ffffffffffffffffffffffffffffffffffffffff81169074010000000000000000000000000000000000000000900467ffffffffffffffff1682565b6040805173ffffffffffffffffffffffffffffffffffffffff909316835267ffffffffffffffff90911660208301520161026b565b3480156106a357600080fd5b507f000000000000000000000000000000000000000000000000000000000000000c6103dc565b3480156106d657600080fd5b50600154610732906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff928316602085015291169082015260600161026b565b6101f661077936600461548a565b6107ab565b34801561078a57600080fd5b5060385461024a9073ffffffffffffffffffffffffffffffffffffffff1681565b8260005a905060006107bb6123e9565b50905073ffffffffffffffffffffffffffffffffffffffff811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee148015906107f757503415155b1561082e576040517ff2365b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61083c883489898989612486565b506108478282612632565b50505050505050565b8260005a905060006108606123e9565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8216016108d2576040517f0eaf3c0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87603d60008282546108e49190615538565b90915550506040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015610956573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097a9190615550565b905061099e73ffffffffffffffffffffffffffffffffffffffff831633308c6128ff565b6109a88982615538565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa158015610a12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a369190615550565b14610a6d576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a7b8a8a8a8a8a8a612486565b5050610a878282612632565b5050505050505050565b610a99611531565b15610ad0576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60325473ffffffffffffffffffffffffffffffffffffffff1661dead14610b23576040517f9396d15600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610b2e836129e1565b9050610b3a81836115c4565b6000818152603360209081526040822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558401516032805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff000000000000000000000000000000000000000090921691909117905580610bc56123e9565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff821601610c2857610c218560400151866080015187606001518860a00151612a2e565b9150610e7b565b8073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff1603610c91576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606085015115610e52578460600151603d6000828254610cb19190615569565b90915550506040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015610d23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d479190615550565b9050610d7c866040015187606001518473ffffffffffffffffffffffffffffffffffffffff16612a8c9092919063ffffffff16565b6060860151610d8b9082615569565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa158015610df5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e199190615550565b14610e50576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b60a08501515115610e7657610c218560400151866080015160008860a00151612a2e565b600191505b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405183907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b90610edd90851515815260200190565b60405180910390a281158015610ef35750326001145b15610f2a576040517feeae4ed300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa158015610fa0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc49190615580565b905090565b610fd1611531565b15611008576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff1603611071576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6038546040517fbb8aa1fc00000000000000000000000000000000000000000000000000000000815260048101869052600091829173ffffffffffffffffffffffffffffffffffffffff9091169063bb8aa1fc90602401606060405180830381865afa1580156110e5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611109919061559d565b925050915060008173ffffffffffffffffffffffffffffffffffffffff1663bcef3b556040518163ffffffff1660e01b8152600401602060405180830381865afa15801561115b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061117f9190615550565b603b5490915063ffffffff8481169116146111c6576040517f27a10cc200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111dd6111d8368890038801886155ea565b612ae7565b8114611215576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611220896129e1565b905060018373ffffffffffffffffffffffffffffffffffffffff1663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa15801561126f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611293919061567f565b60028111156112a4576112a4615650565b036112db576040517fd357347400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051602081018390526000918101829052606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012090830181905292506113a49101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152600182527f010000000000000000000000000000000000000000000000000000000000000060208301529061139a898b6156a0565b8b60400135612b26565b15156000036113df576040517fb05e92fa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051808201825273ffffffffffffffffffffffffffffffffffffffff808716825267ffffffffffffffff4281166020808501918252600088815260398252868120338252825286812095518654935190941674010000000000000000000000000000000000000000027fffffffff0000000000000000000000000000000000000000000000000000000090931693851693909317919091179093558d840151928e01519351928216939091169185917f67a6208cfcc0801d50f6cbe764733f4fddf66ac0b04442061a8a8c0cb6b63f6291a4604051339083907f798f9f13695f8f045aa5f80ed8efebb695f3c7fe65da381969f2f28bf3c60b9790600090a3506000908152603c602090815260408220805460018101825590835291200180547fffffffffffffffffffffffff000000000000000000000000000000000000000016331790555050505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115a0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc49190615724565b600082815260396020908152604080832073ffffffffffffffffffffffffffffffffffffffff85811685529083528184208251808401845290549182168082527401000000000000000000000000000000000000000090920467ffffffffffffffff1681850152818552603a90935292205490919060ff1615611673576040517f09550c7700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b816020015167ffffffffffffffff166000036116bb576040517f94efd49b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061173c8273ffffffffffffffffffffffffffffffffffffffff1663cf09e0d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561170b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061172f9190615741565b67ffffffffffffffff1690565b90508067ffffffffffffffff16836020015167ffffffffffffffff1611611810576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604e60248201527f4f7074696d69736d506f7274616c3a207769746864726177616c2074696d657360448201527f74616d70206c657373207468616e20646973707574652067616d65206372656160648201527f74696f6e2074696d657374616d70000000000000000000000000000000000000608482015260a4015b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000c836020015167ffffffffffffffff164261184b9190615569565b116118d8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4f7074696d69736d506f7274616c3a2070726f76656e2077697468647261776160448201527f6c20686173206e6f74206d6174757265642079657400000000000000000000006064820152608401611807565b60028273ffffffffffffffffffffffffffffffffffffffff1663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611925573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611949919061567f565b600281111561195a5761195a615650565b14611991576040517fa080a3c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603b5463ffffffff1663ffffffff16611a1b8373ffffffffffffffffffffffffffffffffffffffff1663bbdc02db6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119ee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a12919061575e565b63ffffffff1690565b63ffffffff1614611a58576040517f27a10cc200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603b5467ffffffffffffffff64010000000090910481169082161015611b26576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604b60248201527f4f7074696d69736d506f7274616c3a20646973707574652067616d652063726560448201527f61746564206265666f7265207265737065637465642067616d6520747970652060648201527f7761732075706461746564000000000000000000000000000000000000000000608482015260a401611807565b7f0000000000000000000000000000000000000000000000000000000000000006611b958373ffffffffffffffffffffffffffffffffffffffff166319effeb46040518163ffffffff1660e01b8152600401602060405180830381865afa15801561170b573d6000803e3d6000fd5b611ba99067ffffffffffffffff1642615569565b11611c36576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4f7074696d69736d506f7274616c3a206f75747075742070726f706f73616c2060448201527f696e206169722d676170000000000000000000000000000000000000000000006064820152608401611807565b60008581526033602052604090205460ff1615610f2a576040517f475a253500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60375473ffffffffffffffffffffffffffffffffffffffff163314611cd0576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611cdc62030d40612b4a565b60405173ffffffffffffffffffffffffffffffffffffffff8516602482015260ff8416604482015260648101839052608481018290526000907342000000000000000000000000000000000000159073deaddeaddeaddeaddeaddeaddeaddeaddead0001907fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32908490819062030d4090829060a401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f71cfaa3f000000000000000000000000000000000000000000000000000000001790529051611df99695949392910161577b565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815290829052611e31916152f6565b60405180910390a450505050565b611e47610f31565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611eab576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81166000818152603a602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055517f192c289026d59a41a27f5aea08f3969b57931b0589202d14f4368cded95d3cda9190a250565b611f2a610f31565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611f8e576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603b805463ffffffff83167fffffffffffffffffffffffffffffffffffffffff00000000000000000000000090911681176401000000004267ffffffffffffffff90811682029290921793849055604051930416917f049fe9dd413cdf037cce27011cc1790c753118272f3630e6e8bdfa5e8208176090600090a350565b565b612016611531565b1561204d576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6120578133610a91565b50565b600054610100900460ff161580801561207a5750600054600160ff909116105b806120945750303b158015612094575060005460ff166001145b612120576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401611807565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561217e57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603880547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff8881169190911790925560378054909116868316179055603580547fffffffffffffffffffffff0000000000000000000000000000000000000000ff16610100868416021790556032541661229e576032805461dead7fffffffffffffffffffffffff0000000000000000000000000000000000000000909116179055603b80547fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166401000000004267ffffffffffffffff16027fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000161763ffffffff84161790555b6122a6612bac565b8015610f2a57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050505050565b600061231c8260106157e0565b61232890615208615810565b92915050565b603c602052816000526040600020818154811061234a57600080fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff169150829050565b60008061237e6123e9565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8216016123c5574791505090565b5050603d5490565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b603754604080517f4397dfef0000000000000000000000000000000000000000000000000000000081528151600093849373ffffffffffffffffffffffffffffffffffffffff90911692634397dfef92600480830193928290030181865afa158015612459573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061247d919061583c565b90939092509050565b8180156124a8575073ffffffffffffffffffffffffffffffffffffffff861615155b156124df576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6124e9815161230f565b67ffffffffffffffff168367ffffffffffffffff161015612536576040517f4929b80800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6201d4c081511115612574576040517f73052b0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b33328114612595575033731111000000000000000000000000000000001111015b600086868686866040516020016125b095949392919061577b565b604051602081830303815290604052905060008873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c328460405161262091906152f6565b60405180910390a45050505050505050565b600154600090612668907801000000000000000000000000000000000000000000000000900467ffffffffffffffff1643615569565b90506000612674612cbf565b90506000816020015160ff16826000015163ffffffff16612695919061589a565b905082156127cc576001546000906126cc908390700100000000000000000000000000000000900467ffffffffffffffff16615902565b90506000836040015160ff16836126e39190615976565b6001546127039084906fffffffffffffffffffffffffffffffff16615976565b61270d919061589a565b60015490915060009061275e906127379084906fffffffffffffffffffffffffffffffff16615a32565b866060015163ffffffff168760a001516fffffffffffffffffffffffffffffffff16612d80565b9050600186111561278d5761278a61273782876040015160ff1660018a6127859190615569565b612d9f565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760015550505b600180548691906010906127ff908490700100000000000000000000000000000000900467ffffffffffffffff16615810565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550816000015163ffffffff16600160000160109054906101000a900467ffffffffffffffff1667ffffffffffffffff16131561288c576040517f77ebef4d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001546000906128b8906fffffffffffffffffffffffffffffffff1667ffffffffffffffff8816615aa6565b905060006128ca48633b9aca00612df4565b6128d49083615ae3565b905060005a6128e39088615569565b905080821115610a8757610a876128fa8284615569565b612e0b565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526129db9085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152612e34565b50505050565b80516020808301516040808501516060860151608087015160a08801519351600097612a11979096959101615af7565b604051602081830303815290604052805190602001209050919050565b6000806000612a3e866000612f40565b905080612a74576308c379a06000526020805278185361666543616c6c3a204e6f7420656e6f756768206761736058526064601cfd5b600080855160208701888b5af1979650505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052612ae29084907fa9059cbb0000000000000000000000000000000000000000000000000000000090606401612959565b505050565b60008160000151826020015183604001518460600151604051602001612a11949392919093845260208401929092526040830152606082015260800190565b600080612b3286612f5e565b9050612b4081868686612f90565b9695505050505050565b6001805463ffffffff83169190601090612b83908490700100000000000000000000000000000000900467ffffffffffffffff16615810565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555050565b600054610100900460ff16612c43576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401611807565b6001547801000000000000000000000000000000000000000000000000900467ffffffffffffffff1660000361200c5760408051606081018252633b9aca00808252600060208301524367ffffffffffffffff169190920181905278010000000000000000000000000000000000000000000000000217600155565b6040805160c08082018352600080835260208301819052828401819052606083018190526080830181905260a083015260375483517fcc731b020000000000000000000000000000000000000000000000000000000081529351929373ffffffffffffffffffffffffffffffffffffffff9091169263cc731b02926004808401939192918290030181865afa158015612d5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc49190615b4e565b6000612d95612d8f8585612fc0565b83612fd0565b90505b9392505050565b6000670de0b6b3a7640000612de0612db7858361589a565b612dc990670de0b6b3a7640000615902565b612ddb85670de0b6b3a7640000615976565b612fdf565b612dea9086615976565b612d95919061589a565b600081831015612e045781612d98565b5090919050565b6000805a90505b825a612e1e9083615569565b1015612ae257612e2d82615bf0565b9150612e12565b6000612e96826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166130109092919063ffffffff16565b805190915015612ae25780806020019051810190612eb49190615724565b612ae2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401611807565b600080603f83619c4001026040850201603f5a021015949350505050565b60608180519060200120604051602001612f7a91815260200190565b6040516020818303038152906040529050919050565b6000612fb784612fa187868661301f565b8051602091820120825192909101919091201490565b95945050505050565b600081831215612e045781612d98565b6000818312612e045781612d98565b6000612d98670de0b6b3a764000083612ff786613a9d565b6130019190615976565b61300b919061589a565b613ce1565b6060612d958484600085613f20565b6060600084511161308c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4d65726b6c65547269653a20656d707479206b657900000000000000000000006044820152606401611807565b6000613097846140b6565b905060006130a4866141a2565b90506000846040516020016130bb91815260200190565b60405160208183030381529060405290506000805b8451811015613a145760008582815181106130ed576130ed615c28565b602002602001015190508451831115613188576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4d65726b6c65547269653a206b657920696e646578206578636565647320746f60448201527f74616c206b6579206c656e6774680000000000000000000000000000000000006064820152608401611807565b8260000361324157805180516020918201206040516131d6926131b092910190815260200190565b604051602081830303815290604052858051602091820120825192909101919091201490565b61323c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4d65726b6c65547269653a20696e76616c696420726f6f7420686173680000006044820152606401611807565b613398565b8051516020116132f7578051805160209182012060405161326b926131b092910190815260200190565b61323c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d65726b6c65547269653a20696e76616c6964206c6172676520696e7465726e60448201527f616c2068617368000000000000000000000000000000000000000000000000006064820152608401611807565b805184516020808701919091208251919092012014613398576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4d65726b6c65547269653a20696e76616c696420696e7465726e616c206e6f6460448201527f65206861736800000000000000000000000000000000000000000000000000006064820152608401611807565b6133a460106001615538565b816020015151036135805784518303613518576133de81602001516010815181106133d1576133d1615c28565b6020026020010151614205565b96506000875111613471576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603b60248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286272616e63682900000000006064820152608401611807565b6001865161347f9190615569565b821461350d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286272616e6368290000000000006064820152608401611807565b505050505050612d98565b600085848151811061352c5761352c615c28565b602001015160f81c60f81b60f81c9050600082602001518260ff168151811061355757613557615c28565b6020026020010151905061356a816142b9565b9550613577600186615538565b94505050613a01565b600281602001515103613979576000613598826142de565b90506000816000815181106135af576135af615c28565b016020015160f81c905060006135c6600283615c57565b6135d1906002615c79565b905060006135e2848360ff16614302565b905060006135f08a89614302565b905060006135fe8383614338565b905080835114613690576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a20706174682072656d61696e646572206d7573742060448201527f736861726520616c6c206e6962626c65732077697468206b65790000000000006064820152608401611807565b60ff8516600214806136a5575060ff85166003145b15613894578082511461373a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f4d65726b6c65547269653a206b65792072656d61696e646572206d757374206260448201527f65206964656e746963616c20746f20706174682072656d61696e6465720000006064820152608401611807565b61375487602001516001815181106133d1576133d1615c28565b9c5060008d51116137e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286c65616629000000000000006064820152608401611807565b60018c516137f59190615569565b8814613883576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286c6561662900000000000000006064820152608401611807565b505050505050505050505050612d98565b60ff851615806138a7575060ff85166001145b156138e6576138d387602001516001815181106138c6576138c6615c28565b60200260200101516142b9565b99506138df818a615538565b985061396e565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4d65726b6c65547269653a2072656365697665642061206e6f6465207769746860448201527f20616e20756e6b6e6f776e2070726566697800000000000000000000000000006064820152608401611807565b505050505050613a01565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4d65726b6c65547269653a20726563656976656420616e20756e70617273656160448201527f626c65206e6f64650000000000000000000000000000000000000000000000006064820152608401611807565b5080613a0c81615bf0565b9150506130d0565b506040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4d65726b6c65547269653a2072616e206f7574206f662070726f6f6620656c6560448201527f6d656e74730000000000000000000000000000000000000000000000000000006064820152608401611807565b6000808213613b08576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401611807565b60006060613b15846143ec565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c18213613d1257506000919050565b680755bf798b4a1bf1e58212613d84576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4558505f4f564552464c4f5700000000000000000000000000000000000000006044820152606401611807565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b606082471015613fb2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401611807565b73ffffffffffffffffffffffffffffffffffffffff85163b614030576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401611807565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516140599190615c9c565b60006040518083038185875af1925050503d8060008114614096576040519150601f19603f3d011682016040523d82523d6000602084013e61409b565b606091505b50915091506140ab8282866144c2565b979650505050505050565b80516060908067ffffffffffffffff8111156140d4576140d4614eb1565b60405190808252806020026020018201604052801561411957816020015b60408051808201909152606080825260208201528152602001906001900390816140f25790505b50915060005b8181101561419b57604051806040016040528085838151811061414457614144615c28565b6020026020010151815260200161417386848151811061416657614166615c28565b6020026020010151614515565b81525083828151811061418857614188615c28565b602090810291909101015260010161411f565b5050919050565b606080604051905082518060011b603f8101601f1916830160405280835250602084016020830160005b838110156141fa578060011b82018184015160001a8060041c8253600f8116600183015350506001016141cc565b509295945050505050565b6060600080600061421585614528565b91945092509050600081600181111561423057614230615650565b14614267576040517f1ff9b2e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6142718284615538565b8551146142aa576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612fb7856020015184846149c6565b606060208260000151106142d5576142d082614205565b612328565b61232882614a5a565b60606123286142fd83602001516000815181106133d1576133d1615c28565b6141a2565b6060825182106143215750604080516020810190915260008152612328565b612d9883838486516143339190615569565b614a70565b600080825184511061434b57825161434e565b83515b90505b80821080156143d5575082828151811061436d5761436d615c28565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168483815181106143ac576143ac615c28565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b156143e557816001019150614351565b5092915050565b6000808211614457576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401611807565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b606083156144d1575081612d98565b8251156144e15782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161180791906152f6565b606061232861452383614c48565b614cb5565b6000806000836000015160000361456b576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020840151805160001a607f81116145905760006001600094509450945050506149bf565b60b781116146a65760006145a5608083615569565b9050808760000151116145e4576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001838101517fff0000000000000000000000000000000000000000000000000000000000000016908214801561465c57507f80000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000008216105b15614693576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50600195509350600092506149bf915050565b60bf81116148045760006146bb60b783615569565b9050808760000151116146fa576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff0000000000000000000000000000000000000000000000000000000000000016600081900361475c576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c603781116147a4576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6147ae8184615538565b8951116147e7576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6147f2836001615538565b97509550600094506149bf9350505050565b60f7811161486957600061481960c083615569565b905080876000015111614858576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001955093508492506149bf915050565b600061487660f783615569565b9050808760000151116148b5576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614917576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c6037811161495f576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6149698184615538565b8951116149a2576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6149ad836001615538565b97509550600194506149bf9350505050565b9193909250565b60608167ffffffffffffffff8111156149e1576149e1614eb1565b6040519080825280601f01601f191660200182016040528015614a0b576020820181803683370190505b5090508115612d98576000614a208486615538565b90506020820160005b84811015614a41578281015182820152602001614a29565b84811115614a50576000858301525b5050509392505050565b60606123288260200151600084600001516149c6565b60608182601f011015614adf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401611807565b828284011015614b4b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401611807565b81830184511015614bb8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401611807565b606082158015614bd75760405191506000825260208201604052614c3f565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015614c10578051835260209283019201614bf8565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b60408051808201909152600080825260208201528151600003614c97576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50604080518082019091528151815260209182019181019190915290565b60606000806000614cc585614528565b919450925090506001816001811115614ce057614ce0615650565b14614d17576040517f4b9c6abe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8451614d238385615538565b14614d5a576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516020808252610420820190925290816020015b6040805180820190915260008082526020820152815260200190600190039081614d715790505093506000835b8651811015614e5f57600080614de46040518060400160405280858c60000151614dc89190615569565b8152602001858c60200151614ddd9190615538565b9052614528565b509150915060405180604001604052808383614e009190615538565b8152602001848b60200151614e159190615538565b815250888581518110614e2a57614e2a615c28565b6020908102919091010152614e40600185615538565b9350614e4c8183615538565b614e569084615538565b92505050614d9e565b50845250919392505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461205757600080fd5b67ffffffffffffffff8116811461205757600080fd5b801515811461205757600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160c0810167ffffffffffffffff81118282101715614f0357614f03614eb1565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614f5057614f50614eb1565b604052919050565b600082601f830112614f6957600080fd5b813567ffffffffffffffff811115614f8357614f83614eb1565b614fb460207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601614f09565b818152846020838601011115614fc957600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060008060c08789031215614fff57600080fd5b863561500a81614e6b565b95506020870135945060408701359350606087013561502881614e8d565b9250608087013561503881614ea3565b915060a087013567ffffffffffffffff81111561505457600080fd5b61506089828a01614f58565b9150509295509295509295565b600060c0828403121561507f57600080fd5b60405160c0810167ffffffffffffffff82821081831117156150a3576150a3614eb1565b8160405282935084358352602085013591506150be82614e6b565b816020840152604085013591506150d482614e6b565b816040840152606085013560608401526080850135608084015260a085013591508082111561510257600080fd5b5061510f85828601614f58565b60a0830152505092915050565b6000806040838503121561512f57600080fd5b823567ffffffffffffffff81111561514657600080fd5b6151528582860161506d565b925050602083013561516381614e6b565b809150509250929050565b60006020828403121561518057600080fd5b8135612d9881614e6b565b600080600080600085870360e08112156151a457600080fd5b863567ffffffffffffffff808211156151bc57600080fd5b6151c88a838b0161506d565b97506020890135965060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08401121561520157600080fd5b60408901955060c089013592508083111561521b57600080fd5b828901925089601f84011261522f57600080fd5b823591508082111561524057600080fd5b508860208260051b840101111561525657600080fd5b959894975092955050506020019190565b60006020828403121561527957600080fd5b5035919050565b60005b8381101561529b578181015183820152602001615283565b838111156129db5750506000910152565b600081518084526152c4816020860160208601615280565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000612d9860208301846152ac565b6000806040838503121561531c57600080fd5b82359150602083013561516381614e6b565b60ff8116811461205757600080fd5b6000806000806080858703121561535357600080fd5b843561535e81614e6b565b9350602085013561536e8161532e565b93969395505050506040820135916060013590565b63ffffffff8116811461205757600080fd5b6000602082840312156153a757600080fd5b8135612d9881615383565b6000602082840312156153c457600080fd5b813567ffffffffffffffff8111156153db57600080fd5b6153e78482850161506d565b949350505050565b6000806000806080858703121561540557600080fd5b843561541081614e6b565b9350602085013561542081614e6b565b9250604085013561543081614e6b565b9150606085013561544081615383565b939692955090935050565b60006020828403121561545d57600080fd5b8135612d9881614e8d565b6000806040838503121561547b57600080fd5b50508035926020909101359150565b600080600080600060a086880312156154a257600080fd5b85356154ad81614e6b565b94506020860135935060408601356154c481614e8d565b925060608601356154d481614ea3565b9150608086013567ffffffffffffffff8111156154f057600080fd5b6154fc88828901614f58565b9150509295509295909350565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561554b5761554b615509565b500190565b60006020828403121561556257600080fd5b5051919050565b60008282101561557b5761557b615509565b500390565b60006020828403121561559257600080fd5b8151612d9881614e6b565b6000806000606084860312156155b257600080fd5b83516155bd81615383565b60208501519093506155ce81614e8d565b60408501519092506155df81614e6b565b809150509250925092565b6000608082840312156155fc57600080fd5b6040516080810181811067ffffffffffffffff8211171561561f5761561f614eb1565b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60006020828403121561569157600080fd5b815160038110612d9857600080fd5b600067ffffffffffffffff808411156156bb576156bb614eb1565b8360051b60206156cc818301614f09565b8681529185019181810190368411156156e457600080fd5b865b84811015615718578035868111156156fe5760008081fd5b61570a36828b01614f58565b8452509183019183016156e6565b50979650505050505050565b60006020828403121561573657600080fd5b8151612d9881614ea3565b60006020828403121561575357600080fd5b8151612d9881614e8d565b60006020828403121561577057600080fd5b8151612d9881615383565b8581528460208201527fffffffffffffffff0000000000000000000000000000000000000000000000008460c01b16604082015282151560f81b6048820152600082516157cf816049850160208701615280565b919091016049019695505050505050565b600067ffffffffffffffff8083168185168183048111821515161561580757615807615509565b02949350505050565b600067ffffffffffffffff80831681851680830382111561583357615833615509565b01949350505050565b6000806040838503121561584f57600080fd5b825161585a81614e6b565b60208401519092506151638161532e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826158a9576158a961586b565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f8000000000000000000000000000000000000000000000000000000000000000831416156158fd576158fd615509565b500590565b6000808312837f80000000000000000000000000000000000000000000000000000000000000000183128115161561593c5761593c615509565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01831381161561597057615970615509565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6000841360008413858304851182821616156159b7576159b7615509565b7f800000000000000000000000000000000000000000000000000000000000000060008712868205881281841616156159f2576159f2615509565b60008712925087820587128484161615615a0e57615a0e615509565b87850587128184161615615a2457615a24615509565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03841381151615615a6c57615a6c615509565b827f8000000000000000000000000000000000000000000000000000000000000000038412811615615aa057615aa0615509565b50500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615ade57615ade615509565b500290565b600082615af257615af261586b565b500490565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a0830152615b4260c08301846152ac565b98975050505050505050565b600060c08284031215615b6057600080fd5b615b68614ee0565b8251615b7381615383565b81526020830151615b838161532e565b60208201526040830151615b968161532e565b60408201526060830151615ba981615383565b60608201526080830151615bbc81615383565b608082015260a08301516fffffffffffffffffffffffffffffffff81168114615be457600080fd5b60a08201529392505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203615c2157615c21615509565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060ff831680615c6a57615c6a61586b565b8060ff84160691505092915050565b600060ff821660ff841680821015615c9357615c93615509565b90039392505050565b60008251615cae818460208701615280565b919091019291505056fea164736f6c634300080f000a"; ++ hex"6080604052600436106101d15760003560e01c80637fc48504116100f7578063a35d99df11610095578063bf653a5c11610064578063bf653a5c14610697578063cff0ab96146106ca578063e9e05c421461076b578063f2b4e6171461077e57600080fd5b8063a35d99df1461059b578063a3860f48146105bb578063b69ef8a8146105db578063bb2c727e146105f057600080fd5b80638e819e54116100d15780638e819e54146104eb578063952b27971461050b5780639bf62d821461053e578063a14238e71461056b57600080fd5b80637fc48504146104ab5780638b4c40b0146101f65780638c3152e9146104cb57600080fd5b80634870496f1161016f5780635c975abb1161013e5780635c975abb1461043657806371c1566e1461044b57806371cfaa3f1461046b5780637d6be8dc1461048b57600080fd5b80634870496f1461034d5780634fd0434c1461036d578063513747ab146103af57806354fd4d50146103ea57600080fd5b80633c9f397c116101ab5780633c9f397c146102a657806343ca1c50146102d8578063452a9320146102f857806345884d321461030d57600080fd5b8063149f2f22146101fd57806333d7e2bd1461021d57806335e80ab31461027457600080fd5b366101f8576101f63334620186a06000604051806020016040528060008152506107ab565b005b600080fd5b34801561020957600080fd5b506101f6610218366004614feb565b610850565b34801561022957600080fd5b5060375461024a9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561028057600080fd5b5060355461024a90610100900473ffffffffffffffffffffffffffffffffffffffff1681565b3480156102b257600080fd5b50603b546102c39063ffffffff1681565b60405163ffffffff909116815260200161026b565b3480156102e457600080fd5b506101f66102f3366004615121565b610a91565b34801561030457600080fd5b5061024a610f31565b34801561031957600080fd5b5061033d610328366004615173565b603a6020526000908152604090205460ff1681565b604051901515815260200161026b565b34801561035957600080fd5b506101f6610368366004615190565b610fc9565b34801561037957600080fd5b50603b5461039690640100000000900467ffffffffffffffff1681565b60405167ffffffffffffffff909116815260200161026b565b3480156103bb57600080fd5b506103dc6103ca36600461526c565b6000908152603c602052604090205490565b60405190815260200161026b565b3480156103f657600080fd5b50604080518082018252600d81527f332e31312e302d626574612e33000000000000000000000000000000000000006020820152905161026b91906152fb565b34801561044257600080fd5b5061033d611531565b34801561045757600080fd5b506101f661046636600461530e565b6115c4565b34801561047757600080fd5b506101f6610486366004615342565b611c7f565b34801561049757600080fd5b506101f66104a6366004615173565b611e3f565b3480156104b757600080fd5b506101f66104c636600461539a565b611f22565b3480156104d757600080fd5b506101f66104e63660046153b7565b61200e565b3480156104f757600080fd5b506101f66105063660046153f4565b61205a565b34801561051757600080fd5b507f00000000000000000000000000000000000000000000000000000000000000066103dc565b34801561054a57600080fd5b5060325461024a9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561057757600080fd5b5061033d61058636600461526c565b60336020526000908152604090205460ff1681565b3480156105a757600080fd5b506103966105b6366004615450565b61230f565b3480156105c757600080fd5b5061024a6105d636600461546d565b61232e565b3480156105e757600080fd5b506103dc612373565b3480156105fc57600080fd5b5061066261060b36600461530e565b603960209081526000928352604080842090915290825290205473ffffffffffffffffffffffffffffffffffffffff81169074010000000000000000000000000000000000000000900467ffffffffffffffff1682565b6040805173ffffffffffffffffffffffffffffffffffffffff909316835267ffffffffffffffff90911660208301520161026b565b3480156106a357600080fd5b507f000000000000000000000000000000000000000000000000000000000000000c6103dc565b3480156106d657600080fd5b50600154610732906fffffffffffffffffffffffffffffffff81169067ffffffffffffffff7001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041683565b604080516fffffffffffffffffffffffffffffffff909416845267ffffffffffffffff928316602085015291169082015260600161026b565b6101f661077936600461548f565b6107ab565b34801561078a57600080fd5b5060385461024a9073ffffffffffffffffffffffffffffffffffffffff1681565b8260005a905060006107bb6123e9565b50905073ffffffffffffffffffffffffffffffffffffffff811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee148015906107f757503415155b1561082e576040517ff2365b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61083c883489898989612486565b506108478282612632565b50505050505050565b8260005a905060006108606123e9565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8216016108d2576040517f0eaf3c0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87603d60008282546108e4919061553d565b90915550506040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015610956573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097a9190615555565b905061099e73ffffffffffffffffffffffffffffffffffffffff831633308c6128ff565b6109a8898261553d565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa158015610a12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a369190615555565b14610a6d576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a7b8a8a8a8a8a8a612486565b5050610a878282612632565b5050505050505050565b610a99611531565b15610ad0576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60325473ffffffffffffffffffffffffffffffffffffffff1661dead14610b23576040517f9396d15600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610b2e836129e1565b9050610b3a81836115c4565b6000818152603360209081526040822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558401516032805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff000000000000000000000000000000000000000090921691909117905580610bc56123e9565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff821601610c2857610c218560400151866080015187606001518860a00151612a2e565b9150610e7b565b8073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff1603610c91576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606085015115610e52578460600151603d6000828254610cb1919061556e565b90915550506040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015610d23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d479190615555565b9050610d7c866040015187606001518473ffffffffffffffffffffffffffffffffffffffff16612a8c9092919063ffffffff16565b6060860151610d8b908261556e565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa158015610df5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e199190615555565b14610e50576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b60a08501515115610e7657610c218560400151866080015160008860a00151612a2e565b600191505b603280547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead17905560405183907fdb5c7652857aa163daadd670e116628fb42e869d8ac4251ef8971d9e5727df1b90610edd90851515815260200190565b60405180910390a281158015610ef35750326001145b15610f2a576040517feeae4ed300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa158015610fa0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc49190615585565b905090565b610fd1611531565b15611008576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff16856040015173ffffffffffffffffffffffffffffffffffffffff1603611071576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6038546040517fbb8aa1fc00000000000000000000000000000000000000000000000000000000815260048101869052600091829173ffffffffffffffffffffffffffffffffffffffff9091169063bb8aa1fc90602401606060405180830381865afa1580156110e5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061110991906155a2565b925050915060008173ffffffffffffffffffffffffffffffffffffffff1663bcef3b556040518163ffffffff1660e01b8152600401602060405180830381865afa15801561115b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061117f9190615555565b603b5490915063ffffffff8481169116146111c6576040517f27a10cc200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111dd6111d8368890038801886155ef565b612ae7565b8114611215576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611220896129e1565b905060018373ffffffffffffffffffffffffffffffffffffffff1663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa15801561126f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112939190615684565b60028111156112a4576112a4615655565b036112db576040517fd357347400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051602081018390526000918101829052606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012090830181905292506113a49101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828201909152600182527f010000000000000000000000000000000000000000000000000000000000000060208301529061139a898b6156a5565b8b60400135612b26565b15156000036113df576040517fb05e92fa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051808201825273ffffffffffffffffffffffffffffffffffffffff808716825267ffffffffffffffff4281166020808501918252600088815260398252868120338252825286812095518654935190941674010000000000000000000000000000000000000000027fffffffff0000000000000000000000000000000000000000000000000000000090931693851693909317919091179093558d840151928e01519351928216939091169185917f67a6208cfcc0801d50f6cbe764733f4fddf66ac0b04442061a8a8c0cb6b63f6291a4604051339083907f798f9f13695f8f045aa5f80ed8efebb695f3c7fe65da381969f2f28bf3c60b9790600090a3506000908152603c602090815260408220805460018101825590835291200180547fffffffffffffffffffffffff000000000000000000000000000000000000000016331790555050505050505050565b6000603560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115a0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc49190615729565b600082815260396020908152604080832073ffffffffffffffffffffffffffffffffffffffff85811685529083528184208251808401845290549182168082527401000000000000000000000000000000000000000090920467ffffffffffffffff1681850152818552603a90935292205490919060ff1615611673576040517f09550c7700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b816020015167ffffffffffffffff166000036116bb576040517f94efd49b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061173c8273ffffffffffffffffffffffffffffffffffffffff1663cf09e0d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561170b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061172f9190615746565b67ffffffffffffffff1690565b90508067ffffffffffffffff16836020015167ffffffffffffffff1611611810576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604e60248201527f4f7074696d69736d506f7274616c3a207769746864726177616c2074696d657360448201527f74616d70206c657373207468616e20646973707574652067616d65206372656160648201527f74696f6e2074696d657374616d70000000000000000000000000000000000000608482015260a4015b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000c836020015167ffffffffffffffff164261184b919061556e565b116118d8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4f7074696d69736d506f7274616c3a2070726f76656e2077697468647261776160448201527f6c20686173206e6f74206d6174757265642079657400000000000000000000006064820152608401611807565b60028273ffffffffffffffffffffffffffffffffffffffff1663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611925573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119499190615684565b600281111561195a5761195a615655565b14611991576040517fa080a3c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603b5463ffffffff1663ffffffff16611a1b8373ffffffffffffffffffffffffffffffffffffffff1663bbdc02db6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119ee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a129190615763565b63ffffffff1690565b63ffffffff1614611a58576040517f27a10cc200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603b5467ffffffffffffffff64010000000090910481169082161015611b26576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604b60248201527f4f7074696d69736d506f7274616c3a20646973707574652067616d652063726560448201527f61746564206265666f7265207265737065637465642067616d6520747970652060648201527f7761732075706461746564000000000000000000000000000000000000000000608482015260a401611807565b7f0000000000000000000000000000000000000000000000000000000000000006611b958373ffffffffffffffffffffffffffffffffffffffff166319effeb46040518163ffffffff1660e01b8152600401602060405180830381865afa15801561170b573d6000803e3d6000fd5b611ba99067ffffffffffffffff164261556e565b11611c36576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4f7074696d69736d506f7274616c3a206f75747075742070726f706f73616c2060448201527f696e206169722d676170000000000000000000000000000000000000000000006064820152608401611807565b60008581526033602052604090205460ff1615610f2a576040517f475a253500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60375473ffffffffffffffffffffffffffffffffffffffff163314611cd0576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611cdc62030d40612b4a565b60405173ffffffffffffffffffffffffffffffffffffffff8516602482015260ff8416604482015260648101839052608481018290526000907342000000000000000000000000000000000000159073deaddeaddeaddeaddeaddeaddeaddeaddead0001907fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c32908490819062030d4090829060a401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f71cfaa3f000000000000000000000000000000000000000000000000000000001790529051611df996959493929101615780565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815290829052611e31916152fb565b60405180910390a450505050565b611e47610f31565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611eab576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81166000818152603a602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055517f192c289026d59a41a27f5aea08f3969b57931b0589202d14f4368cded95d3cda9190a250565b611f2a610f31565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611f8e576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603b805463ffffffff83167fffffffffffffffffffffffffffffffffffffffff00000000000000000000000090911681176401000000004267ffffffffffffffff90811682029290921793849055604051930416917f049fe9dd413cdf037cce27011cc1790c753118272f3630e6e8bdfa5e8208176090600090a350565b565b612016611531565b1561204d576040517ff480973e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6120578133610a91565b50565b600054610100900460ff161580801561207a5750600054600160ff909116105b806120945750303b158015612094575060005460ff166001145b612120576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401611807565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561217e57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603880547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff8881169190911790925560378054909116868316179055603580547fffffffffffffffffffffff0000000000000000000000000000000000000000ff16610100868416021790556032541661229e576032805461dead7fffffffffffffffffffffffff0000000000000000000000000000000000000000909116179055603b80547fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166401000000004267ffffffffffffffff16027fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000161763ffffffff84161790555b6122a6612bac565b8015610f2a57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050505050565b600061231c8260106157e5565b61232890615208615815565b92915050565b603c602052816000526040600020818154811061234a57600080fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff169150829050565b60008061237e6123e9565b5090507fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8216016123c5574791505090565b5050603d5490565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b603754604080517f4397dfef0000000000000000000000000000000000000000000000000000000081528151600093849373ffffffffffffffffffffffffffffffffffffffff90911692634397dfef92600480830193928290030181865afa158015612459573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061247d9190615841565b90939092509050565b8180156124a8575073ffffffffffffffffffffffffffffffffffffffff861615155b156124df576040517f13496fda00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6124e9815161230f565b67ffffffffffffffff168367ffffffffffffffff161015612536576040517f4929b80800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6201d4c081511115612574576040517f73052b0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b33328114612595575033731111000000000000000000000000000000001111015b600086868686866040516020016125b0959493929190615780565b604051602081830303815290604052905060008873ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fb3813568d9991fc951961fcb4c784893574240a28925604d09fc577c55bb7c328460405161262091906152fb565b60405180910390a45050505050505050565b600154600090612668907801000000000000000000000000000000000000000000000000900467ffffffffffffffff164361556e565b90506000612674612cbf565b90506000816020015160ff16826000015163ffffffff16612695919061589f565b905082156127cc576001546000906126cc908390700100000000000000000000000000000000900467ffffffffffffffff16615907565b90506000836040015160ff16836126e3919061597b565b6001546127039084906fffffffffffffffffffffffffffffffff1661597b565b61270d919061589f565b60015490915060009061275e906127379084906fffffffffffffffffffffffffffffffff16615a37565b866060015163ffffffff168760a001516fffffffffffffffffffffffffffffffff16612d85565b9050600186111561278d5761278a61273782876040015160ff1660018a612785919061556e565b612da4565b90505b6fffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff4316021760015550505b600180548691906010906127ff908490700100000000000000000000000000000000900467ffffffffffffffff16615815565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550816000015163ffffffff16600160000160109054906101000a900467ffffffffffffffff1667ffffffffffffffff16131561288c576040517f77ebef4d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001546000906128b8906fffffffffffffffffffffffffffffffff1667ffffffffffffffff8816615aab565b905060006128ca48633b9aca00612df9565b6128d49083615ae8565b905060005a6128e3908861556e565b905080821115610a8757610a876128fa828461556e565b612e10565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526129db9085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152612e39565b50505050565b80516020808301516040808501516060860151608087015160a08801519351600097612a11979096959101615afc565b604051602081830303815290604052805190602001209050919050565b6000806000612a3e866000612f45565b905080612a74576308c379a06000526020805278185361666543616c6c3a204e6f7420656e6f756768206761736058526064601cfd5b600080855160208701888b5af1979650505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052612ae29084907fa9059cbb0000000000000000000000000000000000000000000000000000000090606401612959565b505050565b60008160000151826020015183604001518460600151604051602001612a11949392919093845260208401929092526040830152606082015260800190565b600080612b3286612f63565b9050612b4081868686612f95565b9695505050505050565b6001805463ffffffff83169190601090612b83908490700100000000000000000000000000000000900467ffffffffffffffff16615815565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555050565b600054610100900460ff16612c43576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401611807565b6001547801000000000000000000000000000000000000000000000000900467ffffffffffffffff1660000361200c5760408051606081018252633b9aca00808252600060208301524367ffffffffffffffff169190920181905278010000000000000000000000000000000000000000000000000217600155565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152603754604080517fcc731b02000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163cc731b029160048083019260c09291908290030181865afa158015612d61573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123289190615b53565b6000612d9a612d948585612fc5565b83612fd5565b90505b9392505050565b6000670de0b6b3a7640000612de5612dbc858361589f565b612dce90670de0b6b3a7640000615907565b612de085670de0b6b3a764000061597b565b612fe4565b612def908661597b565b612d9a919061589f565b600081831015612e095781612d9d565b5090919050565b6000805a90505b825a612e23908361556e565b1015612ae257612e3282615bf5565b9150612e17565b6000612e9b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166130159092919063ffffffff16565b805190915015612ae25780806020019051810190612eb99190615729565b612ae2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401611807565b600080603f83619c4001026040850201603f5a021015949350505050565b60608180519060200120604051602001612f7f91815260200190565b6040516020818303038152906040529050919050565b6000612fbc84612fa6878686613024565b8051602091820120825192909101919091201490565b95945050505050565b600081831215612e095781612d9d565b6000818312612e095781612d9d565b6000612d9d670de0b6b3a764000083612ffc86613aa2565b613006919061597b565b613010919061589f565b613ce6565b6060612d9a8484600085613f25565b60606000845111613091576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4d65726b6c65547269653a20656d707479206b657900000000000000000000006044820152606401611807565b600061309c846140bb565b905060006130a9866141a7565b90506000846040516020016130c091815260200190565b60405160208183030381529060405290506000805b8451811015613a195760008582815181106130f2576130f2615c2d565b60200260200101519050845183111561318d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4d65726b6c65547269653a206b657920696e646578206578636565647320746f60448201527f74616c206b6579206c656e6774680000000000000000000000000000000000006064820152608401611807565b8260000361324657805180516020918201206040516131db926131b592910190815260200190565b604051602081830303815290604052858051602091820120825192909101919091201490565b613241576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4d65726b6c65547269653a20696e76616c696420726f6f7420686173680000006044820152606401611807565b61339d565b8051516020116132fc5780518051602091820120604051613270926131b592910190815260200190565b613241576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d65726b6c65547269653a20696e76616c6964206c6172676520696e7465726e60448201527f616c2068617368000000000000000000000000000000000000000000000000006064820152608401611807565b80518451602080870191909120825191909201201461339d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4d65726b6c65547269653a20696e76616c696420696e7465726e616c206e6f6460448201527f65206861736800000000000000000000000000000000000000000000000000006064820152608401611807565b6133a96010600161553d565b81602001515103613585578451830361351d576133e381602001516010815181106133d6576133d6615c2d565b602002602001015161420a565b96506000875111613476576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603b60248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286272616e63682900000000006064820152608401611807565b60018651613484919061556e565b8214613512576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286272616e6368290000000000006064820152608401611807565b505050505050612d9d565b600085848151811061353157613531615c2d565b602001015160f81c60f81b60f81c9050600082602001518260ff168151811061355c5761355c615c2d565b6020026020010151905061356f816142be565b955061357c60018661553d565b94505050613a06565b60028160200151510361397e57600061359d826142e3565b90506000816000815181106135b4576135b4615c2d565b016020015160f81c905060006135cb600283615c5c565b6135d6906002615c7e565b905060006135e7848360ff16614307565b905060006135f58a89614307565b90506000613603838361433d565b905080835114613695576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4d65726b6c65547269653a20706174682072656d61696e646572206d7573742060448201527f736861726520616c6c206e6962626c65732077697468206b65790000000000006064820152608401611807565b60ff8516600214806136aa575060ff85166003145b15613899578082511461373f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f4d65726b6c65547269653a206b65792072656d61696e646572206d757374206260448201527f65206964656e746963616c20746f20706174682072656d61696e6465720000006064820152608401611807565b61375987602001516001815181106133d6576133d6615c2d565b9c5060008d51116137ec576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f4d65726b6c65547269653a2076616c7565206c656e677468206d75737420626560448201527f2067726561746572207468616e207a65726f20286c65616629000000000000006064820152608401611807565b60018c516137fa919061556e565b8814613888576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f4d65726b6c65547269653a2076616c7565206e6f6465206d757374206265206c60448201527f617374206e6f646520696e2070726f6f6620286c6561662900000000000000006064820152608401611807565b505050505050505050505050612d9d565b60ff851615806138ac575060ff85166001145b156138eb576138d887602001516001815181106138cb576138cb615c2d565b60200260200101516142be565b99506138e4818a61553d565b9850613973565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603260248201527f4d65726b6c65547269653a2072656365697665642061206e6f6465207769746860448201527f20616e20756e6b6e6f776e2070726566697800000000000000000000000000006064820152608401611807565b505050505050613a06565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f4d65726b6c65547269653a20726563656976656420616e20756e70617273656160448201527f626c65206e6f64650000000000000000000000000000000000000000000000006064820152608401611807565b5080613a1181615bf5565b9150506130d5565b506040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f4d65726b6c65547269653a2072616e206f7574206f662070726f6f6620656c6560448201527f6d656e74730000000000000000000000000000000000000000000000000000006064820152608401611807565b6000808213613b0d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401611807565b60006060613b1a846143f1565b03609f8181039490941b90931c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506027d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b393909302929092017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d92915050565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c18213613d1757506000919050565b680755bf798b4a1bf1e58212613d89576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4558505f4f564552464c4f5700000000000000000000000000000000000000006044820152606401611807565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b606082471015613fb7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401611807565b73ffffffffffffffffffffffffffffffffffffffff85163b614035576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401611807565b6000808673ffffffffffffffffffffffffffffffffffffffff16858760405161405e9190615ca1565b60006040518083038185875af1925050503d806000811461409b576040519150601f19603f3d011682016040523d82523d6000602084013e6140a0565b606091505b50915091506140b08282866144c7565b979650505050505050565b80516060908067ffffffffffffffff8111156140d9576140d9614eb6565b60405190808252806020026020018201604052801561411e57816020015b60408051808201909152606080825260208201528152602001906001900390816140f75790505b50915060005b818110156141a057604051806040016040528085838151811061414957614149615c2d565b6020026020010151815260200161417886848151811061416b5761416b615c2d565b602002602001015161451a565b81525083828151811061418d5761418d615c2d565b6020908102919091010152600101614124565b5050919050565b606080604051905082518060011b603f8101601f1916830160405280835250602084016020830160005b838110156141ff578060011b82018184015160001a8060041c8253600f8116600183015350506001016141d1565b509295945050505050565b6060600080600061421a8561452d565b91945092509050600081600181111561423557614235615655565b1461426c576040517f1ff9b2e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614276828461553d565b8551146142af576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612fbc856020015184846149cb565b606060208260000151106142da576142d58261420a565b612328565b61232882614a5f565b606061232861430283602001516000815181106133d6576133d6615c2d565b6141a7565b6060825182106143265750604080516020810190915260008152612328565b612d9d8383848651614338919061556e565b614a75565b6000808251845110614350578251614353565b83515b90505b80821080156143da575082828151811061437257614372615c2d565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168483815181106143b1576143b1615c2d565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b156143ea57816001019150614356565b5092915050565b600080821161445c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f554e444546494e454400000000000000000000000000000000000000000000006044820152606401611807565b5060016fffffffffffffffffffffffffffffffff821160071b82811c67ffffffffffffffff1060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110821b1791821c111790565b606083156144d6575081612d9d565b8251156144e65782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161180791906152fb565b606061232861452883614c4d565b614cba565b60008060008360000151600003614570576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020840151805160001a607f81116145955760006001600094509450945050506149c4565b60b781116146ab5760006145aa60808361556e565b9050808760000151116145e9576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001838101517fff0000000000000000000000000000000000000000000000000000000000000016908214801561466157507f80000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000008216105b15614698576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50600195509350600092506149c4915050565b60bf81116148095760006146c060b78361556e565b9050808760000151116146ff576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614761576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c603781116147a9576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6147b3818461553d565b8951116147ec576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6147f783600161553d565b97509550600094506149c49350505050565b60f7811161486e57600061481e60c08361556e565b90508087600001511161485d576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001955093508492506149c4915050565b600061487b60f78361556e565b9050808760000151116148ba576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff0000000000000000000000000000000000000000000000000000000000000016600081900361491c576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c60378111614964576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61496e818461553d565b8951116149a7576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6149b283600161553d565b97509550600194506149c49350505050565b9193909250565b60608167ffffffffffffffff8111156149e6576149e6614eb6565b6040519080825280601f01601f191660200182016040528015614a10576020820181803683370190505b5090508115612d9d576000614a25848661553d565b90506020820160005b84811015614a46578281015182820152602001614a2e565b84811115614a55576000858301525b5050509392505050565b60606123288260200151600084600001516149cb565b60608182601f011015614ae4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401611807565b828284011015614b50576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401611807565b81830184511015614bbd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401611807565b606082158015614bdc5760405191506000825260208201604052614c44565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015614c15578051835260209283019201614bfd565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b60408051808201909152600080825260208201528151600003614c9c576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50604080518082019091528151815260209182019181019190915290565b60606000806000614cca8561452d565b919450925090506001816001811115614ce557614ce5615655565b14614d1c576040517f4b9c6abe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8451614d28838561553d565b14614d5f576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516020808252610420820190925290816020015b6040805180820190915260008082526020820152815260200190600190039081614d765790505093506000835b8651811015614e6457600080614de96040518060400160405280858c60000151614dcd919061556e565b8152602001858c60200151614de2919061553d565b905261452d565b509150915060405180604001604052808383614e05919061553d565b8152602001848b60200151614e1a919061553d565b815250888581518110614e2f57614e2f615c2d565b6020908102919091010152614e4560018561553d565b9350614e51818361553d565b614e5b908461553d565b92505050614da3565b50845250919392505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461205757600080fd5b67ffffffffffffffff8116811461205757600080fd5b801515811461205757600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160c0810167ffffffffffffffff81118282101715614f0857614f08614eb6565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614f5557614f55614eb6565b604052919050565b600082601f830112614f6e57600080fd5b813567ffffffffffffffff811115614f8857614f88614eb6565b614fb960207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601614f0e565b818152846020838601011115614fce57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060008060c0878903121561500457600080fd5b863561500f81614e70565b95506020870135945060408701359350606087013561502d81614e92565b9250608087013561503d81614ea8565b915060a087013567ffffffffffffffff81111561505957600080fd5b61506589828a01614f5d565b9150509295509295509295565b600060c0828403121561508457600080fd5b60405160c0810167ffffffffffffffff82821081831117156150a8576150a8614eb6565b8160405282935084358352602085013591506150c382614e70565b816020840152604085013591506150d982614e70565b816040840152606085013560608401526080850135608084015260a085013591508082111561510757600080fd5b5061511485828601614f5d565b60a0830152505092915050565b6000806040838503121561513457600080fd5b823567ffffffffffffffff81111561514b57600080fd5b61515785828601615072565b925050602083013561516881614e70565b809150509250929050565b60006020828403121561518557600080fd5b8135612d9d81614e70565b600080600080600085870360e08112156151a957600080fd5b863567ffffffffffffffff808211156151c157600080fd5b6151cd8a838b01615072565b97506020890135965060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08401121561520657600080fd5b60408901955060c089013592508083111561522057600080fd5b828901925089601f84011261523457600080fd5b823591508082111561524557600080fd5b508860208260051b840101111561525b57600080fd5b959894975092955050506020019190565b60006020828403121561527e57600080fd5b5035919050565b60005b838110156152a0578181015183820152602001615288565b838111156129db5750506000910152565b600081518084526152c9816020860160208601615285565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000612d9d60208301846152b1565b6000806040838503121561532157600080fd5b82359150602083013561516881614e70565b60ff8116811461205757600080fd5b6000806000806080858703121561535857600080fd5b843561536381614e70565b9350602085013561537381615333565b93969395505050506040820135916060013590565b63ffffffff8116811461205757600080fd5b6000602082840312156153ac57600080fd5b8135612d9d81615388565b6000602082840312156153c957600080fd5b813567ffffffffffffffff8111156153e057600080fd5b6153ec84828501615072565b949350505050565b6000806000806080858703121561540a57600080fd5b843561541581614e70565b9350602085013561542581614e70565b9250604085013561543581614e70565b9150606085013561544581615388565b939692955090935050565b60006020828403121561546257600080fd5b8135612d9d81614e92565b6000806040838503121561548057600080fd5b50508035926020909101359150565b600080600080600060a086880312156154a757600080fd5b85356154b281614e70565b94506020860135935060408601356154c981614e92565b925060608601356154d981614ea8565b9150608086013567ffffffffffffffff8111156154f557600080fd5b61550188828901614f5d565b9150509295509295909350565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156155505761555061550e565b500190565b60006020828403121561556757600080fd5b5051919050565b6000828210156155805761558061550e565b500390565b60006020828403121561559757600080fd5b8151612d9d81614e70565b6000806000606084860312156155b757600080fd5b83516155c281615388565b60208501519093506155d381614e92565b60408501519092506155e481614e70565b809150509250925092565b60006080828403121561560157600080fd5b6040516080810181811067ffffffffffffffff8211171561562457615624614eb6565b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60006020828403121561569657600080fd5b815160038110612d9d57600080fd5b600067ffffffffffffffff808411156156c0576156c0614eb6565b8360051b60206156d1818301614f0e565b8681529185019181810190368411156156e957600080fd5b865b8481101561571d578035868111156157035760008081fd5b61570f36828b01614f5d565b8452509183019183016156eb565b50979650505050505050565b60006020828403121561573b57600080fd5b8151612d9d81614ea8565b60006020828403121561575857600080fd5b8151612d9d81614e92565b60006020828403121561577557600080fd5b8151612d9d81615388565b8581528460208201527fffffffffffffffff0000000000000000000000000000000000000000000000008460c01b16604082015282151560f81b6048820152600082516157d4816049850160208701615285565b919091016049019695505050505050565b600067ffffffffffffffff8083168185168183048111821515161561580c5761580c61550e565b02949350505050565b600067ffffffffffffffff8083168185168083038211156158385761583861550e565b01949350505050565b6000806040838503121561585457600080fd5b825161585f81614e70565b602084015190925061516881615333565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826158ae576158ae615870565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f8000000000000000000000000000000000000000000000000000000000000000831416156159025761590261550e565b500590565b6000808312837f8000000000000000000000000000000000000000000000000000000000000000018312811516156159415761594161550e565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0183138116156159755761597561550e565b50500390565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6000841360008413858304851182821616156159bc576159bc61550e565b7f800000000000000000000000000000000000000000000000000000000000000060008712868205881281841616156159f7576159f761550e565b60008712925087820587128484161615615a1357615a1361550e565b87850587128184161615615a2957615a2961550e565b505050929093029392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03841381151615615a7157615a7161550e565b827f8000000000000000000000000000000000000000000000000000000000000000038412811615615aa557615aa561550e565b50500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615ae357615ae361550e565b500290565b600082615af757615af7615870565b500490565b868152600073ffffffffffffffffffffffffffffffffffffffff808816602084015280871660408401525084606083015283608083015260c060a0830152615b4760c08301846152b1565b98975050505050505050565b600060c08284031215615b6557600080fd5b615b6d614ee5565b8251615b7881615388565b81526020830151615b8881615333565b60208201526040830151615b9b81615333565b60408201526060830151615bae81615388565b60608201526080830151615bc181615388565b608082015260a08301516fffffffffffffffffffffffffffffffff81168114615be957600080fd5b60a08201529392505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203615c2657615c2661550e565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060ff831680615c6f57615c6f615870565b8060ff84160691505092915050565b600060ff821660ff841680821015615c9857615c9861550e565b90039392505050565b60008251615cb3818460208701615285565b919091019291505056fea164736f6c634300080f000a"; + bytes internal constant disputeGameFactoryCode = +- hex"6080604052600436106100e85760003560e01c80636593dc6e1161008a57806396cd97201161005957806396cd972014610313578063bb8aa1fc14610333578063c4d66de814610394578063f2fde38b146103b457600080fd5b80636593dc6e14610293578063715018a6146102c057806382ecf2f6146102d55780638da5cb5b146102e857600080fd5b8063254bd683116100c6578063254bd6831461019c5780634d1975b4146101c957806354fd4d50146101e85780635f0150cb1461023e57600080fd5b806314f6b1a3146100ed5780631b685b9e1461010f5780631e3342401461017c575b600080fd5b3480156100f957600080fd5b5061010d6101083660046110c6565b6103d4565b005b34801561011b57600080fd5b5061015261012a3660046110fd565b60656020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561018857600080fd5b5061010d610197366004611118565b61045e565b3480156101a857600080fd5b506101bc6101b7366004611142565b6104aa565b60405161017391906111ef565b3480156101d557600080fd5b506068545b604051908152602001610173565b3480156101f457600080fd5b506102316040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b60405161017391906112ac565b34801561024a57600080fd5b5061025e6102593660046112bf565b6106ee565b6040805173ffffffffffffffffffffffffffffffffffffffff909316835267ffffffffffffffff909116602083015201610173565b34801561029f57600080fd5b506101da6102ae3660046110fd565b60666020526000908152604090205481565b3480156102cc57600080fd5b5061010d610741565b6101526102e33660046112bf565b610755565b3480156102f457600080fd5b5060335473ffffffffffffffffffffffffffffffffffffffff16610152565b34801561031f57600080fd5b506101da61032e3660046112bf565b6109ef565b34801561033f57600080fd5b5061035361034e366004611346565b610a28565b6040805163ffffffff909416845267ffffffffffffffff909216602084015273ffffffffffffffffffffffffffffffffffffffff1690820152606001610173565b3480156103a057600080fd5b5061010d6103af36600461135f565b610a91565b3480156103c057600080fd5b5061010d6103cf36600461135f565b610c2d565b6103dc610d00565b63ffffffff821660008181526065602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8616908117909155905190917fff513d80e2c7fa487608f70a618dfbc0cf415699dc69588c747e8c71566c88de91a35050565b610466610d00565b63ffffffff8216600081815260666020526040808220849055518392917f74d6665c4b26d5596a5aa13d3014e0c06af4d322075a797f87b03cd4c5bc91ca91a35050565b606854606090831015806104bc575081155b6106e7575060408051600583901b8101602001909152825b8381116106e5576000606882815481106104f0576104f061137c565b600091825260209091200154905060e081901c60a082901c67ffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff831663ffffffff891683036106b6576001865101865260008173ffffffffffffffffffffffffffffffffffffffff1663609d33346040518163ffffffff1660e01b8152600401600060405180830381865afa15801561058a573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526105d091908101906113da565b905060008273ffffffffffffffffffffffffffffffffffffffff1663bcef3b556040518163ffffffff1660e01b8152600401602060405180830381865afa15801561061f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064391906114a5565b90506040518060a001604052808881526020018781526020018567ffffffffffffffff168152602001828152602001838152508860018a5161068591906114be565b815181106106955761069561137c565b6020026020010181905250888851106106b3575050505050506106e5565b50505b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90920191506104d49050565b505b9392505050565b60008060006106ff878787876109ef565b60009081526067602052604090205473ffffffffffffffffffffffffffffffffffffffff81169860a09190911c67ffffffffffffffff16975095505050505050565b610749610d00565b6107536000610d81565b565b63ffffffff841660009081526065602052604081205473ffffffffffffffffffffffffffffffffffffffff16806107c5576040517f031c6de400000000000000000000000000000000000000000000000000000000815263ffffffff871660048201526024015b60405180910390fd5b63ffffffff86166000908152606660205260409020543414610813576040517f8620aa1900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006108206001436114be565b40905061088a338783888860405160200161083f9594939291906114fc565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905273ffffffffffffffffffffffffffffffffffffffff841690610df8565b92508273ffffffffffffffffffffffffffffffffffffffff16638129fc1c346040518263ffffffff1660e01b81526004016000604051808303818588803b1580156108d457600080fd5b505af11580156108e8573d6000803e3d6000fd5b505050505060006108fb888888886109ef565b60008181526067602052604090205490915015610947576040517f014f6fe5000000000000000000000000000000000000000000000000000000008152600481018290526024016107bc565b60004260a01b60e08a901b178517600083815260676020526040808220839055606880546001810182559083527fa2153420d844928b4421650203c77babc8b33d7f2e7b450e2966db0c220977530183905551919250899163ffffffff8c169173ffffffffffffffffffffffffffffffffffffffff8916917f5b565efe82411da98814f356d0e7bcb8f0219b8d970307c5afb4a6903a8b2e359190a450505050949350505050565b600084848484604051602001610a089493929190611549565b604051602081830303815290604052805190602001209050949350505050565b600080600080600080610a8160688881548110610a4757610a4761137c565b906000526020600020015460e081901c9160a082901c67ffffffffffffffff169173ffffffffffffffffffffffffffffffffffffffff1690565b9199909850909650945050505050565b600054610100900460ff1615808015610ab15750600054600160ff909116105b80610acb5750303b158015610acb575060005460ff166001145b610b57576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016107bc565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610bb557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610bbd610e06565b610bc682610d81565b8015610c2957600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b610c35610d00565b73ffffffffffffffffffffffffffffffffffffffff8116610cd8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016107bc565b610ce181610d81565b50565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b60335473ffffffffffffffffffffffffffffffffffffffff163314610753576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016107bc565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60006106e760008484610ea5565b600054610100900460ff16610e9d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016107bc565b610753610feb565b600060608203516040830351602084035184518060208701018051600283016c5af43d3d93803e606057fd5bf3895289600d8a035278593da1005b363d3d373d3d3d3d610000806062363936013d738160481b1760218a03527f9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff603a8a035272fd6100003d81600a3d39f336602c57343d527f6062820160781b1761ff9e82106059018a03528060f01b8352606c8101604c8a038cf097505086610f715763301164256000526004601cfd5b905285527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08501527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08401527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa09092019190915292915050565b600054610100900460ff16611082576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016107bc565b61075333610d81565b803563ffffffff8116811461109f57600080fd5b919050565b73ffffffffffffffffffffffffffffffffffffffff81168114610ce157600080fd5b600080604083850312156110d957600080fd5b6110e28361108b565b915060208301356110f2816110a4565b809150509250929050565b60006020828403121561110f57600080fd5b6106e78261108b565b6000806040838503121561112b57600080fd5b6111348361108b565b946020939093013593505050565b60008060006060848603121561115757600080fd5b6111608461108b565b95602085013595506040909401359392505050565b60005b83811015611190578181015183820152602001611178565b8381111561119f576000848401525b50505050565b600081518084526111bd816020860160208601611175565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b8381101561129e578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc001855281518051845287810151888501528681015167ffffffffffffffff16878501526060808201519085015260809081015160a09185018290529061128a818601836111a5565b968901969450505090860190600101611216565b509098975050505050505050565b6020815260006106e760208301846111a5565b600080600080606085870312156112d557600080fd5b6112de8561108b565b935060208501359250604085013567ffffffffffffffff8082111561130257600080fd5b818701915087601f83011261131657600080fd5b81358181111561132557600080fd5b88602082850101111561133757600080fd5b95989497505060200194505050565b60006020828403121561135857600080fd5b5035919050565b60006020828403121561137157600080fd5b81356106e7816110a4565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156113ec57600080fd5b815167ffffffffffffffff8082111561140457600080fd5b818401915084601f83011261141857600080fd5b81518181111561142a5761142a6113ab565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611470576114706113ab565b8160405282815287602084870101111561148957600080fd5b61149a836020830160208801611175565b979650505050505050565b6000602082840312156114b757600080fd5b5051919050565b6000828210156114f7577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b500390565b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008660601b1681528460148201528360348201528183605483013760009101605401908152949350505050565b63ffffffff8516815283602082015260606040820152816060820152818360808301376000818301608090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101939250505056fea164736f6c634300080f000a"; ++ hex"6080604052600436106100e85760003560e01c80636593dc6e1161008a57806396cd97201161005957806396cd972014610313578063bb8aa1fc14610333578063c4d66de814610394578063f2fde38b146103b457600080fd5b80636593dc6e14610293578063715018a6146102c057806382ecf2f6146102d55780638da5cb5b146102e857600080fd5b8063254bd683116100c6578063254bd6831461019c5780634d1975b4146101c957806354fd4d50146101e85780635f0150cb1461023e57600080fd5b806314f6b1a3146100ed5780631b685b9e1461010f5780631e3342401461017c575b600080fd5b3480156100f957600080fd5b5061010d6101083660046110c6565b6103d4565b005b34801561011b57600080fd5b5061015261012a3660046110fd565b60656020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561018857600080fd5b5061010d610197366004611118565b61045e565b3480156101a857600080fd5b506101bc6101b7366004611142565b6104aa565b60405161017391906111ef565b3480156101d557600080fd5b506068545b604051908152602001610173565b3480156101f457600080fd5b506102316040518060400160405280600c81526020017f312e302e312d626574612e31000000000000000000000000000000000000000081525081565b60405161017391906112ac565b34801561024a57600080fd5b5061025e6102593660046112bf565b6106ee565b6040805173ffffffffffffffffffffffffffffffffffffffff909316835267ffffffffffffffff909116602083015201610173565b34801561029f57600080fd5b506101da6102ae3660046110fd565b60666020526000908152604090205481565b3480156102cc57600080fd5b5061010d610741565b6101526102e33660046112bf565b610755565b3480156102f457600080fd5b5060335473ffffffffffffffffffffffffffffffffffffffff16610152565b34801561031f57600080fd5b506101da61032e3660046112bf565b6109ef565b34801561033f57600080fd5b5061035361034e366004611346565b610a28565b6040805163ffffffff909416845267ffffffffffffffff909216602084015273ffffffffffffffffffffffffffffffffffffffff1690820152606001610173565b3480156103a057600080fd5b5061010d6103af36600461135f565b610a91565b3480156103c057600080fd5b5061010d6103cf36600461135f565b610c2d565b6103dc610d00565b63ffffffff821660008181526065602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8616908117909155905190917fff513d80e2c7fa487608f70a618dfbc0cf415699dc69588c747e8c71566c88de91a35050565b610466610d00565b63ffffffff8216600081815260666020526040808220849055518392917f74d6665c4b26d5596a5aa13d3014e0c06af4d322075a797f87b03cd4c5bc91ca91a35050565b606854606090831015806104bc575081155b6106e7575060408051600583901b8101602001909152825b8381116106e5576000606882815481106104f0576104f061137c565b600091825260209091200154905060e081901c60a082901c67ffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff831663ffffffff891683036106b6576001865101865260008173ffffffffffffffffffffffffffffffffffffffff1663609d33346040518163ffffffff1660e01b8152600401600060405180830381865afa15801561058a573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526105d091908101906113da565b905060008273ffffffffffffffffffffffffffffffffffffffff1663bcef3b556040518163ffffffff1660e01b8152600401602060405180830381865afa15801561061f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064391906114a5565b90506040518060a001604052808881526020018781526020018567ffffffffffffffff168152602001828152602001838152508860018a5161068591906114be565b815181106106955761069561137c565b6020026020010181905250888851106106b3575050505050506106e5565b50505b50507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90920191506104d49050565b505b9392505050565b60008060006106ff878787876109ef565b60009081526067602052604090205473ffffffffffffffffffffffffffffffffffffffff81169860a09190911c67ffffffffffffffff16975095505050505050565b610749610d00565b6107536000610d81565b565b63ffffffff841660009081526065602052604081205473ffffffffffffffffffffffffffffffffffffffff16806107c5576040517f031c6de400000000000000000000000000000000000000000000000000000000815263ffffffff871660048201526024015b60405180910390fd5b63ffffffff86166000908152606660205260409020543414610813576040517f8620aa1900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006108206001436114be565b40905061088a338783888860405160200161083f9594939291906114fc565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905273ffffffffffffffffffffffffffffffffffffffff841690610df8565b92508273ffffffffffffffffffffffffffffffffffffffff16638129fc1c346040518263ffffffff1660e01b81526004016000604051808303818588803b1580156108d457600080fd5b505af11580156108e8573d6000803e3d6000fd5b505050505060006108fb888888886109ef565b60008181526067602052604090205490915015610947576040517f014f6fe5000000000000000000000000000000000000000000000000000000008152600481018290526024016107bc565b60004260a01b60e08a901b178517600083815260676020526040808220839055606880546001810182559083527fa2153420d844928b4421650203c77babc8b33d7f2e7b450e2966db0c220977530183905551919250899163ffffffff8c169173ffffffffffffffffffffffffffffffffffffffff8916917f5b565efe82411da98814f356d0e7bcb8f0219b8d970307c5afb4a6903a8b2e359190a450505050949350505050565b600084848484604051602001610a089493929190611549565b604051602081830303815290604052805190602001209050949350505050565b600080600080600080610a8160688881548110610a4757610a4761137c565b906000526020600020015460e081901c9160a082901c67ffffffffffffffff169173ffffffffffffffffffffffffffffffffffffffff1690565b9199909850909650945050505050565b600054610100900460ff1615808015610ab15750600054600160ff909116105b80610acb5750303b158015610acb575060005460ff166001145b610b57576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016107bc565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610bb557600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610bbd610e06565b610bc682610d81565b8015610c2957600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b610c35610d00565b73ffffffffffffffffffffffffffffffffffffffff8116610cd8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016107bc565b610ce181610d81565b50565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b60335473ffffffffffffffffffffffffffffffffffffffff163314610753576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016107bc565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60006106e760008484610ea5565b600054610100900460ff16610e9d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016107bc565b610753610feb565b600060608203516040830351602084035184518060208701018051600283016c5af43d3d93803e606057fd5bf3895289600d8a035278593da1005b363d3d373d3d3d3d610000806062363936013d738160481b1760218a03527f9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff603a8a035272fd6100003d81600a3d39f336602c57343d527f6062820160781b1761ff9e82106059018a03528060f01b8352606c8101604c8a038cf097505086610f715763301164256000526004601cfd5b905285527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08501527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08401527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa09092019190915292915050565b600054610100900460ff16611082576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016107bc565b61075333610d81565b803563ffffffff8116811461109f57600080fd5b919050565b73ffffffffffffffffffffffffffffffffffffffff81168114610ce157600080fd5b600080604083850312156110d957600080fd5b6110e28361108b565b915060208301356110f2816110a4565b809150509250929050565b60006020828403121561110f57600080fd5b6106e78261108b565b6000806040838503121561112b57600080fd5b6111348361108b565b946020939093013593505050565b60008060006060848603121561115757600080fd5b6111608461108b565b95602085013595506040909401359392505050565b60005b83811015611190578181015183820152602001611178565b8381111561119f576000848401525b50505050565b600081518084526111bd816020860160208601611175565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b8381101561129e578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc001855281518051845287810151888501528681015167ffffffffffffffff16878501526060808201519085015260809081015160a09185018290529061128a818601836111a5565b968901969450505090860190600101611216565b509098975050505050505050565b6020815260006106e760208301846111a5565b600080600080606085870312156112d557600080fd5b6112de8561108b565b935060208501359250604085013567ffffffffffffffff8082111561130257600080fd5b818701915087601f83011261131657600080fd5b81358181111561132557600080fd5b88602082850101111561133757600080fd5b95989497505060200194505050565b60006020828403121561135857600080fd5b5035919050565b60006020828403121561137157600080fd5b81356106e7816110a4565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156113ec57600080fd5b815167ffffffffffffffff8082111561140457600080fd5b818401915084601f83011261141857600080fd5b81518181111561142a5761142a6113ab565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611470576114706113ab565b8160405282815287602084870101111561148957600080fd5b61149a836020830160208801611175565b979650505050505050565b6000602082840312156114b757600080fd5b5051919050565b6000828210156114f7577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b500390565b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008660601b1681528460148201528360348201528183605483013760009101605401908152949350505050565b63ffffffff8516815283602082015260606040820152816060820152818360808301376000818301608090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101939250505056fea164736f6c634300080f000a"; + bytes internal constant delayedWETHCode = +- hex"6080604052600436106101845760003560e01c8063715018a6116100d6578063a9059cbb1161007f578063dd62ed3e11610059578063dd62ed3e1461051c578063f2fde38b14610554578063f3fef3a31461057457610193565b8063a9059cbb146104a8578063cd47bde1146104c8578063d0e30db01461019357610193565b80638da5cb5b116100b05780638da5cb5b1461041757806395d89b4114610442578063977a5ec51461048857610193565b8063715018a61461039057806379502c55146103a55780637eee288d146103f757610193565b80632e1a7d4d1161013857806354fd4d501161011257806354fd4d50146102e75780636a42b8f81461033057806370a082311461036357610193565b80632e1a7d4d14610280578063313ce567146102a0578063485cc955146102c757610193565b80630ca35682116101695780630ca356821461022357806318160ddd1461024357806323b872dd1461026057610193565b806306fdde031461019b578063095ea7b3146101f357610193565b3661019357610191610594565b005b610191610594565b3480156101a757600080fd5b5060408051808201909152600d81527f577261707065642045746865720000000000000000000000000000000000000060208201525b6040516101ea91906113fd565b60405180910390f35b3480156101ff57600080fd5b5061021361020e366004611492565b6105ef565b60405190151581526020016101ea565b34801561022f57600080fd5b5061019161023e3660046114be565b610668565b34801561024f57600080fd5b50475b6040519081526020016101ea565b34801561026c57600080fd5b5061021361027b3660046114d7565b6107b9565b34801561028c57600080fd5b5061019161029b3660046114be565b6109d0565b3480156102ac57600080fd5b506102b5601281565b60405160ff90911681526020016101ea565b3480156102d357600080fd5b506101916102e2366004611518565b6109dd565b3480156102f357600080fd5b506101dd6040518060400160405280600a81526020017f312e312e302d72632e310000000000000000000000000000000000000000000081525081565b34801561033c57600080fd5b507f0000000000000000000000000000000000000000000000000000000000093a80610252565b34801561036f57600080fd5b5061025261037e366004611551565b60656020526000908152604090205481565b34801561039c57600080fd5b50610191610bb9565b3480156103b157600080fd5b506068546103d29073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101ea565b34801561040357600080fd5b50610191610412366004611492565b610bcd565b34801561042357600080fd5b5060335473ffffffffffffffffffffffffffffffffffffffff166103d2565b34801561044e57600080fd5b5060408051808201909152600481527f574554480000000000000000000000000000000000000000000000000000000060208201526101dd565b34801561049457600080fd5b506101916104a3366004611492565b610c21565b3480156104b457600080fd5b506102136104c3366004611492565b610d0e565b3480156104d457600080fd5b506105076104e3366004611518565b60676020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152016101ea565b34801561052857600080fd5b50610252610537366004611518565b606660209081526000928352604080842090915290825290205481565b34801561056057600080fd5b5061019161056f366004611551565b610d22565b34801561058057600080fd5b5061019161058f366004611492565b610dd6565b33600090815260656020526040812080543492906105b390849061159d565b909155505060405134815233907fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9060200160405180910390a2565b33600081815260666020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906106579086815260200190565b60405180910390a350600192915050565b60335473ffffffffffffffffffffffffffffffffffffffff1633146106ee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f44656c61796564574554483a206e6f74206f776e65720000000000000000000060448201526064015b60405180910390fd5b60004782106106fd57476106ff565b815b604051909150600090339083908381818185875af1925050503d8060008114610744576040519150601f19603f3d011682016040523d82523d6000602084013e610749565b606091505b50509050806107b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f44656c61796564574554483a207265636f766572206661696c6564000000000060448201526064016106e5565b505050565b73ffffffffffffffffffffffffffffffffffffffff83166000908152606560205260408120548211156107eb57600080fd5b73ffffffffffffffffffffffffffffffffffffffff84163314801590610861575073ffffffffffffffffffffffffffffffffffffffff841660009081526066602090815260408083203384529091529020547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14155b156108e95773ffffffffffffffffffffffffffffffffffffffff841660009081526066602090815260408083203384529091529020548211156108a357600080fd5b73ffffffffffffffffffffffffffffffffffffffff84166000908152606660209081526040808320338452909152812080548492906108e39084906115b5565b90915550505b73ffffffffffffffffffffffffffffffffffffffff84166000908152606560205260408120805484929061091e9084906115b5565b909155505073ffffffffffffffffffffffffffffffffffffffff83166000908152606560205260408120805484929061095890849061159d565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516109be91815260200190565b60405180910390a35060019392505050565b6109da3382610dd6565b50565b600054610100900460ff16158080156109fd5750600054600160ff909116105b80610a175750303b158015610a17575060005460ff166001145b610aa3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016106e5565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610b0157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610b09611120565b610b12836111bf565b606880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff841617905580156107b457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a1505050565b610bc1611236565b610bcb60006111bf565b565b33600090815260676020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091528120426001820155805490918391839190610c1790849061159d565b9091555050505050565b60335473ffffffffffffffffffffffffffffffffffffffff163314610ca2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f44656c61796564574554483a206e6f74206f776e65720000000000000000000060448201526064016106e5565b73ffffffffffffffffffffffffffffffffffffffff821660008181526066602090815260408083203380855290835292819020859055518481529192917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a35050565b6000610d1b3384846107b9565b9392505050565b610d2a611236565b73ffffffffffffffffffffffffffffffffffffffff8116610dcd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016106e5565b6109da816111bf565b606860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e6791906115cc565b15610ece576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f44656c61796564574554483a20636f6e7472616374206973207061757365640060448201526064016106e5565b33600090815260676020908152604080832073ffffffffffffffffffffffffffffffffffffffff8616845290915290208054821115610f8f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f44656c61796564574554483a20696e73756666696369656e7420756e6c6f636b60448201527f6564207769746864726177616c0000000000000000000000000000000000000060648201526084016106e5565b6000816001015411611022576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f44656c61796564574554483a207769746864726177616c206e6f7420756e6c6f60448201527f636b65640000000000000000000000000000000000000000000000000000000060648201526084016106e5565b427f0000000000000000000000000000000000000000000000000000000000093a808260010154611053919061159d565b11156110e1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f44656c61796564574554483a207769746864726177616c2064656c6179206e6f60448201527f74206d657400000000000000000000000000000000000000000000000000000060648201526084016106e5565b818160000160008282546110f591906115b5565b909155506107b49050826112b7565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b600054610100900460ff166111b7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016106e5565b610bcb61135d565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60335473ffffffffffffffffffffffffffffffffffffffff163314610bcb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106e5565b336000908152606560205260409020548111156112d357600080fd5b33600090815260656020526040812080548392906112f29084906115b5565b9091555050604051339082156108fc029083906000818181858888f19350505050158015611324573d6000803e3d6000fd5b5060405181815233907f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b659060200160405180910390a250565b600054610100900460ff166113f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016106e5565b610bcb336111bf565b600060208083528351808285015260005b8181101561142a5785810183015185820160400152820161140e565b8181111561143c576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b73ffffffffffffffffffffffffffffffffffffffff811681146109da57600080fd5b600080604083850312156114a557600080fd5b82356114b081611470565b946020939093013593505050565b6000602082840312156114d057600080fd5b5035919050565b6000806000606084860312156114ec57600080fd5b83356114f781611470565b9250602084013561150781611470565b929592945050506040919091013590565b6000806040838503121561152b57600080fd5b823561153681611470565b9150602083013561154681611470565b809150509250929050565b60006020828403121561156357600080fd5b8135610d1b81611470565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156115b0576115b061156e565b500190565b6000828210156115c7576115c761156e565b500390565b6000602082840312156115de57600080fd5b81518015158114610d1b57600080fdfea164736f6c634300080f000a"; ++ hex"6080604052600436106101845760003560e01c8063715018a6116100d6578063a9059cbb1161007f578063dd62ed3e11610059578063dd62ed3e1461051c578063f2fde38b14610554578063f3fef3a31461057457610193565b8063a9059cbb146104a8578063cd47bde1146104c8578063d0e30db01461019357610193565b80638da5cb5b116100b05780638da5cb5b1461041757806395d89b4114610442578063977a5ec51461048857610193565b8063715018a61461039057806379502c55146103a55780637eee288d146103f757610193565b80632e1a7d4d1161013857806354fd4d501161011257806354fd4d50146102e75780636a42b8f81461033057806370a082311461036357610193565b80632e1a7d4d14610280578063313ce567146102a0578063485cc955146102c757610193565b80630ca35682116101695780630ca356821461022357806318160ddd1461024357806323b872dd1461026057610193565b806306fdde031461019b578063095ea7b3146101f357610193565b3661019357610191610594565b005b610191610594565b3480156101a757600080fd5b5060408051808201909152600d81527f577261707065642045746865720000000000000000000000000000000000000060208201525b6040516101ea91906113fd565b60405180910390f35b3480156101ff57600080fd5b5061021361020e366004611492565b6105ef565b60405190151581526020016101ea565b34801561022f57600080fd5b5061019161023e3660046114be565b610668565b34801561024f57600080fd5b50475b6040519081526020016101ea565b34801561026c57600080fd5b5061021361027b3660046114d7565b6107b9565b34801561028c57600080fd5b5061019161029b3660046114be565b6109d0565b3480156102ac57600080fd5b506102b5601281565b60405160ff90911681526020016101ea565b3480156102d357600080fd5b506101916102e2366004611518565b6109dd565b3480156102f357600080fd5b506101dd6040518060400160405280600c81526020017f312e312e312d626574612e32000000000000000000000000000000000000000081525081565b34801561033c57600080fd5b507f0000000000000000000000000000000000000000000000000000000000093a80610252565b34801561036f57600080fd5b5061025261037e366004611551565b60656020526000908152604090205481565b34801561039c57600080fd5b50610191610bb9565b3480156103b157600080fd5b506068546103d29073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101ea565b34801561040357600080fd5b50610191610412366004611492565b610bcd565b34801561042357600080fd5b5060335473ffffffffffffffffffffffffffffffffffffffff166103d2565b34801561044e57600080fd5b5060408051808201909152600481527f574554480000000000000000000000000000000000000000000000000000000060208201526101dd565b34801561049457600080fd5b506101916104a3366004611492565b610c21565b3480156104b457600080fd5b506102136104c3366004611492565b610d0e565b3480156104d457600080fd5b506105076104e3366004611518565b60676020908152600092835260408084209091529082529020805460019091015482565b604080519283526020830191909152016101ea565b34801561052857600080fd5b50610252610537366004611518565b606660209081526000928352604080842090915290825290205481565b34801561056057600080fd5b5061019161056f366004611551565b610d22565b34801561058057600080fd5b5061019161058f366004611492565b610dd6565b33600090815260656020526040812080543492906105b390849061159d565b909155505060405134815233907fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9060200160405180910390a2565b33600081815260666020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906106579086815260200190565b60405180910390a350600192915050565b60335473ffffffffffffffffffffffffffffffffffffffff1633146106ee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f44656c61796564574554483a206e6f74206f776e65720000000000000000000060448201526064015b60405180910390fd5b60004782106106fd57476106ff565b815b604051909150600090339083908381818185875af1925050503d8060008114610744576040519150601f19603f3d011682016040523d82523d6000602084013e610749565b606091505b50509050806107b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f44656c61796564574554483a207265636f766572206661696c6564000000000060448201526064016106e5565b505050565b73ffffffffffffffffffffffffffffffffffffffff83166000908152606560205260408120548211156107eb57600080fd5b73ffffffffffffffffffffffffffffffffffffffff84163314801590610861575073ffffffffffffffffffffffffffffffffffffffff841660009081526066602090815260408083203384529091529020547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14155b156108e95773ffffffffffffffffffffffffffffffffffffffff841660009081526066602090815260408083203384529091529020548211156108a357600080fd5b73ffffffffffffffffffffffffffffffffffffffff84166000908152606660209081526040808320338452909152812080548492906108e39084906115b5565b90915550505b73ffffffffffffffffffffffffffffffffffffffff84166000908152606560205260408120805484929061091e9084906115b5565b909155505073ffffffffffffffffffffffffffffffffffffffff83166000908152606560205260408120805484929061095890849061159d565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516109be91815260200190565b60405180910390a35060019392505050565b6109da3382610dd6565b50565b600054610100900460ff16158080156109fd5750600054600160ff909116105b80610a175750303b158015610a17575060005460ff166001145b610aa3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016106e5565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610b0157600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610b09611120565b610b12836111bf565b606880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff841617905580156107b457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a1505050565b610bc1611236565b610bcb60006111bf565b565b33600090815260676020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091528120426001820155805490918391839190610c1790849061159d565b9091555050505050565b60335473ffffffffffffffffffffffffffffffffffffffff163314610ca2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f44656c61796564574554483a206e6f74206f776e65720000000000000000000060448201526064016106e5565b73ffffffffffffffffffffffffffffffffffffffff821660008181526066602090815260408083203380855290835292819020859055518481529192917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a35050565b6000610d1b3384846107b9565b9392505050565b610d2a611236565b73ffffffffffffffffffffffffffffffffffffffff8116610dcd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016106e5565b6109da816111bf565b606860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635c975abb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e6791906115cc565b15610ece576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f44656c61796564574554483a20636f6e7472616374206973207061757365640060448201526064016106e5565b33600090815260676020908152604080832073ffffffffffffffffffffffffffffffffffffffff8616845290915290208054821115610f8f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f44656c61796564574554483a20696e73756666696369656e7420756e6c6f636b60448201527f6564207769746864726177616c0000000000000000000000000000000000000060648201526084016106e5565b6000816001015411611022576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f44656c61796564574554483a207769746864726177616c206e6f7420756e6c6f60448201527f636b65640000000000000000000000000000000000000000000000000000000060648201526084016106e5565b427f0000000000000000000000000000000000000000000000000000000000093a808260010154611053919061159d565b11156110e1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f44656c61796564574554483a207769746864726177616c2064656c6179206e6f60448201527f74206d657400000000000000000000000000000000000000000000000000000060648201526084016106e5565b818160000160008282546110f591906115b5565b909155506107b49050826112b7565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b600054610100900460ff166111b7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016106e5565b610bcb61135d565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60335473ffffffffffffffffffffffffffffffffffffffff163314610bcb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106e5565b336000908152606560205260409020548111156112d357600080fd5b33600090815260656020526040812080548392906112f29084906115b5565b9091555050604051339082156108fc029083906000818181858888f19350505050158015611324573d6000803e3d6000fd5b5060405181815233907f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b659060200160405180910390a250565b600054610100900460ff166113f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016106e5565b610bcb336111bf565b600060208083528351808285015260005b8181101561142a5785810183015185820160400152820161140e565b8181111561143c576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b73ffffffffffffffffffffffffffffffffffffffff811681146109da57600080fd5b600080604083850312156114a557600080fd5b82356114b081611470565b946020939093013593505050565b6000602082840312156114d057600080fd5b5035919050565b6000806000606084860312156114ec57600080fd5b83356114f781611470565b9250602084013561150781611470565b929592945050506040919091013590565b6000806040838503121561152b57600080fd5b823561153681611470565b9150602083013561154681611470565b809150509250929050565b60006020828403121561156357600080fd5b8135610d1b81611470565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082198211156115b0576115b061156e565b500190565b6000828210156115c7576115c761156e565b500390565b6000602082840312156115de57600080fd5b81518015158114610d1b57600080fdfea164736f6c634300080f000a"; + bytes internal constant preimageOracleCode = +- hex"6080604052600436106101d85760003560e01c80639d53a64811610102578063ddcd58de11610095578063ec5efcbc11610064578063ec5efcbc14610681578063f3f480d9146106a1578063faf37bc7146106d4578063fef2b4ed146106e757600080fd5b8063ddcd58de146105d4578063e03110e11461060c578063e159261114610641578063ea7139501461066157600080fd5b8063b5e7154c116100d1578063b5e7154c14610555578063d18534b51461056c578063da35c6641461058c578063dd24f9bf146105a157600080fd5b80639d53a6481461048e5780639d7e8769146104dd578063b2e67ba8146104fd578063b4801e611461053557600080fd5b806361238bde1161017a5780637ac54767116101495780637ac54767146103ca5780638542cf50146103ea578063882856ef146104355780638dc4be111461046e57600080fd5b806361238bde1461031e5780636551927b146103565780637051472e1461038e5780637917de1d146103aa57600080fd5b80633909af5c116101b65780633909af5c146102715780634d52b4c91461029357806352f0f3ad146102a857806354fd4d50146102c857600080fd5b8063013cf08b146101dd5780630359a5631461022e5780632055b36b1461025c575b600080fd5b3480156101e957600080fd5b506101fd6101f8366004612e29565b610714565b6040805173ffffffffffffffffffffffffffffffffffffffff90931683526020830191909152015b60405180910390f35b34801561023a57600080fd5b5061024e610249366004612e6b565b610759565b604051908152602001610225565b34801561026857600080fd5b5061024e601081565b34801561027d57600080fd5b5061029161028c366004613073565b610891565b005b34801561029f57600080fd5b5061024e610ae8565b3480156102b457600080fd5b5061024e6102c336600461315f565b610b03565b3480156102d457600080fd5b506103116040518060400160405280600a81526020017f312e312e322d72632e310000000000000000000000000000000000000000000081525081565b60405161022591906131c6565b34801561032a57600080fd5b5061024e610339366004613217565b600160209081526000928352604080842090915290825290205481565b34801561036257600080fd5b5061024e610371366004612e6b565b601560209081526000928352604080842090915290825290205481565b34801561039a57600080fd5b5061024e6703782dace9d9000081565b3480156103b657600080fd5b506102916103c536600461327b565b610bd9565b3480156103d657600080fd5b5061024e6103e5366004612e29565b6110dc565b3480156103f657600080fd5b50610425610405366004613217565b600260209081526000928352604080842090915290825290205460ff1681565b6040519015158152602001610225565b34801561044157600080fd5b50610455610450366004613317565b6110f3565b60405167ffffffffffffffff9091168152602001610225565b34801561047a57600080fd5b5061029161048936600461334a565b61114d565b34801561049a57600080fd5b5061024e6104a9366004612e6b565b73ffffffffffffffffffffffffffffffffffffffff9091166000908152601860209081526040808320938352929052205490565b3480156104e957600080fd5b506102916104f8366004613396565b611248565b34801561050957600080fd5b5061024e610518366004612e6b565b601760209081526000928352604080842090915290825290205481565b34801561054157600080fd5b5061024e610550366004613317565b6113ff565b34801561056157600080fd5b5061024e620186a081565b34801561057857600080fd5b50610291610587366004613073565b611431565b34801561059857600080fd5b5060135461024e565b3480156105ad57600080fd5b507f000000000000000000000000000000000000000000000000000000000000271061024e565b3480156105e057600080fd5b5061024e6105ef366004612e6b565b601660209081526000928352604080842090915290825290205481565b34801561061857600080fd5b5061062c610627366004613217565b611840565b60408051928352602083019190915201610225565b34801561064d57600080fd5b5061029161065c36600461334a565b611931565b34801561066d57600080fd5b5061029161067c366004613422565b611a39565b34801561068d57600080fd5b5061029161069c366004613491565b611b98565b3480156106ad57600080fd5b507f000000000000000000000000000000000000000000000000000000000000007861024e565b6102916106e2366004613519565b611d1e565b3480156106f357600080fd5b5061024e610702366004612e29565b60006020819052908152604090205481565b6013818154811061072457600080fd5b60009182526020909120600290910201805460019091015473ffffffffffffffffffffffffffffffffffffffff909116915082565b73ffffffffffffffffffffffffffffffffffffffff82166000908152601560209081526040808320848452909152812054819061079c9060601c63ffffffff1690565b63ffffffff16905060005b6010811015610889578160011660010361082f5773ffffffffffffffffffffffffffffffffffffffff85166000908152601460209081526040808320878452909152902081601081106107fc576107fc613555565b01546040805160208101929092528101849052606001604051602081830303815290604052805190602001209250610870565b826003826010811061084357610843613555565b01546040805160208101939093528201526060016040516020818303038152906040528051906020012092505b60019190911c9080610881816135b3565b9150506107a7565b505092915050565b600061089d8a8a610759565b90506108c086868360208b01356108bb6108b68d6135eb565b611fea565b61202a565b80156108de57506108de83838360208801356108bb6108b68a6135eb565b610914576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b86604001358860405160200161092a91906136ba565b6040516020818303038152906040528051906020012014610977576040517f1968a90200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83602001358760200135600161098d91906136f8565b146109c4576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a0c886109d28680613710565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061208b92505050565b610a15886121e6565b836040013588604051602001610a2b91906136ba565b6040516020818303038152906040528051906020012003610a78576040517f9843145b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8a1660009081526015602090815260408083208c8452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000166001179055610adc8a8a3361298e565b50505050505050505050565b6001610af660106002613897565b610b0091906138a3565b81565b6000610b0f8686612a47565b9050610b1c8360086136f8565b82101580610b2a5750602083115b15610b61576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000602081815260c085901b82526008959095528251828252600286526040808320858452875280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558484528752808320948352938652838220558181529384905292205592915050565b60608115610bf257610beb8686612af4565b9050610c2c565b85858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050505b3360009081526014602090815260408083208b845290915280822081516102008101928390529160109082845b815481526020019060010190808311610c5957505050505090506000601560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008b81526020019081526020016000205490506000610cda8260601c63ffffffff1690565b63ffffffff169050333214610d1b576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d2b8260801c63ffffffff1690565b63ffffffff16600003610d6a576040517f87138d5c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d748260c01c90565b67ffffffffffffffff1615610db5576040517f475a253500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b898114610dee576040517f60f95d5a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610dfb89898d8886612b6d565b83516020850160888204881415608883061715610e20576307b1daf16000526004601cfd5b60405160c8810160405260005b83811015610ed0578083018051835260208101516020840152604081015160408401526060810151606084015260808101516080840152508460888301526088810460051b8b013560a883015260c882206001860195508560005b610200811015610ec5576001821615610ea55782818b0152610ec5565b8981015160009081526020938452604090209260019290921c9101610e88565b505050608801610e2d565b50505050600160106002610ee49190613897565b610eee91906138a3565b811115610f27576040517f6229572300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f9c610f3a8360401c63ffffffff1690565b610f4a9063ffffffff168a6136f8565b60401b7fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff606084901b167fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff8516171790565b915084156110295777ffffffffffffffffffffffffffffffffffffffffffffffff82164260c01b179150610fd68260801c63ffffffff1690565b63ffffffff16610fec8360401c63ffffffff1690565b63ffffffff1614611029576040517f7b1dafd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360009081526014602090815260408083208e8452909152902061104f90846010612d9f565b503360008181526018602090815260408083208f8452825280832080546001810182559084528284206004820401805460039092166008026101000a67ffffffffffffffff818102199093164390931602919091179055838352601582528083208f8452909152812084905560609190911b81523690601437366014016000a05050505050505050505050565b600381601081106110ec57600080fd5b0154905081565b6018602052826000526040600020602052816000526040600020818154811061111b57600080fd5b906000526020600020906004918282040191900660080292509250509054906101000a900467ffffffffffffffff1681565b60443560008060088301861061116b5763fe2549876000526004601cfd5b60c083901b60805260888386823786600882030151915060206000858360025afa90508061119857600080fd5b50600080517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0400000000000000000000000000000000000000000000000000000000000000178082526002602090815260408084208a8552825280842080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558385528252808420998452988152888320939093558152908190529490942055505050565b600080603087600037602060006030600060025afa806112705763f91129696000526004601cfd5b6000517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f010000000000000000000000000000000000000000000000000000000000000017608081815260a08c905260c08b905260308a60e037603088609083013760008060c083600a5afa9250826112f2576309bde3396000526004601cfd5b602886106113085763fe2549876000526004601cfd5b6000602882015278200000000000000000000000000000000000000000000000008152600881018b905285810151935060308a8237603081019b909b52505060509098207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0500000000000000000000000000000000000000000000000000000000000000176000818152600260209081526040808320868452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915584845282528083209583529481528482209a909a559081528089529190912096909655505050505050565b6014602052826000526040600020602052816000526040600020816010811061142757600080fd5b0154925083915050565b73ffffffffffffffffffffffffffffffffffffffff891660009081526015602090815260408083208b845290915290205467ffffffffffffffff8116156114a4576040517fc334f06900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6114ae8160c01c90565b67ffffffffffffffff166000036114f1576040517f55d4cbf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000007861151c8260c01c90565b6115309067ffffffffffffffff16426138a3565b11611567576040517f55d4cbf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006115738b8b610759565b905061158c87878360208c01356108bb6108b68e6135eb565b80156115aa57506115aa84848360208901356108bb6108b68b6135eb565b6115e0576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8760400135896040516020016115f691906136ba565b6040516020818303038152906040528051906020012014611643576040517f1968a90200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84602001358860200135600161165991906136f8565b14158061168b575060016116738360601c63ffffffff1690565b61167d91906138ba565b63ffffffff16856020013514155b156116c2576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6116d0896109d28780613710565b6116d9896121e6565b60006116e48a612cc0565b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0200000000000000000000000000000000000000000000000000000000000000179050600061173b8460a01c63ffffffff1690565b67ffffffffffffffff169050600160026000848152602001908152602001600020600083815260200190815260200160002060006101000a81548160ff021916908315150217905550601760008e73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008d8152602001908152602001600020546001600084815260200190815260200160002060008381526020019081526020016000208190555061180d8460801c63ffffffff1690565b600083815260208190526040902063ffffffff9190911690556118318d8d8161298e565b50505050505050505050505050565b6000828152600260209081526040808320848452909152812054819060ff166118c9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f7072652d696d616765206d757374206578697374000000000000000000000000604482015260640160405180910390fd5b50600083815260208181526040909120546118e58160086136f8565b6118f08560206136f8565b1061190e57836119018260086136f8565b61190b91906138a3565b91505b506000938452600160209081526040808620948652939052919092205492909150565b60443560008060088301861061194f5763fe2549876000526004601cfd5b60c083901b6080526088838682378087017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80151908490207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f02000000000000000000000000000000000000000000000000000000000000001760008181526002602090815260408083208b8452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915584845282528083209a83529981528982209390935590815290819052959095209190915550505050565b60008060008060808860601b81528760c01b6014820152858782601c0137601c860181207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0600000000000000000000000000000000000000000000000000000000000000179350604088026260216001603f5a021015611ac35763dd629f866000526004601cfd5b6000808783601c018c5afa94503d6001019150600882018a10611aee5763fe2549876000526004601cfd5b60c082901b81526008018481533d6000600183013e89017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8015160008481526002602090815260408083208d8452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915587845282528083209c83529b81528b8220929092559384528390529790912096909655505050505050565b6000611ba48686610759565b9050611bbd83838360208801356108bb6108b68a6135eb565b611bf3576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602084013515611c2f576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611c37612ddd565b611c45816109d28780613710565b611c4e816121e6565b846040013581604051602001611c6491906136ba565b6040516020818303038152906040528051906020012003611cb1576040517f9843145b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff87166000908152601560209081526040808320898452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000166001179055611d1587873361298e565b50505050505050565b6703782dace9d90000341015611d60576040517fe92c469f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b333214611d99576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611da48160086138df565b63ffffffff168263ffffffff1610611de8576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000027108163ffffffff161015611e48576040517f7b1dafd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000908152601560209081526040808320868452909152902054611e738160801c63ffffffff1690565b63ffffffff1615611eb0576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b608082901b7fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff60a085901b167fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff83161717336000818152601560209081526040808320898452825280832094909455835180850185528381528082018981526013805460018101825590855291517f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a090600290930292830180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909216919091179055517f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a0919091015591815260168252828120968152959052909320349055505050565b600081600001518260200151836040015160405160200161200d93929190613907565b604051602081830303815290604052805190602001209050919050565b60008160005b601081101561207e578060051b880135600186831c16600181146120635760008481526020839052604090209350612074565b600082815260208590526040902093505b5050600101612030565b5090931495945050505050565b608881511461209957600080fd5b602081016020830161211a565b8260031b8201518060001a8160011a60081b178160021a60101b8260031a60181b17178160041a60201b8260051a60281b178260061a60301b8360071a60381b1717179050612114816120ff868560059190911b015190565b1867ffffffffffffffff16600586901b840152565b50505050565b612126600083836120a6565b612132600183836120a6565b61213e600283836120a6565b61214a600383836120a6565b612156600483836120a6565b612162600583836120a6565b61216e600683836120a6565b61217a600783836120a6565b612186600883836120a6565b612192600983836120a6565b61219e600a83836120a6565b6121aa600b83836120a6565b6121b6600c83836120a6565b6121c2600d83836120a6565b6121ce600e83836120a6565b6121da600f83836120a6565b612114601083836120a6565b6040805178010000000000008082800000000000808a8000000080008000602082015279808b00000000800000018000000080008081800000000000800991810191909152788a00000000000000880000000080008009000000008000000a60608201527b8000808b800000000000008b8000000000008089800000000000800360808201527f80000000000080028000000000000080000000000000800a800000008000000a60a08201527f800000008000808180000000000080800000000080000001800000008000800860c082015260009060e0016040516020818303038152906040529050602082016020820161286e565b6102808101516101e082015161014083015160a0840151845118189118186102a082015161020083015161016084015160c0850151602086015118189118186102c083015161022084015161018085015160e0860151604087015118189118186102e08401516102408501516101a0860151610100870151606088015118189118186103008501516102608601516101c0870151610120880151608089015118189118188084603f1c6123998660011b67ffffffffffffffff1690565b18188584603f1c6123b48660011b67ffffffffffffffff1690565b18188584603f1c6123cf8660011b67ffffffffffffffff1690565b181895508483603f1c6123ec8560011b67ffffffffffffffff1690565b181894508387603f1c6124098960011b67ffffffffffffffff1690565b60208b01518b51861867ffffffffffffffff168c5291189190911897508118600181901b603f9190911c18935060c08801518118601481901c602c9190911b1867ffffffffffffffff1660208901526101208801518718602c81901c60149190911b1867ffffffffffffffff1660c08901526102c08801518618600381901c603d9190911b1867ffffffffffffffff166101208901526101c08801518718601981901c60279190911b1867ffffffffffffffff166102c08901526102808801518218602e81901c60129190911b1867ffffffffffffffff166101c089015260408801518618600281901c603e9190911b1867ffffffffffffffff166102808901526101808801518618601581901c602b9190911b1867ffffffffffffffff1660408901526101a08801518518602781901c60199190911b1867ffffffffffffffff166101808901526102608801518718603881901c60089190911b1867ffffffffffffffff166101a08901526102e08801518518600881901c60389190911b1867ffffffffffffffff166102608901526101e08801518218601781901c60299190911b1867ffffffffffffffff166102e089015260808801518718602581901c601b9190911b1867ffffffffffffffff166101e08901526103008801518718603281901c600e9190911b1867ffffffffffffffff1660808901526102a08801518118603e81901c60029190911b1867ffffffffffffffff166103008901526101008801518518600981901c60379190911b1867ffffffffffffffff166102a08901526102008801518118601381901c602d9190911b1867ffffffffffffffff1661010089015260a08801518218601c81901c60249190911b1867ffffffffffffffff1661020089015260608801518518602481901c601c9190911b1867ffffffffffffffff1660a08901526102408801518518602b81901c60159190911b1867ffffffffffffffff1660608901526102208801518618603181901c600f9190911b1867ffffffffffffffff166102408901526101608801518118603681901c600a9190911b1867ffffffffffffffff166102208901525060e08701518518603a81901c60069190911b1867ffffffffffffffff166101608801526101408701518118603d81901c60039190911b1867ffffffffffffffff1660e0880152505067ffffffffffffffff81166101408601525b5050505050565b600582811b8201805160018501831b8401805160028701851b8601805160038901871b8801805160048b0190981b8901805167ffffffffffffffff861985168918811690995283198a16861889169096528819861683188816909352841986168818871690528419831684189095169052919391929190611d15565b612808600082612781565b612813600582612781565b61281e600a82612781565b612829600f82612781565b612834601482612781565b50565b612840816122dc565b612849816127fd565b600383901b820151815160c09190911c9061211490821867ffffffffffffffff168352565b61287a60008284612837565b61288660018284612837565b61289260028284612837565b61289e60038284612837565b6128aa60048284612837565b6128b660058284612837565b6128c260068284612837565b6128ce60078284612837565b6128da60088284612837565b6128e660098284612837565b6128f2600a8284612837565b6128fe600b8284612837565b61290a600c8284612837565b612916600d8284612837565b612922600e8284612837565b61292e600f8284612837565b61293a60108284612837565b61294660118284612837565b61295260128284612837565b61295e60138284612837565b61296a60148284612837565b61297660158284612837565b61298260168284612837565b61211460178284612837565b73ffffffffffffffffffffffffffffffffffffffff83811660009081526016602090815260408083208684529091528082208054908390559051909284169083908381818185875af1925050503d8060008114612a07576040519150601f19603f3d011682016040523d82523d6000602084013e612a0c565b606091505b505090508061277a576040517f83e6cc6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f01000000000000000000000000000000000000000000000000000000000000007effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831617612aed818360408051600093845233602052918152606090922091527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001790565b9392505050565b6060604051905081602082018181018286833760888306808015612b3d5760888290038501848101848103803687375060806001820353506001845160001a1784538652612b54565b608836843760018353608060878401536088850186525b5050505050601f19603f82510116810160405292915050565b6000612b7f8260a01c63ffffffff1690565b67ffffffffffffffff1690506000612b9d8360801c63ffffffff1690565b63ffffffff1690506000612bb78460401c63ffffffff1690565b63ffffffff169050600883108015612bcd575080155b15612c015760c082901b6000908152883560085283513382526017602090815260408084208a855290915290912055612cb6565b60088310158015612c1f575080612c196008856138a3565b93508310155b8015612c335750612c3087826136f8565b83105b15612cb6576000612c4482856138a3565b905087612c528260206136f8565b10158015612c5e575085155b15612c95576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360009081526017602090815260408083208a845290915290209089013590555b5050505050505050565b6000612d43565b66ff00ff00ff00ff8160081c1667ff00ff00ff00ff00612cf18360081b67ffffffffffffffff1690565b1617905065ffff0000ffff8160101c1667ffff0000ffff0000612d1e8360101b67ffffffffffffffff1690565b1617905060008160201c612d3c8360201b67ffffffffffffffff1690565b1792915050565b60808201516020830190612d5b90612cc7565b612cc7565b6040820151612d6990612cc7565b60401b17612d81612d5660018460059190911b015190565b825160809190911b90612d9390612cc7565b60c01b17179392505050565b8260108101928215612dcd579160200282015b82811115612dcd578251825591602001919060010190612db2565b50612dd9929150612df5565b5090565b6040518060200160405280612df0612e0a565b905290565b5b80821115612dd95760008155600101612df6565b6040518061032001604052806019906020820280368337509192915050565b600060208284031215612e3b57600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114612e6657600080fd5b919050565b60008060408385031215612e7e57600080fd5b612e8783612e42565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610320810167ffffffffffffffff81118282101715612ee857612ee8612e95565b60405290565b6040516060810167ffffffffffffffff81118282101715612ee857612ee8612e95565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715612f5857612f58612e95565b604052919050565b803567ffffffffffffffff81168114612e6657600080fd5b6000610320808385031215612f8c57600080fd5b604051602080820182811067ffffffffffffffff82111715612fb057612fb0612e95565b806040525081935085601f860112612fc757600080fd5b612fcf612ec4565b928501928087851115612fe157600080fd5b865b8581101561300157612ff481612f60565b8352918301918301612fe3565b509092525091949350505050565b60006060828403121561302157600080fd5b50919050565b60008083601f84011261303957600080fd5b50813567ffffffffffffffff81111561305157600080fd5b6020830191508360208260051b850101111561306c57600080fd5b9250929050565b60008060008060008060008060006103e08a8c03121561309257600080fd5b61309b8a612e42565b985060208a013597506130b18b60408c01612f78565b96506103608a013567ffffffffffffffff808211156130cf57600080fd5b6130db8d838e0161300f565b97506103808c01359150808211156130f257600080fd5b6130fe8d838e01613027565b90975095506103a08c013591508082111561311857600080fd5b6131248d838e0161300f565b94506103c08c013591508082111561313b57600080fd5b506131488c828d01613027565b915080935050809150509295985092959850929598565b600080600080600060a0868803121561317757600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b60005b838110156131b557818101518382015260200161319d565b838111156121145750506000910152565b60208152600082518060208401526131e581604085016020870161319a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b6000806040838503121561322a57600080fd5b50508035926020909101359150565b60008083601f84011261324b57600080fd5b50813567ffffffffffffffff81111561326357600080fd5b60208301915083602082850101111561306c57600080fd5b600080600080600080600060a0888a03121561329657600080fd5b8735965060208801359550604088013567ffffffffffffffff808211156132bc57600080fd5b6132c88b838c01613239565b909750955060608a01359150808211156132e157600080fd5b506132ee8a828b01613027565b9094509250506080880135801515811461330757600080fd5b8091505092959891949750929550565b60008060006060848603121561332c57600080fd5b61333584612e42565b95602085013595506040909401359392505050565b60008060006040848603121561335f57600080fd5b83359250602084013567ffffffffffffffff81111561337d57600080fd5b61338986828701613239565b9497909650939450505050565b600080600080600080600060a0888a0312156133b157600080fd5b8735965060208801359550604088013567ffffffffffffffff808211156133d757600080fd5b6133e38b838c01613239565b909750955060608a01359150808211156133fc57600080fd5b506134098a828b01613239565b989b979a50959894979596608090950135949350505050565b60008060008060006080868803121561343a57600080fd5b8535945061344a60208701612e42565b935061345860408701612f60565b9250606086013567ffffffffffffffff81111561347457600080fd5b61348088828901613239565b969995985093965092949392505050565b6000806000806000608086880312156134a957600080fd5b6134b286612e42565b945060208601359350604086013567ffffffffffffffff808211156134d657600080fd5b6134e289838a0161300f565b945060608801359150808211156134f857600080fd5b5061348088828901613027565b803563ffffffff81168114612e6657600080fd5b60008060006060848603121561352e57600080fd5b8335925061353e60208501613505565b915061354c60408501613505565b90509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036135e4576135e4613584565b5060010190565b6000606082360312156135fd57600080fd5b613605612eee565b823567ffffffffffffffff8082111561361d57600080fd5b9084019036601f83011261363057600080fd5b813560208282111561364457613644612e95565b613674817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f85011601612f11565b9250818352368183860101111561368a57600080fd5b81818501828501376000918301810191909152908352848101359083015250604092830135928101929092525090565b81516103208201908260005b60198110156136ef57825167ffffffffffffffff168252602092830192909101906001016136c6565b50505092915050565b6000821982111561370b5761370b613584565b500190565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261374557600080fd5b83018035915067ffffffffffffffff82111561376057600080fd5b60200191503681900382131561306c57600080fd5b600181815b808511156137ce57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156137b4576137b4613584565b808516156137c157918102915b93841c939080029061377a565b509250929050565b6000826137e557506001613891565b816137f257506000613891565b816001811461380857600281146138125761382e565b6001915050613891565b60ff84111561382357613823613584565b50506001821b613891565b5060208310610133831016604e8410600b8410161715613851575081810a613891565b61385b8383613775565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561388d5761388d613584565b0290505b92915050565b6000612aed83836137d6565b6000828210156138b5576138b5613584565b500390565b600063ffffffff838116908316818110156138d7576138d7613584565b039392505050565b600063ffffffff8083168185168083038211156138fe576138fe613584565b01949350505050565b6000845161391981846020890161319a565b9190910192835250602082015260400191905056fea164736f6c634300080f000a"; ++ hex"6080604052600436106101d85760003560e01c80639d53a64811610102578063ddcd58de11610095578063ec5efcbc11610064578063ec5efcbc14610681578063f3f480d9146106a1578063faf37bc7146106d4578063fef2b4ed146106e757600080fd5b8063ddcd58de146105d4578063e03110e11461060c578063e159261114610641578063ea7139501461066157600080fd5b8063b5e7154c116100d1578063b5e7154c14610555578063d18534b51461056c578063da35c6641461058c578063dd24f9bf146105a157600080fd5b80639d53a6481461048e5780639d7e8769146104dd578063b2e67ba8146104fd578063b4801e611461053557600080fd5b806361238bde1161017a5780637ac54767116101495780637ac54767146103ca5780638542cf50146103ea578063882856ef146104355780638dc4be111461046e57600080fd5b806361238bde1461031e5780636551927b146103565780637051472e1461038e5780637917de1d146103aa57600080fd5b80633909af5c116101b65780633909af5c146102715780634d52b4c91461029357806352f0f3ad146102a857806354fd4d50146102c857600080fd5b8063013cf08b146101dd5780630359a5631461022e5780632055b36b1461025c575b600080fd5b3480156101e957600080fd5b506101fd6101f8366004612e29565b610714565b6040805173ffffffffffffffffffffffffffffffffffffffff90931683526020830191909152015b60405180910390f35b34801561023a57600080fd5b5061024e610249366004612e6b565b610759565b604051908152602001610225565b34801561026857600080fd5b5061024e601081565b34801561027d57600080fd5b5061029161028c366004613073565b610891565b005b34801561029f57600080fd5b5061024e610ae8565b3480156102b457600080fd5b5061024e6102c336600461315f565b610b03565b3480156102d457600080fd5b506103116040518060400160405280600c81526020017f312e312e332d626574612e32000000000000000000000000000000000000000081525081565b60405161022591906131c6565b34801561032a57600080fd5b5061024e610339366004613217565b600160209081526000928352604080842090915290825290205481565b34801561036257600080fd5b5061024e610371366004612e6b565b601560209081526000928352604080842090915290825290205481565b34801561039a57600080fd5b5061024e6703782dace9d9000081565b3480156103b657600080fd5b506102916103c536600461327b565b610bd9565b3480156103d657600080fd5b5061024e6103e5366004612e29565b6110dc565b3480156103f657600080fd5b50610425610405366004613217565b600260209081526000928352604080842090915290825290205460ff1681565b6040519015158152602001610225565b34801561044157600080fd5b50610455610450366004613317565b6110f3565b60405167ffffffffffffffff9091168152602001610225565b34801561047a57600080fd5b5061029161048936600461334a565b61114d565b34801561049a57600080fd5b5061024e6104a9366004612e6b565b73ffffffffffffffffffffffffffffffffffffffff9091166000908152601860209081526040808320938352929052205490565b3480156104e957600080fd5b506102916104f8366004613396565b611248565b34801561050957600080fd5b5061024e610518366004612e6b565b601760209081526000928352604080842090915290825290205481565b34801561054157600080fd5b5061024e610550366004613317565b6113ff565b34801561056157600080fd5b5061024e620186a081565b34801561057857600080fd5b50610291610587366004613073565b611431565b34801561059857600080fd5b5060135461024e565b3480156105ad57600080fd5b507f000000000000000000000000000000000000000000000000000000000000271061024e565b3480156105e057600080fd5b5061024e6105ef366004612e6b565b601660209081526000928352604080842090915290825290205481565b34801561061857600080fd5b5061062c610627366004613217565b611840565b60408051928352602083019190915201610225565b34801561064d57600080fd5b5061029161065c36600461334a565b611931565b34801561066d57600080fd5b5061029161067c366004613422565b611a39565b34801561068d57600080fd5b5061029161069c366004613491565b611b98565b3480156106ad57600080fd5b507f000000000000000000000000000000000000000000000000000000000000007861024e565b6102916106e2366004613519565b611d1e565b3480156106f357600080fd5b5061024e610702366004612e29565b60006020819052908152604090205481565b6013818154811061072457600080fd5b60009182526020909120600290910201805460019091015473ffffffffffffffffffffffffffffffffffffffff909116915082565b73ffffffffffffffffffffffffffffffffffffffff82166000908152601560209081526040808320848452909152812054819061079c9060601c63ffffffff1690565b63ffffffff16905060005b6010811015610889578160011660010361082f5773ffffffffffffffffffffffffffffffffffffffff85166000908152601460209081526040808320878452909152902081601081106107fc576107fc613555565b01546040805160208101929092528101849052606001604051602081830303815290604052805190602001209250610870565b826003826010811061084357610843613555565b01546040805160208101939093528201526060016040516020818303038152906040528051906020012092505b60019190911c9080610881816135b3565b9150506107a7565b505092915050565b600061089d8a8a610759565b90506108c086868360208b01356108bb6108b68d6135eb565b611fea565b61202a565b80156108de57506108de83838360208801356108bb6108b68a6135eb565b610914576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b86604001358860405160200161092a91906136ba565b6040516020818303038152906040528051906020012014610977576040517f1968a90200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83602001358760200135600161098d91906136f8565b146109c4576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a0c886109d28680613710565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061208b92505050565b610a15886121e6565b836040013588604051602001610a2b91906136ba565b6040516020818303038152906040528051906020012003610a78576040517f9843145b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8a1660009081526015602090815260408083208c8452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000166001179055610adc8a8a3361298e565b50505050505050505050565b6001610af660106002613897565b610b0091906138a3565b81565b6000610b0f8686612a47565b9050610b1c8360086136f8565b82101580610b2a5750602083115b15610b61576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000602081815260c085901b82526008959095528251828252600286526040808320858452875280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558484528752808320948352938652838220558181529384905292205592915050565b60608115610bf257610beb8686612af4565b9050610c2c565b85858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050505b3360009081526014602090815260408083208b845290915280822081516102008101928390529160109082845b815481526020019060010190808311610c5957505050505090506000601560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008b81526020019081526020016000205490506000610cda8260601c63ffffffff1690565b63ffffffff169050333214610d1b576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d2b8260801c63ffffffff1690565b63ffffffff16600003610d6a576040517f87138d5c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d748260c01c90565b67ffffffffffffffff1615610db5576040517f475a253500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b898114610dee576040517f60f95d5a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610dfb89898d8886612b6d565b83516020850160888204881415608883061715610e20576307b1daf16000526004601cfd5b60405160c8810160405260005b83811015610ed0578083018051835260208101516020840152604081015160408401526060810151606084015260808101516080840152508460888301526088810460051b8b013560a883015260c882206001860195508560005b610200811015610ec5576001821615610ea55782818b0152610ec5565b8981015160009081526020938452604090209260019290921c9101610e88565b505050608801610e2d565b50505050600160106002610ee49190613897565b610eee91906138a3565b811115610f27576040517f6229572300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f9c610f3a8360401c63ffffffff1690565b610f4a9063ffffffff168a6136f8565b60401b7fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff606084901b167fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff8516171790565b915084156110295777ffffffffffffffffffffffffffffffffffffffffffffffff82164260c01b179150610fd68260801c63ffffffff1690565b63ffffffff16610fec8360401c63ffffffff1690565b63ffffffff1614611029576040517f7b1dafd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360009081526014602090815260408083208e8452909152902061104f90846010612d9f565b503360008181526018602090815260408083208f8452825280832080546001810182559084528284206004820401805460039092166008026101000a67ffffffffffffffff818102199093164390931602919091179055838352601582528083208f8452909152812084905560609190911b81523690601437366014016000a05050505050505050505050565b600381601081106110ec57600080fd5b0154905081565b6018602052826000526040600020602052816000526040600020818154811061111b57600080fd5b906000526020600020906004918282040191900660080292509250509054906101000a900467ffffffffffffffff1681565b60443560008060088301861061116b5763fe2549876000526004601cfd5b60c083901b60805260888386823786600882030151915060206000858360025afa90508061119857600080fd5b50600080517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0400000000000000000000000000000000000000000000000000000000000000178082526002602090815260408084208a8552825280842080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558385528252808420998452988152888320939093558152908190529490942055505050565b600080603087600037602060006030600060025afa806112705763f91129696000526004601cfd5b6000517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f010000000000000000000000000000000000000000000000000000000000000017608081815260a08c905260c08b905260308a60e037603088609083013760008060c083600a5afa9250826112f2576309bde3396000526004601cfd5b602886106113085763fe2549876000526004601cfd5b6000602882015278200000000000000000000000000000000000000000000000008152600881018b905285810151935060308a8237603081019b909b52505060509098207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0500000000000000000000000000000000000000000000000000000000000000176000818152600260209081526040808320868452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915584845282528083209583529481528482209a909a559081528089529190912096909655505050505050565b6014602052826000526040600020602052816000526040600020816010811061142757600080fd5b0154925083915050565b73ffffffffffffffffffffffffffffffffffffffff891660009081526015602090815260408083208b845290915290205467ffffffffffffffff8116156114a4576040517fc334f06900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6114ae8160c01c90565b67ffffffffffffffff166000036114f1576040517f55d4cbf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000007861151c8260c01c90565b6115309067ffffffffffffffff16426138a3565b11611567576040517f55d4cbf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006115738b8b610759565b905061158c87878360208c01356108bb6108b68e6135eb565b80156115aa57506115aa84848360208901356108bb6108b68b6135eb565b6115e0576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8760400135896040516020016115f691906136ba565b6040516020818303038152906040528051906020012014611643576040517f1968a90200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84602001358860200135600161165991906136f8565b14158061168b575060016116738360601c63ffffffff1690565b61167d91906138ba565b63ffffffff16856020013514155b156116c2576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6116d0896109d28780613710565b6116d9896121e6565b60006116e48a612cc0565b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0200000000000000000000000000000000000000000000000000000000000000179050600061173b8460a01c63ffffffff1690565b67ffffffffffffffff169050600160026000848152602001908152602001600020600083815260200190815260200160002060006101000a81548160ff021916908315150217905550601760008e73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008d8152602001908152602001600020546001600084815260200190815260200160002060008381526020019081526020016000208190555061180d8460801c63ffffffff1690565b600083815260208190526040902063ffffffff9190911690556118318d8d8161298e565b50505050505050505050505050565b6000828152600260209081526040808320848452909152812054819060ff166118c9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f7072652d696d616765206d757374206578697374000000000000000000000000604482015260640160405180910390fd5b50600083815260208181526040909120546118e58160086136f8565b6118f08560206136f8565b1061190e57836119018260086136f8565b61190b91906138a3565b91505b506000938452600160209081526040808620948652939052919092205492909150565b60443560008060088301861061194f5763fe2549876000526004601cfd5b60c083901b6080526088838682378087017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80151908490207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f02000000000000000000000000000000000000000000000000000000000000001760008181526002602090815260408083208b8452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915584845282528083209a83529981528982209390935590815290819052959095209190915550505050565b60008060008060808860601b81528760c01b6014820152858782601c0137601c860181207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0600000000000000000000000000000000000000000000000000000000000000179350604088026260216001603f5a021015611ac35763dd629f866000526004601cfd5b6000808783601c018c5afa94503d6001019150600882018a10611aee5763fe2549876000526004601cfd5b60c082901b81526008018481533d6000600183013e89017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8015160008481526002602090815260408083208d8452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915587845282528083209c83529b81528b8220929092559384528390529790912096909655505050505050565b6000611ba48686610759565b9050611bbd83838360208801356108bb6108b68a6135eb565b611bf3576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602084013515611c2f576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611c37612ddd565b611c45816109d28780613710565b611c4e816121e6565b846040013581604051602001611c6491906136ba565b6040516020818303038152906040528051906020012003611cb1576040517f9843145b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff87166000908152601560209081526040808320898452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000166001179055611d1587873361298e565b50505050505050565b6703782dace9d90000341015611d60576040517fe92c469f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b333214611d99576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611da48160086138df565b63ffffffff168263ffffffff1610611de8576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000027108163ffffffff161015611e48576040517f7b1dafd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000908152601560209081526040808320868452909152902054611e738160801c63ffffffff1690565b63ffffffff1615611eb0576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b608082901b7fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff60a085901b167fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff83161717336000818152601560209081526040808320898452825280832094909455835180850185528381528082018981526013805460018101825590855291517f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a090600290930292830180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909216919091179055517f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a0919091015591815260168252828120968152959052909320349055505050565b600081600001518260200151836040015160405160200161200d93929190613907565b604051602081830303815290604052805190602001209050919050565b60008160005b601081101561207e578060051b880135600186831c16600181146120635760008481526020839052604090209350612074565b600082815260208590526040902093505b5050600101612030565b5090931495945050505050565b608881511461209957600080fd5b602081016020830161211a565b8260031b8201518060001a8160011a60081b178160021a60101b8260031a60181b17178160041a60201b8260051a60281b178260061a60301b8360071a60381b1717179050612114816120ff868560059190911b015190565b1867ffffffffffffffff16600586901b840152565b50505050565b612126600083836120a6565b612132600183836120a6565b61213e600283836120a6565b61214a600383836120a6565b612156600483836120a6565b612162600583836120a6565b61216e600683836120a6565b61217a600783836120a6565b612186600883836120a6565b612192600983836120a6565b61219e600a83836120a6565b6121aa600b83836120a6565b6121b6600c83836120a6565b6121c2600d83836120a6565b6121ce600e83836120a6565b6121da600f83836120a6565b612114601083836120a6565b6040805178010000000000008082800000000000808a8000000080008000602082015279808b00000000800000018000000080008081800000000000800991810191909152788a00000000000000880000000080008009000000008000000a60608201527b8000808b800000000000008b8000000000008089800000000000800360808201527f80000000000080028000000000000080000000000000800a800000008000000a60a08201527f800000008000808180000000000080800000000080000001800000008000800860c082015260009060e0016040516020818303038152906040529050602082016020820161286e565b6102808101516101e082015161014083015160a0840151845118189118186102a082015161020083015161016084015160c0850151602086015118189118186102c083015161022084015161018085015160e0860151604087015118189118186102e08401516102408501516101a0860151610100870151606088015118189118186103008501516102608601516101c0870151610120880151608089015118189118188084603f1c6123998660011b67ffffffffffffffff1690565b18188584603f1c6123b48660011b67ffffffffffffffff1690565b18188584603f1c6123cf8660011b67ffffffffffffffff1690565b181895508483603f1c6123ec8560011b67ffffffffffffffff1690565b181894508387603f1c6124098960011b67ffffffffffffffff1690565b60208b01518b51861867ffffffffffffffff168c5291189190911897508118600181901b603f9190911c18935060c08801518118601481901c602c9190911b1867ffffffffffffffff1660208901526101208801518718602c81901c60149190911b1867ffffffffffffffff1660c08901526102c08801518618600381901c603d9190911b1867ffffffffffffffff166101208901526101c08801518718601981901c60279190911b1867ffffffffffffffff166102c08901526102808801518218602e81901c60129190911b1867ffffffffffffffff166101c089015260408801518618600281901c603e9190911b1867ffffffffffffffff166102808901526101808801518618601581901c602b9190911b1867ffffffffffffffff1660408901526101a08801518518602781901c60199190911b1867ffffffffffffffff166101808901526102608801518718603881901c60089190911b1867ffffffffffffffff166101a08901526102e08801518518600881901c60389190911b1867ffffffffffffffff166102608901526101e08801518218601781901c60299190911b1867ffffffffffffffff166102e089015260808801518718602581901c601b9190911b1867ffffffffffffffff166101e08901526103008801518718603281901c600e9190911b1867ffffffffffffffff1660808901526102a08801518118603e81901c60029190911b1867ffffffffffffffff166103008901526101008801518518600981901c60379190911b1867ffffffffffffffff166102a08901526102008801518118601381901c602d9190911b1867ffffffffffffffff1661010089015260a08801518218601c81901c60249190911b1867ffffffffffffffff1661020089015260608801518518602481901c601c9190911b1867ffffffffffffffff1660a08901526102408801518518602b81901c60159190911b1867ffffffffffffffff1660608901526102208801518618603181901c600f9190911b1867ffffffffffffffff166102408901526101608801518118603681901c600a9190911b1867ffffffffffffffff166102208901525060e08701518518603a81901c60069190911b1867ffffffffffffffff166101608801526101408701518118603d81901c60039190911b1867ffffffffffffffff1660e0880152505067ffffffffffffffff81166101408601525b5050505050565b600582811b8201805160018501831b8401805160028701851b8601805160038901871b8801805160048b0190981b8901805167ffffffffffffffff861985168918811690995283198a16861889169096528819861683188816909352841986168818871690528419831684189095169052919391929190611d15565b612808600082612781565b612813600582612781565b61281e600a82612781565b612829600f82612781565b612834601482612781565b50565b612840816122dc565b612849816127fd565b600383901b820151815160c09190911c9061211490821867ffffffffffffffff168352565b61287a60008284612837565b61288660018284612837565b61289260028284612837565b61289e60038284612837565b6128aa60048284612837565b6128b660058284612837565b6128c260068284612837565b6128ce60078284612837565b6128da60088284612837565b6128e660098284612837565b6128f2600a8284612837565b6128fe600b8284612837565b61290a600c8284612837565b612916600d8284612837565b612922600e8284612837565b61292e600f8284612837565b61293a60108284612837565b61294660118284612837565b61295260128284612837565b61295e60138284612837565b61296a60148284612837565b61297660158284612837565b61298260168284612837565b61211460178284612837565b73ffffffffffffffffffffffffffffffffffffffff83811660009081526016602090815260408083208684529091528082208054908390559051909284169083908381818185875af1925050503d8060008114612a07576040519150601f19603f3d011682016040523d82523d6000602084013e612a0c565b606091505b505090508061277a576040517f83e6cc6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f01000000000000000000000000000000000000000000000000000000000000007effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831617612aed818360408051600093845233602052918152606090922091527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001790565b9392505050565b6060604051905081602082018181018286833760888306808015612b3d5760888290038501848101848103803687375060806001820353506001845160001a1784538652612b54565b608836843760018353608060878401536088850186525b5050505050601f19603f82510116810160405292915050565b6000612b7f8260a01c63ffffffff1690565b67ffffffffffffffff1690506000612b9d8360801c63ffffffff1690565b63ffffffff1690506000612bb78460401c63ffffffff1690565b63ffffffff169050600883108015612bcd575080155b15612c015760c082901b6000908152883560085283513382526017602090815260408084208a855290915290912055612cb6565b60088310158015612c1f575080612c196008856138a3565b93508310155b8015612c335750612c3087826136f8565b83105b15612cb6576000612c4482856138a3565b905087612c528260206136f8565b10158015612c5e575085155b15612c95576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360009081526017602090815260408083208a845290915290209089013590555b5050505050505050565b6000612d43565b66ff00ff00ff00ff8160081c1667ff00ff00ff00ff00612cf18360081b67ffffffffffffffff1690565b1617905065ffff0000ffff8160101c1667ffff0000ffff0000612d1e8360101b67ffffffffffffffff1690565b1617905060008160201c612d3c8360201b67ffffffffffffffff1690565b1792915050565b60808201516020830190612d5b90612cc7565b612cc7565b6040820151612d6990612cc7565b60401b17612d81612d5660018460059190911b015190565b825160809190911b90612d9390612cc7565b60c01b17179392505050565b8260108101928215612dcd579160200282015b82811115612dcd578251825591602001919060010190612db2565b50612dd9929150612df5565b5090565b6040518060200160405280612df0612e0a565b905290565b5b80821115612dd95760008155600101612df6565b6040518061032001604052806019906020820280368337509192915050565b600060208284031215612e3b57600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114612e6657600080fd5b919050565b60008060408385031215612e7e57600080fd5b612e8783612e42565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610320810167ffffffffffffffff81118282101715612ee857612ee8612e95565b60405290565b6040516060810167ffffffffffffffff81118282101715612ee857612ee8612e95565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715612f5857612f58612e95565b604052919050565b803567ffffffffffffffff81168114612e6657600080fd5b6000610320808385031215612f8c57600080fd5b604051602080820182811067ffffffffffffffff82111715612fb057612fb0612e95565b806040525081935085601f860112612fc757600080fd5b612fcf612ec4565b928501928087851115612fe157600080fd5b865b8581101561300157612ff481612f60565b8352918301918301612fe3565b509092525091949350505050565b60006060828403121561302157600080fd5b50919050565b60008083601f84011261303957600080fd5b50813567ffffffffffffffff81111561305157600080fd5b6020830191508360208260051b850101111561306c57600080fd5b9250929050565b60008060008060008060008060006103e08a8c03121561309257600080fd5b61309b8a612e42565b985060208a013597506130b18b60408c01612f78565b96506103608a013567ffffffffffffffff808211156130cf57600080fd5b6130db8d838e0161300f565b97506103808c01359150808211156130f257600080fd5b6130fe8d838e01613027565b90975095506103a08c013591508082111561311857600080fd5b6131248d838e0161300f565b94506103c08c013591508082111561313b57600080fd5b506131488c828d01613027565b915080935050809150509295985092959850929598565b600080600080600060a0868803121561317757600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b60005b838110156131b557818101518382015260200161319d565b838111156121145750506000910152565b60208152600082518060208401526131e581604085016020870161319a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b6000806040838503121561322a57600080fd5b50508035926020909101359150565b60008083601f84011261324b57600080fd5b50813567ffffffffffffffff81111561326357600080fd5b60208301915083602082850101111561306c57600080fd5b600080600080600080600060a0888a03121561329657600080fd5b8735965060208801359550604088013567ffffffffffffffff808211156132bc57600080fd5b6132c88b838c01613239565b909750955060608a01359150808211156132e157600080fd5b506132ee8a828b01613027565b9094509250506080880135801515811461330757600080fd5b8091505092959891949750929550565b60008060006060848603121561332c57600080fd5b61333584612e42565b95602085013595506040909401359392505050565b60008060006040848603121561335f57600080fd5b83359250602084013567ffffffffffffffff81111561337d57600080fd5b61338986828701613239565b9497909650939450505050565b600080600080600080600060a0888a0312156133b157600080fd5b8735965060208801359550604088013567ffffffffffffffff808211156133d757600080fd5b6133e38b838c01613239565b909750955060608a01359150808211156133fc57600080fd5b506134098a828b01613239565b989b979a50959894979596608090950135949350505050565b60008060008060006080868803121561343a57600080fd5b8535945061344a60208701612e42565b935061345860408701612f60565b9250606086013567ffffffffffffffff81111561347457600080fd5b61348088828901613239565b969995985093965092949392505050565b6000806000806000608086880312156134a957600080fd5b6134b286612e42565b945060208601359350604086013567ffffffffffffffff808211156134d657600080fd5b6134e289838a0161300f565b945060608801359150808211156134f857600080fd5b5061348088828901613027565b803563ffffffff81168114612e6657600080fd5b60008060006060848603121561352e57600080fd5b8335925061353e60208501613505565b915061354c60408501613505565b90509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036135e4576135e4613584565b5060010190565b6000606082360312156135fd57600080fd5b613605612eee565b823567ffffffffffffffff8082111561361d57600080fd5b9084019036601f83011261363057600080fd5b813560208282111561364457613644612e95565b613674817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f85011601612f11565b9250818352368183860101111561368a57600080fd5b81818501828501376000918301810191909152908352848101359083015250604092830135928101929092525090565b81516103208201908260005b60198110156136ef57825167ffffffffffffffff168252602092830192909101906001016136c6565b50505092915050565b6000821982111561370b5761370b613584565b500190565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261374557600080fd5b83018035915067ffffffffffffffff82111561376057600080fd5b60200191503681900382131561306c57600080fd5b600181815b808511156137ce57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156137b4576137b4613584565b808516156137c157918102915b93841c939080029061377a565b509250929050565b6000826137e557506001613891565b816137f257506000613891565b816001811461380857600281146138125761382e565b6001915050613891565b60ff84111561382357613823613584565b50506001821b613891565b5060208310610133831016604e8410600b8410161715613851575081810a613891565b61385b8383613775565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561388d5761388d613584565b0290505b92915050565b6000612aed83836137d6565b6000828210156138b5576138b5613584565b500390565b600063ffffffff838116908316818110156138d7576138d7613584565b039392505050565b600063ffffffff8083168185168083038211156138fe576138fe613584565b01949350505050565b6000845161391981846020890161319a565b9190910192835250602082015260400191905056fea164736f6c634300080f000a"; + bytes internal constant mipsCode = +- hex"608060405234801561001057600080fd5b50600436106100415760003560e01c806354fd4d50146100465780637dc0d1d014610098578063e14ced32146100dc575b600080fd5b6100826040518060400160405280600a81526020017f312e312e302d72632e310000000000000000000000000000000000000000000081525081565b60405161008f91906121ee565b60405180910390f35b60405173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000373d916d11cce55b548f7051002e76bcfbd7a85d16815260200161008f565b6100ef6100ea3660046122a3565b6100fd565b60405190815260200161008f565b6000610107612164565b6080811461011457600080fd5b6040516106001461012457600080fd5b6084871461013157600080fd5b6101a4851461013f57600080fd5b8635608052602087013560a052604087013560e090811c60c09081526044890135821c82526048890135821c61010052604c890135821c610120526050890135821c61014052605489013590911c61016052605888013560f890811c610180526059890135901c6101a0819052605a89013590911c6101c05260628801906101e09060018111156101f5576040517f0136cc76000000000000000000000000000000000000000000000000000000008152600481fd5b506020810181511461020657600080fd5b60200160005b602081101561023057823560e01c825260049092019160209091019060010161020c565b5050508061012001511561024e576102466103a6565b91505061039d565b6101408101805160010167ffffffffffffffff16905260006101a49050600080600061028385606001518660000151866104f7565b9250925092508163ffffffff1660001480156102a557508063ffffffff16600c145b156102bf576102b387610521565b9550505050505061039d565b6000610339866040805160808101825260008082526020820181905291810182905260608101919091526040518060800160405280836060015163ffffffff168152602001836080015163ffffffff1681526020018360a0015163ffffffff1681526020018360c0015163ffffffff168152509050919050565b6101608701518751919250610356918391906105248888886108f9565b8652805163ffffffff9081166060808901919091526020830151821660808901526040830151821660a08901528201511660c08701526103946103a6565b96505050505050505b95945050505050565b60408051608051815260a051602082015260dc519181019190915260fc51604482015261011c51604882015261013c51604c82015261015c51605082015261017c5160548201526101805161019f5160588301526101a0516101bf5160598401526101d851605a8401526000926102009290916062830191906001811115610453576040517f0136cc76000000000000000000000000000000000000000000000000000000008152600481fd5b60005b602081101561047a57601c8601518452602090950194600490930192600101610456565b506000835283830384a060009450806001811461049a57600395506104c2565b8280156104b257600181146104bb57600296506104c0565b600096506104c0565b600196505b505b50505081900390207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1660f89190911b17919050565b6000806000610507858786610cdf565b925050603f601a83901c8116915082165b93509350939050565b600061052b612164565b608090506000806000806105628561016001516040810151608082015160a083015160c084015160e0909401519294919390929091565b509350935093509350600080610ffa63ffffffff168663ffffffff16036105a75761059285858960e00151610d93565b63ffffffff1660e08a01529092509050610808565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03363ffffffff8716016105e05763400000009150610808565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefe863ffffffff8716016106165760019150610808565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffef6a63ffffffff87160161066a57600161012088015260ff851661010088015261065d6103a6565b9998505050505050505050565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff05d63ffffffff8716016107665760006040518061012001604052808763ffffffff1681526020018663ffffffff1681526020018563ffffffff16815260200189602001518152602001896040015163ffffffff1681526020018b81526020017f000000000000000000000000373d916d11cce55b548f7051002e76bcfbd7a85d73ffffffffffffffffffffffffffffffffffffffff1681526020016107386101a4600160ff16610380020190565b81528951602090910152905061074d81610e27565b8b5263ffffffff1660408b015290935091506108089050565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff05c63ffffffff8716016107cb57602087015160408801516107b1918791879187916105248d5161109f565b63ffffffff1660408b015260208a01529092509050610808565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff02963ffffffff871601610808576108028585611195565b90925090505b6000610882886040805160808101825260008082526020820181905291810182905260608101919091526040518060800160405280836060015163ffffffff168152602001836080015163ffffffff1681526020018360a0015163ffffffff1681526020018360c0015163ffffffff168152509050919050565b61016089015163ffffffff85811660408084019190915285821660e0909301929092526020830180518083168086526004909101831682526060808e01919091529051821660808d015291830151811660a08c0152908201511660c08a015290506108eb6103a6565b9a9950505050505050505050565b84600263ffffffff8416148061091557508263ffffffff166003145b156109675760006002856303ffffff1663ffffffff16901b896020015163f00000001617905061096189898663ffffffff1660021461095557601f610958565b60005b60ff168461124a565b50610cd4565b600080601f601087901c8116908a90601589901c166020811061098c5761098c612317565b602002015192508063ffffffff871615806109ad57508663ffffffff16601c145b156109df578a8263ffffffff16602081106109ca576109ca612317565b6020020151925050601f600b88901c16610a96565b60208763ffffffff161015610a41578663ffffffff16600c1480610a0957508663ffffffff16600d145b80610a1a57508663ffffffff16600e145b15610a2b578761ffff169250610a96565b610a3a8861ffff166010611322565b9250610a96565b60288763ffffffff16101580610a5d57508663ffffffff166022145b80610a6e57508663ffffffff166026145b15610a96578a8263ffffffff1660208110610a8b57610a8b612317565b602002015192508190505b60048763ffffffff1610158015610ab3575060088763ffffffff16105b80610ac457508663ffffffff166001145b15610ae057610ad78c8c898b8689611395565b50505050610cd4565b63ffffffff6000602089831610610b4557610b008a61ffff166010611322565b9095019463fffffffc8616610b168d828e610cdf565b915060288a63ffffffff1610158015610b3657508963ffffffff16603014155b15610b4357809250600093505b505b6000610b558b8b8b8a8a87611583565b63ffffffff1690508963ffffffff166000148015610b7a575060088963ffffffff1610155b8015610b8c5750601c8963ffffffff16105b15610c54578863ffffffff1660081480610bac57508863ffffffff166009145b15610bdf57610bd38f8f8b63ffffffff16600814610bca5786610bcd565b60005b8a61124a565b50505050505050610cd4565b8863ffffffff16600a03610c0157610bd38f8f868a63ffffffff8b1615611ca0565b8863ffffffff16600b03610c2457610bd38f8f868a63ffffffff8b161515611ca0565b60108963ffffffff1610158015610c415750601c8963ffffffff16105b15610c5457610bd38f8f8b8a8a89611d70565b8963ffffffff166038148015610c6f575063ffffffff851615155b15610c9f5760018e8663ffffffff1660208110610c8e57610c8e612317565b63ffffffff90921660209290920201525b8263ffffffff1663ffffffff14610cbe57610cbb838d83612029565b97505b610ccc8f8f86846001611ca0565b505050505050505b979650505050505050565b6000610cea826120cb565b6003831615610cf857600080fd5b6020820191358360051c8160005b601b811015610d5e5760208601953583821c6001168015610d2e5760018114610d4357610d54565b60008481526020839052604090209350610d54565b600082815260208590526040902093505b5050600101610d06565b50868114610d7457630badf00d60005260206000fd5b5050601f93909316601c0360031b9290921c63ffffffff169392505050565b6000808284610fff811615610dad57610fff811661100003015b8663ffffffff16600003610e195784935090810190636000000063ffffffff83161180610de557508463ffffffff168263ffffffff16105b80610dfb57508563ffffffff168163ffffffff16105b15610e14575063ffffffff925060169150839050610518565b610e1d565b8693505b5093509350939050565b6101008101516080820151825160009283929163ffffffff161561109857845163ffffffff167ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb01611052576000610e93866101000151876020015163fffffffc168860e00151610cdf565b606087015190915060001a600103610f1557610f0f86606001518760a0015160408051600093845233602052918152606090922091527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001790565b60608701525b6000808760c0015173ffffffffffffffffffffffffffffffffffffffff1663e03110e189606001518a608001516040518363ffffffff1660e01b8152600401610f6e92919091825263ffffffff16602082015260400190565b6040805180830381865afa158015610f8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fae9190612346565b60208a015160408b01519294509092509060038216600481900384811015610fd4578094505b5083821015610fe1578193505b8460088502610100031c9450846008828660040303021b9450600180600883600403021b036001806008878560040303021b0391508119811690508581198816179650505061103f8a6020015163fffffffc168b60e0015187612029565b9298505050938601939250611098915050565b845163ffffffff167ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd0161108c5784604001519350611098565b63ffffffff9350600992505b9193509193565b600080858563ffffffff8b16600114806110bf575063ffffffff8b166002145b806110d0575063ffffffff8b166004145b156110dd57889350611187565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa63ffffffff8c160161117b57600061111d868c63fffffffc1689610cdf565b90508860038c166004038b81101561113357809b505b8b965086900360089081029290921c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600193880293841b0116911b17915060009050611187565b63ffffffff9350600992505b975097509750979350505050565b60008063ffffffff83166003036112385763ffffffff841615806111bf575063ffffffff84166005145b806111d0575063ffffffff84166003145b156111de5760009150611243565b63ffffffff8416600114806111f9575063ffffffff84166002145b8061120a575063ffffffff84166006145b8061121b575063ffffffff84166004145b156112295760019150611243565b5063ffffffff90506009611243565b5063ffffffff905060165b9250929050565b836000015160040163ffffffff16846020015163ffffffff16146112cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6a756d7020696e2064656c617920736c6f74000000000000000000000000000060448201526064015b60405180910390fd5b835160208501805163ffffffff908116875283811690915283161561131b5780600801848463ffffffff166020811061130a5761130a612317565b63ffffffff90921660209290920201525b5050505050565b600063ffffffff8381167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80850183169190911c821615159160016020869003821681901b830191861691821b92911b018261137f576000611381565b815b90861663ffffffff16179250505092915050565b6000866000015160040163ffffffff16876020015163ffffffff1614611417576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f6272616e636820696e2064656c617920736c6f7400000000000000000000000060448201526064016112c6565b8463ffffffff166004148061143257508463ffffffff166005145b156114a9576000868463ffffffff166020811061145157611451612317565b602002015190508063ffffffff168363ffffffff1614801561147957508563ffffffff166004145b806114a157508063ffffffff168363ffffffff16141580156114a157508563ffffffff166005145b915050611526565b8463ffffffff166006036114c65760008260030b13159050611526565b8463ffffffff166007036114e25760008260030b139050611526565b8463ffffffff1660010361152657601f601085901c16600081900361150b5760008360030b1291505b8063ffffffff166001036115245760008360030b121591505b505b8651602088015163ffffffff168852811561156757600261154c8661ffff166010611322565b63ffffffff90811690911b8201600401166020890152611579565b60208801805160040163ffffffff1690525b5050505050505050565b600063ffffffff861615806115b0575060088663ffffffff16101580156115b05750600f8663ffffffff16105b156119b05785600881146115f357600981146115fc57600a811461160557600b811461160e57600c811461161757600d811461162057600e81146116295761162e565b6020955061162e565b6021955061162e565b602a955061162e565b602b955061162e565b6024955061162e565b6025955061162e565b602695505b508463ffffffff16600003611653575063ffffffff8216601f600688901c161b611c96565b8463ffffffff16600203611677575063ffffffff8216601f600688901c161c611c96565b8463ffffffff166003036116ab57601f600688901c166116a363ffffffff8516821c6020839003611322565b915050611c96565b8463ffffffff166004036116cb575063ffffffff8216601f84161b611c96565b8463ffffffff166006036116eb575063ffffffff8216601f84161c611c96565b8463ffffffff1660070361171357601f84166116a363ffffffff8516821c6020839003611322565b8463ffffffff16600803611728575082611c96565b8463ffffffff1660090361173d575082611c96565b8463ffffffff16600a03611752575082611c96565b8463ffffffff16600b03611767575082611c96565b8463ffffffff16600c0361177c575082611c96565b8463ffffffff16600f03611791575082611c96565b8463ffffffff166010036117a6575082611c96565b8463ffffffff166011036117bb575082611c96565b8463ffffffff166012036117d0575082611c96565b8463ffffffff166013036117e5575082611c96565b8463ffffffff166018036117fa575082611c96565b8463ffffffff1660190361180f575082611c96565b8463ffffffff16601a03611824575082611c96565b8463ffffffff16601b03611839575082611c96565b8463ffffffff166020036118505750828201611c96565b8463ffffffff166021036118675750828201611c96565b8463ffffffff1660220361187e5750818303611c96565b8463ffffffff166023036118955750818303611c96565b8463ffffffff166024036118ac5750828216611c96565b8463ffffffff166025036118c35750828217611c96565b8463ffffffff166026036118da5750828218611c96565b8463ffffffff166027036118f2575082821719611c96565b8463ffffffff16602a03611921578260030b8460030b12611914576000611917565b60015b60ff169050611c96565b8463ffffffff16602b03611949578263ffffffff168463ffffffff1610611914576000611917565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f696e76616c696420696e737472756374696f6e0000000000000000000000000060448201526064016112c6565b611949565b8563ffffffff16601c03611a30578463ffffffff166002036119d55750828202611c96565b8463ffffffff16602014806119f057508463ffffffff166021145b156119ab578463ffffffff16602003611a07579219925b60005b6380000000851615611a29576401fffffffe600195861b169401611a0a565b9050611c96565b8563ffffffff16600f03611a51575065ffffffff0000601083901b16611c96565b8563ffffffff16602003611a8557611a298460031660080260180363ffffffff168363ffffffff16901c60ff166008611322565b8563ffffffff16602103611aba57611a298460021660080260100363ffffffff168363ffffffff16901c61ffff166010611322565b8563ffffffff16602203611ae8575063ffffffff60086003851602811681811b198416918316901b17611c96565b8563ffffffff16602303611afd575080611c96565b8563ffffffff16602403611b2e578360031660080260180363ffffffff168263ffffffff16901c60ff169050611c96565b8563ffffffff16602503611b60578360021660080260100363ffffffff168263ffffffff16901c61ffff169050611c96565b8563ffffffff16602603611b91575063ffffffff60086003851602601803811681811c198416918316901c17611c96565b8563ffffffff16602803611bc6575060ff63ffffffff60086003861602601803811682811b9091188316918416901b17611c96565b8563ffffffff16602903611bfc575061ffff63ffffffff60086002861602601003811682811b9091188316918416901b17611c96565b8563ffffffff16602a03611c2a575063ffffffff60086003851602811681811c198316918416901c17611c96565b8563ffffffff16602b03611c3f575081611c96565b8563ffffffff16602e03611c70575063ffffffff60086003851602601803811681811b198316918416901b17611c96565b8563ffffffff16603003611c85575080611c96565b8563ffffffff166038036119495750815b9695505050505050565b60208363ffffffff1610611d10576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f76616c696420726567697374657200000000000000000000000000000000000060448201526064016112c6565b63ffffffff831615801590611d225750805b15611d515781848463ffffffff1660208110611d4057611d40612317565b63ffffffff90921660209290920201525b5050505060208101805163ffffffff8082169093526004019091169052565b60008463ffffffff16601003611d8b57506060860151611fd1565b8463ffffffff16601103611daa5763ffffffff84166060880152611fd1565b8463ffffffff16601203611dc357506040860151611fd1565b8463ffffffff16601303611de25763ffffffff84166040880152611fd1565b8463ffffffff16601803611e165763ffffffff600385810b9085900b02602081901c821660608a0152166040880152611fd1565b8463ffffffff16601903611e475763ffffffff84811681851602602081901c821660608a0152166040880152611fd1565b8463ffffffff16601a03611f0a578260030b600003611ec2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d4950533a206469766973696f6e206279207a65726f0000000000000000000060448201526064016112c6565b8260030b8460030b81611ed757611ed761236a565b0763ffffffff166060880152600383810b9085900b81611ef957611ef961236a565b0563ffffffff166040880152611fd1565b8463ffffffff16601b03611fd1578263ffffffff16600003611f88576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d4950533a206469766973696f6e206279207a65726f0000000000000000000060448201526064016112c6565b8263ffffffff168463ffffffff1681611fa357611fa361236a565b0663ffffffff908116606089015283811690851681611fc457611fc461236a565b0463ffffffff1660408801525b63ffffffff8216156120075780868363ffffffff1660208110611ff657611ff6612317565b63ffffffff90921660209290920201525b50505060208401805163ffffffff808216909652600401909416909352505050565b6000612034836120cb565b600384161561204257600080fd5b6020830192601f8516601c0360031b83811b913563ffffffff90911b1916178460051c60005b601b8110156120c05760208601953582821c600116801561209057600181146120a5576120b6565b600085815260208390526040902094506120b6565b600082815260208690526040902094505b5050600101612068565b509095945050505050565b366103808201811015612160576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f636865636b207468617420746865726520697320656e6f7567682063616c6c6460448201527f617461000000000000000000000000000000000000000000000000000000000060648201526084016112c6565b5050565b6040805161018081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081018290526101008101829052610120810182905261014081019190915261016081016121ca6121cf565b905290565b6040518061040001604052806020906020820280368337509192915050565b600060208083528351808285015260005b8181101561221b578581018301518582016040015282016121ff565b8181111561222d576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b60008083601f84011261227357600080fd5b50813567ffffffffffffffff81111561228b57600080fd5b60208301915083602082850101111561124357600080fd5b6000806000806000606086880312156122bb57600080fd5b853567ffffffffffffffff808211156122d357600080fd5b6122df89838a01612261565b909750955060208801359150808211156122f857600080fd5b5061230588828901612261565b96999598509660400135949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000806040838503121561235957600080fd5b505080516020909101519092909150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fdfea164736f6c634300080f000a"; ++ hex"608060405234801561001057600080fd5b50600436106100415760003560e01c806354fd4d50146100465780637dc0d1d014610098578063e14ced32146100dc575b600080fd5b6100826040518060400160405280600c81526020017f312e312e312d626574612e33000000000000000000000000000000000000000081525081565b60405161008f9190612237565b60405180910390f35b60405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000007a9eab4ce99d157aee7a02e95b366e972a2d5b0b16815260200161008f565b6100ef6100ea3660046122ec565b6100fd565b60405190815260200161008f565b60006101076121ad565b6080811461011457600080fd5b6040516106001461012457600080fd5b6084871461013157600080fd5b6101a4851461013f57600080fd5b8635608052602087013560a052604087013560e090811c60c09081526044890135821c82526048890135821c61010052604c890135821c610120526050890135821c61014052605489013590911c61016052605888013560f890811c610180526059890135901c6101a0819052605a89013590911c6101c05260628801906101e09060018111156101f5576040517f0136cc76000000000000000000000000000000000000000000000000000000008152600481fd5b506020810181511461020657600080fd5b60200160005b602081101561023057823560e01c825260049092019160209091019060010161020c565b5050508061012001511561024e576102466103a6565b91505061039d565b6101408101805160010167ffffffffffffffff16905260006101a49050600080600061028385606001518660000151866104f7565b9250925092508163ffffffff1660001480156102a557508063ffffffff16600c145b156102bf576102b387610521565b9550505050505061039d565b6000610339866040805160808101825260008082526020820181905291810182905260608101919091526040518060800160405280836060015163ffffffff168152602001836080015163ffffffff1681526020018360a0015163ffffffff1681526020018360c0015163ffffffff168152509050919050565b6101608701518751919250610356918391906105248888886108f9565b8652805163ffffffff9081166060808901919091526020830151821660808901526040830151821660a08901528201511660c08701526103946103a6565b96505050505050505b95945050505050565b60408051608051815260a051602082015260dc519181019190915260fc51604482015261011c51604882015261013c51604c82015261015c51605082015261017c5160548201526101805161019f5160588301526101a0516101bf5160598401526101d851605a8401526000926102009290916062830191906001811115610453576040517f0136cc76000000000000000000000000000000000000000000000000000000008152600481fd5b60005b602081101561047a57601c8601518452602090950194600490930192600101610456565b506000835283830384a060009450806001811461049a57600395506104c2565b8280156104b257600181146104bb57600296506104c0565b600096506104c0565b600196505b505b50505081900390207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1660f89190911b17919050565b6000806000610507858786610cdf565b925050603f601a83901c8116915082165b93509350939050565b600061052b6121ad565b608090506000806000806105628561016001516040810151608082015160a083015160c084015160e0909401519294919390929091565b509350935093509350600080610ffa63ffffffff168663ffffffff16036105a75761059285858960e00151610d31565b63ffffffff1660e08a01529092509050610808565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03363ffffffff8716016105e05763400000009150610808565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefe863ffffffff8716016106165760019150610808565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffef6a63ffffffff87160161066a57600161012088015260ff851661010088015261065d6103a6565b9998505050505050505050565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff05d63ffffffff8716016107665760006040518061012001604052808763ffffffff1681526020018663ffffffff1681526020018563ffffffff16815260200189602001518152602001896040015163ffffffff1681526020018b81526020017f0000000000000000000000007a9eab4ce99d157aee7a02e95b366e972a2d5b0b73ffffffffffffffffffffffffffffffffffffffff1681526020016107386101a4600160ff16610380020190565b81528951602090910152905061074d81610dc5565b8b5263ffffffff1660408b015290935091506108089050565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff05c63ffffffff8716016107cb57602087015160408801516107b1918791879187916105248d5161103d565b63ffffffff1660408b015260208a01529092509050610808565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff02963ffffffff871601610808576108028585611133565b90925090505b6000610882886040805160808101825260008082526020820181905291810182905260608101919091526040518060800160405280836060015163ffffffff168152602001836080015163ffffffff1681526020018360a0015163ffffffff1681526020018360c0015163ffffffff168152509050919050565b61016089015163ffffffff85811660408084019190915285821660e0909301929092526020830180518083168086526004909101831682526060808e01919091529051821660808d015291830151811660a08c0152908201511660c08a015290506108eb6103a6565b9a9950505050505050505050565b84600263ffffffff8416148061091557508263ffffffff166003145b156109675760006002856303ffffff1663ffffffff16901b896020015163f00000001617905061096189898663ffffffff1660021461095557601f610958565b60005b60ff16846111e8565b50610cd4565b600080601f601087901c8116908a90601589901c166020811061098c5761098c612360565b602002015192508063ffffffff871615806109ad57508663ffffffff16601c145b156109df578a8263ffffffff16602081106109ca576109ca612360565b6020020151925050601f600b88901c16610a96565b60208763ffffffff161015610a41578663ffffffff16600c1480610a0957508663ffffffff16600d145b80610a1a57508663ffffffff16600e145b15610a2b578761ffff169250610a96565b610a3a8861ffff1660106112c0565b9250610a96565b60288763ffffffff16101580610a5d57508663ffffffff166022145b80610a6e57508663ffffffff166026145b15610a96578a8263ffffffff1660208110610a8b57610a8b612360565b602002015192508190505b60048763ffffffff1610158015610ab3575060088763ffffffff16105b80610ac457508663ffffffff166001145b15610ae057610ad78c8c898b8689611333565b50505050610cd4565b63ffffffff6000602089831610610b4557610b008a61ffff1660106112c0565b9095019463fffffffc8616610b168d828e610cdf565b915060288a63ffffffff1610158015610b3657508963ffffffff16603014155b15610b4357809250600093505b505b6000610b558b8b8b8a8a87611521565b63ffffffff1690508963ffffffff166000148015610b7a575060088963ffffffff1610155b8015610b8c5750601c8963ffffffff16105b15610c54578863ffffffff1660081480610bac57508863ffffffff166009145b15610bdf57610bd38f8f8b63ffffffff16600814610bca5786610bcd565b60005b8a6111e8565b50505050505050610cd4565b8863ffffffff16600a03610c0157610bd38f8f868a63ffffffff8b1615611c3e565b8863ffffffff16600b03610c2457610bd38f8f868a63ffffffff8b161515611c3e565b60108963ffffffff1610158015610c415750601c8963ffffffff16105b15610c5457610bd38f8f8b8a8a89611d0e565b8963ffffffff166038148015610c6f575063ffffffff851615155b15610c9f5760018e8663ffffffff1660208110610c8e57610c8e612360565b63ffffffff90921660209290920201525b8263ffffffff1663ffffffff14610cbe57610cbb838d83611fc7565b97505b610ccc8f8f86846001611c3e565b505050505050505b979650505050505050565b600080610ced858585612069565b909250905080610d29576040517f8e77b2b700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b509392505050565b6000808284610fff811615610d4b57610fff811661100003015b8663ffffffff16600003610db75784935090810190636000000063ffffffff83161180610d8357508463ffffffff168263ffffffff16105b80610d9957508563ffffffff168163ffffffff16105b15610db2575063ffffffff925060169150839050610518565b610dbb565b8693505b5093509350939050565b6101008101516080820151825160009283929163ffffffff161561103657845163ffffffff167ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb01610ff0576000610e31866101000151876020015163fffffffc168860e00151610cdf565b606087015190915060001a600103610eb357610ead86606001518760a0015160408051600093845233602052918152606090922091527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001790565b60608701525b6000808760c0015173ffffffffffffffffffffffffffffffffffffffff1663e03110e189606001518a608001516040518363ffffffff1660e01b8152600401610f0c92919091825263ffffffff16602082015260400190565b6040805180830381865afa158015610f28573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4c919061238f565b60208a015160408b01519294509092509060038216600481900384811015610f72578094505b5083821015610f7f578193505b8460088502610100031c9450846008828660040303021b9450600180600883600403021b036001806008878560040303021b03915081198116905085811988161796505050610fdd8a6020015163fffffffc168b60e0015187611fc7565b9298505050938601939250611036915050565b845163ffffffff167ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd0161102a5784604001519350611036565b63ffffffff9350600992505b9193509193565b600080858563ffffffff8b166001148061105d575063ffffffff8b166002145b8061106e575063ffffffff8b166004145b1561107b57889350611125565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa63ffffffff8c16016111195760006110bb868c63fffffffc1689610cdf565b90508860038c166004038b8110156110d157809b505b8b965086900360089081029290921c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600193880293841b0116911b17915060009050611125565b63ffffffff9350600992505b975097509750979350505050565b60008063ffffffff83166003036111d65763ffffffff8416158061115d575063ffffffff84166005145b8061116e575063ffffffff84166003145b1561117c57600091506111e1565b63ffffffff841660011480611197575063ffffffff84166002145b806111a8575063ffffffff84166006145b806111b9575063ffffffff84166004145b156111c757600191506111e1565b5063ffffffff905060096111e1565b5063ffffffff905060165b9250929050565b836000015160040163ffffffff16846020015163ffffffff161461126d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6a756d7020696e2064656c617920736c6f74000000000000000000000000000060448201526064015b60405180910390fd5b835160208501805163ffffffff90811687528381169091528316156112b95780600801848463ffffffff16602081106112a8576112a8612360565b63ffffffff90921660209290920201525b5050505050565b600063ffffffff8381167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80850183169190911c821615159160016020869003821681901b830191861691821b92911b018261131d57600061131f565b815b90861663ffffffff16179250505092915050565b6000866000015160040163ffffffff16876020015163ffffffff16146113b5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f6272616e636820696e2064656c617920736c6f740000000000000000000000006044820152606401611264565b8463ffffffff16600414806113d057508463ffffffff166005145b15611447576000868463ffffffff16602081106113ef576113ef612360565b602002015190508063ffffffff168363ffffffff1614801561141757508563ffffffff166004145b8061143f57508063ffffffff168363ffffffff161415801561143f57508563ffffffff166005145b9150506114c4565b8463ffffffff166006036114645760008260030b131590506114c4565b8463ffffffff166007036114805760008260030b1390506114c4565b8463ffffffff166001036114c457601f601085901c1660008190036114a95760008360030b1291505b8063ffffffff166001036114c25760008360030b121591505b505b8651602088015163ffffffff16885281156115055760026114ea8661ffff1660106112c0565b63ffffffff90811690911b8201600401166020890152611517565b60208801805160040163ffffffff1690525b5050505050505050565b600063ffffffff8616158061154e575060088663ffffffff161015801561154e5750600f8663ffffffff16105b1561194e578560088114611591576009811461159a57600a81146115a357600b81146115ac57600c81146115b557600d81146115be57600e81146115c7576115cc565b602095506115cc565b602195506115cc565b602a95506115cc565b602b95506115cc565b602495506115cc565b602595506115cc565b602695505b508463ffffffff166000036115f1575063ffffffff8216601f600688901c161b611c34565b8463ffffffff16600203611615575063ffffffff8216601f600688901c161c611c34565b8463ffffffff1660030361164957601f600688901c1661164163ffffffff8516821c60208390036112c0565b915050611c34565b8463ffffffff16600403611669575063ffffffff8216601f84161b611c34565b8463ffffffff16600603611689575063ffffffff8216601f84161c611c34565b8463ffffffff166007036116b157601f841661164163ffffffff8516821c60208390036112c0565b8463ffffffff166008036116c6575082611c34565b8463ffffffff166009036116db575082611c34565b8463ffffffff16600a036116f0575082611c34565b8463ffffffff16600b03611705575082611c34565b8463ffffffff16600c0361171a575082611c34565b8463ffffffff16600f0361172f575082611c34565b8463ffffffff16601003611744575082611c34565b8463ffffffff16601103611759575082611c34565b8463ffffffff1660120361176e575082611c34565b8463ffffffff16601303611783575082611c34565b8463ffffffff16601803611798575082611c34565b8463ffffffff166019036117ad575082611c34565b8463ffffffff16601a036117c2575082611c34565b8463ffffffff16601b036117d7575082611c34565b8463ffffffff166020036117ee5750828201611c34565b8463ffffffff166021036118055750828201611c34565b8463ffffffff1660220361181c5750818303611c34565b8463ffffffff166023036118335750818303611c34565b8463ffffffff1660240361184a5750828216611c34565b8463ffffffff166025036118615750828217611c34565b8463ffffffff166026036118785750828218611c34565b8463ffffffff16602703611890575082821719611c34565b8463ffffffff16602a036118bf578260030b8460030b126118b25760006118b5565b60015b60ff169050611c34565b8463ffffffff16602b036118e7578263ffffffff168463ffffffff16106118b25760006118b5565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f696e76616c696420696e737472756374696f6e000000000000000000000000006044820152606401611264565b6118e7565b8563ffffffff16601c036119ce578463ffffffff166002036119735750828202611c34565b8463ffffffff166020148061198e57508463ffffffff166021145b15611949578463ffffffff166020036119a5579219925b60005b63800000008516156119c7576401fffffffe600195861b1694016119a8565b9050611c34565b8563ffffffff16600f036119ef575065ffffffff0000601083901b16611c34565b8563ffffffff16602003611a23576119c78460031660080260180363ffffffff168363ffffffff16901c60ff1660086112c0565b8563ffffffff16602103611a58576119c78460021660080260100363ffffffff168363ffffffff16901c61ffff1660106112c0565b8563ffffffff16602203611a86575063ffffffff60086003851602811681811b198416918316901b17611c34565b8563ffffffff16602303611a9b575080611c34565b8563ffffffff16602403611acc578360031660080260180363ffffffff168263ffffffff16901c60ff169050611c34565b8563ffffffff16602503611afe578360021660080260100363ffffffff168263ffffffff16901c61ffff169050611c34565b8563ffffffff16602603611b2f575063ffffffff60086003851602601803811681811c198416918316901c17611c34565b8563ffffffff16602803611b64575060ff63ffffffff60086003861602601803811682811b9091188316918416901b17611c34565b8563ffffffff16602903611b9a575061ffff63ffffffff60086002861602601003811682811b9091188316918416901b17611c34565b8563ffffffff16602a03611bc8575063ffffffff60086003851602811681811c198316918416901c17611c34565b8563ffffffff16602b03611bdd575081611c34565b8563ffffffff16602e03611c0e575063ffffffff60086003851602601803811681811b198316918416901b17611c34565b8563ffffffff16603003611c23575080611c34565b8563ffffffff166038036118e75750815b9695505050505050565b60208363ffffffff1610611cae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f76616c69642072656769737465720000000000000000000000000000000000006044820152606401611264565b63ffffffff831615801590611cc05750805b15611cef5781848463ffffffff1660208110611cde57611cde612360565b63ffffffff90921660209290920201525b5050505060208101805163ffffffff8082169093526004019091169052565b60008463ffffffff16601003611d2957506060860151611f6f565b8463ffffffff16601103611d485763ffffffff84166060880152611f6f565b8463ffffffff16601203611d6157506040860151611f6f565b8463ffffffff16601303611d805763ffffffff84166040880152611f6f565b8463ffffffff16601803611db45763ffffffff600385810b9085900b02602081901c821660608a0152166040880152611f6f565b8463ffffffff16601903611de55763ffffffff84811681851602602081901c821660608a0152166040880152611f6f565b8463ffffffff16601a03611ea8578260030b600003611e60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d4950533a206469766973696f6e206279207a65726f000000000000000000006044820152606401611264565b8260030b8460030b81611e7557611e756123b3565b0763ffffffff166060880152600383810b9085900b81611e9757611e976123b3565b0563ffffffff166040880152611f6f565b8463ffffffff16601b03611f6f578263ffffffff16600003611f26576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d4950533a206469766973696f6e206279207a65726f000000000000000000006044820152606401611264565b8263ffffffff168463ffffffff1681611f4157611f416123b3565b0663ffffffff908116606089015283811690851681611f6257611f626123b3565b0463ffffffff1660408801525b63ffffffff821615611fa55780868363ffffffff1660208110611f9457611f94612360565b63ffffffff90921660209290920201525b50505060208401805163ffffffff808216909652600401909416909352505050565b6000611fd283612114565b6003841615611fe057600080fd5b6020830192601f8516601c0360031b83811b913563ffffffff90911b1916178460051c60005b601b81101561205e5760208601953582821c600116801561202e576001811461204357612054565b60008581526020839052604090209450612054565b600082815260208690526040902094505b5050600101612006565b509095945050505050565b60008061207583612114565b600384161561208357600080fd5b6020830192358460051c8160005b601b8110156120e95760208701963583821c60011680156120b957600181146120ce576120df565b600084815260208390526040902093506120df565b600082815260208590526040902093505b5050600101612091565b508714925050811561210b57601f8516601c0360031b81901c63ffffffff1692505b50935093915050565b3661038082018110156121a9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f636865636b207468617420746865726520697320656e6f7567682063616c6c6460448201527f61746100000000000000000000000000000000000000000000000000000000006064820152608401611264565b5050565b6040805161018081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101919091526101608101612213612218565b905290565b6040518061040001604052806020906020820280368337509192915050565b600060208083528351808285015260005b8181101561226457858101830151858201604001528201612248565b81811115612276576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b60008083601f8401126122bc57600080fd5b50813567ffffffffffffffff8111156122d457600080fd5b6020830191508360208285010111156111e157600080fd5b60008060008060006060868803121561230457600080fd5b853567ffffffffffffffff8082111561231c57600080fd5b61232889838a016122aa565b9097509550602088013591508082111561234157600080fd5b5061234e888289016122aa565b96999598509660400135949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600080604083850312156123a257600080fd5b505080516020909101519092909150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fdfea164736f6c634300080f000a"; + bytes internal constant anchorStateRegistryCode = +- hex"608060405234801561001057600080fd5b506004361061007d5760003560e01c80635e05fbd01161005b5780635e05fbd01461012a5780637258a8071461013d578063838c2d1e14610179578063f2b4e6171461018157600080fd5b806317cf21a91461008257806335e80ab31461009757806354fd4d50146100e1575b600080fd5b610095610090366004610b4c565b6101a7565b005b6002546100b79073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b61011d6040518060400160405280600a81526020017f322e302e302d72632e310000000000000000000000000000000000000000000081525081565b6040516100d89190610bea565b610095610138366004610cc6565b61061c565b61016461014b366004610df0565b6001602081905260009182526040909120805491015482565b604080519283526020830191909152016100d8565b610095610853565b7f0000000000000000000000005207cfa0166e8de0fcdfd78b4d17b68587be306d6100b7565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa158015610214573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102389190610e0d565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461029c576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060008373ffffffffffffffffffffffffffffffffffffffff1663fa24f7436040518163ffffffff1660e01b8152600401600060405180830381865afa1580156102ec573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526103329190810190610e2a565b92509250925060007f0000000000000000000000005207cfa0166e8de0fcdfd78b4d17b68587be306d73ffffffffffffffffffffffffffffffffffffffff16635f0150cb8585856040518463ffffffff1660e01b815260040161039793929190610efb565b6040805180830381865afa1580156103b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103d79190610f29565b5090508473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461043f576040517f6b0f689100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60028573ffffffffffffffffffffffffffffffffffffffff1663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa15801561048c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104b09190610f9f565b60028111156104c1576104c1610f70565b146104f8576040517f8f8af25f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052806105788773ffffffffffffffffffffffffffffffffffffffff1663bcef3b556040518163ffffffff1660e01b8152600401602060405180830381865afa158015610551573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105759190610fc0565b90565b81526020018673ffffffffffffffffffffffffffffffffffffffff16638b85902b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ec9190610fc0565b905263ffffffff909416600090815260016020818152604090922086518155959091015194019390935550505050565b600054610100900460ff161580801561063c5750600054600160ff909116105b806106565750303b158015610656575060005460ff166001145b6106e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561074457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b60005b83518110156107aa57600084828151811061076457610764610fd9565b60209081029190910181015180820151905163ffffffff1660009081526001808452604090912082518155919092015191015550806107a281611008565b915050610747565b50600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8416179055801561084e57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b600033905060008060008373ffffffffffffffffffffffffffffffffffffffff1663fa24f7436040518163ffffffff1660e01b8152600401600060405180830381865afa1580156108a8573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526108ee9190810190610e2a565b92509250925060007f0000000000000000000000005207cfa0166e8de0fcdfd78b4d17b68587be306d73ffffffffffffffffffffffffffffffffffffffff16635f0150cb8585856040518463ffffffff1660e01b815260040161095393929190610efb565b6040805180830381865afa15801561096f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109939190610f29565b5090508473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146109fb576040517f6b0f689100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160008563ffffffff1663ffffffff168152602001908152602001600020600101548573ffffffffffffffffffffffffffffffffffffffff16638b85902b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8d9190610fc0565b11610a99575050505050565b60028573ffffffffffffffffffffffffffffffffffffffff1663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ae6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b0a9190610f9f565b6002811115610b1b57610b1b610f70565b146104f8575050505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610b4957600080fd5b50565b600060208284031215610b5e57600080fd5b8135610b6981610b27565b9392505050565b60005b83811015610b8b578181015183820152602001610b73565b83811115610b9a576000848401525b50505050565b60008151808452610bb8816020860160208601610b70565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610b696020830184610ba0565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715610c4f57610c4f610bfd565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715610c9c57610c9c610bfd565b604052919050565b63ffffffff81168114610b4957600080fd5b8035610cc181610b27565b919050565b6000806040808486031215610cda57600080fd5b833567ffffffffffffffff80821115610cf257600080fd5b818601915086601f830112610d0657600080fd5b8135602082821115610d1a57610d1a610bfd565b610d28818360051b01610c55565b8281528181019350606092830285018201928a841115610d4757600080fd5b948201945b83861015610dd457858b0381811215610d655760008081fd5b610d6d610c2c565b8735610d7881610ca4565b81527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08201891315610daa5760008081fd5b610db2610c2c565b8886013581528989013586820152818601528652509485019493820193610d4c565b509650610de2888201610cb6565b955050505050509250929050565b600060208284031215610e0257600080fd5b8135610b6981610ca4565b600060208284031215610e1f57600080fd5b8151610b6981610b27565b600080600060608486031215610e3f57600080fd5b8351610e4a81610ca4565b60208501516040860151919450925067ffffffffffffffff80821115610e6f57600080fd5b818601915086601f830112610e8357600080fd5b815181811115610e9557610e95610bfd565b610ec660207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601610c55565b9150808252876020828501011115610edd57600080fd5b610eee816020840160208601610b70565b5080925050509250925092565b63ffffffff84168152826020820152606060408201526000610f206060830184610ba0565b95945050505050565b60008060408385031215610f3c57600080fd5b8251610f4781610b27565b602084015190925067ffffffffffffffff81168114610f6557600080fd5b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600060208284031215610fb157600080fd5b815160038110610b6957600080fd5b600060208284031215610fd257600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611060577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b506001019056fea164736f6c634300080f000a"; ++ hex"608060405234801561001057600080fd5b506004361061007d5760003560e01c80635e05fbd01161005b5780635e05fbd01461012a5780637258a8071461013d578063838c2d1e14610179578063f2b4e6171461018157600080fd5b806317cf21a91461008257806335e80ab31461009757806354fd4d50146100e1575b600080fd5b610095610090366004610b4c565b6101a7565b005b6002546100b79073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b61011d6040518060400160405280600c81526020017f322e302e312d626574612e32000000000000000000000000000000000000000081525081565b6040516100d89190610bea565b610095610138366004610cc6565b61061c565b61016461014b366004610df0565b6001602081905260009182526040909120805491015482565b604080519283526020830191909152016100d8565b610095610853565b7f0000000000000000000000005207cfa0166e8de0fcdfd78b4d17b68587be306d6100b7565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663452a93206040518163ffffffff1660e01b8152600401602060405180830381865afa158015610214573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102389190610e0d565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461029c576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060008373ffffffffffffffffffffffffffffffffffffffff1663fa24f7436040518163ffffffff1660e01b8152600401600060405180830381865afa1580156102ec573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526103329190810190610e2a565b92509250925060007f0000000000000000000000005207cfa0166e8de0fcdfd78b4d17b68587be306d73ffffffffffffffffffffffffffffffffffffffff16635f0150cb8585856040518463ffffffff1660e01b815260040161039793929190610efb565b6040805180830381865afa1580156103b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103d79190610f29565b5090508473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461043f576040517f6b0f689100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60028573ffffffffffffffffffffffffffffffffffffffff1663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa15801561048c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104b09190610f9f565b60028111156104c1576104c1610f70565b146104f8576040517f8f8af25f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052806105788773ffffffffffffffffffffffffffffffffffffffff1663bcef3b556040518163ffffffff1660e01b8152600401602060405180830381865afa158015610551573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105759190610fc0565b90565b81526020018673ffffffffffffffffffffffffffffffffffffffff16638b85902b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ec9190610fc0565b905263ffffffff909416600090815260016020818152604090922086518155959091015194019390935550505050565b600054610100900460ff161580801561063c5750600054600160ff909116105b806106565750303b158015610656575060005460ff166001145b6106e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561074457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b60005b83518110156107aa57600084828151811061076457610764610fd9565b60209081029190910181015180820151905163ffffffff1660009081526001808452604090912082518155919092015191015550806107a281611008565b915050610747565b50600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8416179055801561084e57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b600033905060008060008373ffffffffffffffffffffffffffffffffffffffff1663fa24f7436040518163ffffffff1660e01b8152600401600060405180830381865afa1580156108a8573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526108ee9190810190610e2a565b92509250925060007f0000000000000000000000005207cfa0166e8de0fcdfd78b4d17b68587be306d73ffffffffffffffffffffffffffffffffffffffff16635f0150cb8585856040518463ffffffff1660e01b815260040161095393929190610efb565b6040805180830381865afa15801561096f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109939190610f29565b5090508473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146109fb576040517f6b0f689100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600160008563ffffffff1663ffffffff168152602001908152602001600020600101548573ffffffffffffffffffffffffffffffffffffffff16638b85902b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8d9190610fc0565b11610a99575050505050565b60028573ffffffffffffffffffffffffffffffffffffffff1663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ae6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b0a9190610f9f565b6002811115610b1b57610b1b610f70565b146104f8575050505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610b4957600080fd5b50565b600060208284031215610b5e57600080fd5b8135610b6981610b27565b9392505050565b60005b83811015610b8b578181015183820152602001610b73565b83811115610b9a576000848401525b50505050565b60008151808452610bb8816020860160208601610b70565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610b696020830184610ba0565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715610c4f57610c4f610bfd565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715610c9c57610c9c610bfd565b604052919050565b63ffffffff81168114610b4957600080fd5b8035610cc181610b27565b919050565b6000806040808486031215610cda57600080fd5b833567ffffffffffffffff80821115610cf257600080fd5b818601915086601f830112610d0657600080fd5b8135602082821115610d1a57610d1a610bfd565b610d28818360051b01610c55565b8281528181019350606092830285018201928a841115610d4757600080fd5b948201945b83861015610dd457858b0381811215610d655760008081fd5b610d6d610c2c565b8735610d7881610ca4565b81527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08201891315610daa5760008081fd5b610db2610c2c565b8886013581528989013586820152818601528652509485019493820193610d4c565b509650610de2888201610cb6565b955050505050509250929050565b600060208284031215610e0257600080fd5b8135610b6981610ca4565b600060208284031215610e1f57600080fd5b8151610b6981610b27565b600080600060608486031215610e3f57600080fd5b8351610e4a81610ca4565b60208501516040860151919450925067ffffffffffffffff80821115610e6f57600080fd5b818601915086601f830112610e8357600080fd5b815181811115610e9557610e95610bfd565b610ec660207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601610c55565b9150808252876020828501011115610edd57600080fd5b610eee816020840160208601610b70565b5080925050509250925092565b63ffffffff84168152826020820152606060408201526000610f206060830184610ba0565b95945050505050565b60008060408385031215610f3c57600080fd5b8251610f4781610b27565b602084015190925067ffffffffffffffff81168114610f6557600080fd5b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600060208284031215610fb157600080fd5b815160038110610b6957600080fd5b600060208284031215610fd257600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611060577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b506001019056fea164736f6c634300080f000a"; + bytes internal constant acc33Code = +- hex"6080604052600436106102f25760003560e01c806370872aa51161018f578063c6f0308c116100e1578063ec5e63081161008a578063fa24f74311610064578063fa24f74314610b18578063fa315aa914610b3c578063fe2bbeb214610b6f57600080fd5b8063ec5e630814610a95578063eff0f59214610ac8578063f8f43ff614610af857600080fd5b8063d6ae3cd5116100bb578063d6ae3cd514610a0f578063d8cc1a3c14610a42578063dabd396d14610a6257600080fd5b8063c6f0308c14610937578063cf09e0d0146109c1578063d5d44d80146109e257600080fd5b80638d450a9511610143578063bcef3b551161011d578063bcef3b55146108b7578063bd8da956146108f7578063c395e1ca1461091757600080fd5b80638d450a9514610777578063a445ece6146107aa578063bbdc02db1461087657600080fd5b80638129fc1c116101745780638129fc1c1461071a5780638980e0cc146107225780638b85902b1461073757600080fd5b806370872aa5146106f25780637b0f0adc1461070757600080fd5b80633fc8cef3116102485780635c0cba33116101fc5780636361506d116101d65780636361506d1461066c5780636b6716c0146106ac5780636f034409146106df57600080fd5b80635c0cba3314610604578063609d33341461063757806360e274641461064c57600080fd5b806354fd4d501161022d57806354fd4d501461055e57806357da950e146105b45780635a5fa2d9146105e457600080fd5b80633fc8cef314610518578063472777c61461054b57600080fd5b80632810e1d6116102aa57806337b1b2291161028457806337b1b229146104655780633a768463146104a55780633e3ac912146104d857600080fd5b80632810e1d6146103de5780632ad69aeb146103f357806330dbe5701461041357600080fd5b806319effeb4116102db57806319effeb414610339578063200d2ed21461038457806325fc2ace146103bf57600080fd5b806301935130146102f757806303c2924d14610319575b600080fd5b34801561030357600080fd5b506103176103123660046154e2565b610b9f565b005b34801561032557600080fd5b5061031761033436600461553d565b610ec0565b34801561034557600080fd5b506000546103669068010000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020015b60405180910390f35b34801561039057600080fd5b506000546103b290700100000000000000000000000000000000900460ff1681565b60405161037b919061558e565b3480156103cb57600080fd5b506008545b60405190815260200161037b565b3480156103ea57600080fd5b506103b2611566565b3480156103ff57600080fd5b506103d061040e36600461553d565b61180b565b34801561041f57600080fd5b506001546104409073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161037b565b34801561047157600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90033560601c610440565b3480156104b157600080fd5b507f000000000000000000000000444e09fe6d839273316a87002ab0efbea6fe7806610440565b3480156104e457600080fd5b50600054610508907201000000000000000000000000000000000000900460ff1681565b604051901515815260200161037b565b34801561052457600080fd5b507f000000000000000000000000ef179756ea6525afade217ca5ab0b1b5cfe0fd92610440565b6103176105593660046155cf565b611841565b34801561056a57600080fd5b506105a76040518060400160405280600a81526020017f312e332e302d72632e310000000000000000000000000000000000000000000081525081565b60405161037b9190615666565b3480156105c057600080fd5b506008546009546105cf919082565b6040805192835260208301919091520161037b565b3480156105f057600080fd5b506103d06105ff366004615679565b611853565b34801561061057600080fd5b507f000000000000000000000000970670459734a83899773a0fd45941b5afc1200e610440565b34801561064357600080fd5b506105a761188d565b34801561065857600080fd5b506103176106673660046156b7565b61189b565b34801561067857600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003603401356103d0565b3480156106b857600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610366565b6103176106ed3660046156e9565b611a42565b3480156106fe57600080fd5b506009546103d0565b6103176107153660046155cf565b61251b565b610317612528565b34801561072e57600080fd5b506002546103d0565b34801561074357600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401356103d0565b34801561078357600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006103d0565b3480156107b657600080fd5b506108226107c5366004615679565b6007602052600090815260409020805460019091015460ff821691610100810463ffffffff1691650100000000009091046fffffffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff1684565b60408051941515855263ffffffff90931660208501526fffffffffffffffffffffffffffffffff9091169183019190915273ffffffffffffffffffffffffffffffffffffffff16606082015260800161037b565b34801561088257600080fd5b5060405163ffffffff7f000000000000000000000000000000000000000000000000000000000000000016815260200161037b565b3480156108c357600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003601401356103d0565b34801561090357600080fd5b50610366610912366004615679565b612a81565b34801561092357600080fd5b506103d0610932366004615728565b612c60565b34801561094357600080fd5b50610957610952366004615679565b612e43565b6040805163ffffffff909816885273ffffffffffffffffffffffffffffffffffffffff968716602089015295909416948601949094526fffffffffffffffffffffffffffffffff9182166060860152608085015291821660a08401521660c082015260e00161037b565b3480156109cd57600080fd5b506000546103669067ffffffffffffffff1681565b3480156109ee57600080fd5b506103d06109fd3660046156b7565b60036020526000908152604090205481565b348015610a1b57600080fd5b507f00000000000000000000000000000000000000000000000000000000000003856103d0565b348015610a4e57600080fd5b50610317610a5d36600461575a565b612eda565b348015610a6e57600080fd5b507f00000000000000000000000000000000000000000000000000000000000004b0610366565b348015610aa157600080fd5b507f00000000000000000000000000000000000000000000000000000000000000046103d0565b348015610ad457600080fd5b50610508610ae3366004615679565b60046020526000908152604090205460ff1681565b348015610b0457600080fd5b50610317610b133660046155cf565b613509565b348015610b2457600080fd5b50610b2d6139c6565b60405161037b939291906157e4565b348015610b4857600080fd5b507f00000000000000000000000000000000000000000000000000000000000000086103d0565b348015610b7b57600080fd5b50610508610b8a366004615679565b60066020526000908152604090205460ff1681565b60008054700100000000000000000000000000000000900460ff166002811115610bcb57610bcb61555f565b14610c02576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000547201000000000000000000000000000000000000900460ff1615610c55576040517f0ea2e75200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610c8c367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013590565b90565b610ca3610c9e36869003860186615838565b613a41565b14610cda576040517f9cc00b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82606001358282604051610cef9291906158c5565b604051809103902014610d2e576040517fd81d583b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610d77610d7284848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613a9d92505050565b613b0a565b90506000610d9e82600881518110610d9157610d916158d5565b6020026020010151613cc0565b9050602081511115610ddc576040517fd81d583b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602081810151825190910360031b1c367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401358103610e51576040517fb8ed883000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050600180547fffffffffffffffffffffffff000000000000000000000000000000000000000016331790555050600080547fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff1672010000000000000000000000000000000000001790555050565b60008054700100000000000000000000000000000000900460ff166002811115610eec57610eec61555f565b14610f23576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028381548110610f3857610f386158d5565b906000526020600020906005020190506000610f5384612a81565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b081169082161015610fbc576040517ff2440b5300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008481526006602052604090205460ff1615611005576040517ff1a9458100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600084815260056020526040902080548015801561102257508515155b156110bd578354640100000000900473ffffffffffffffffffffffffffffffffffffffff16600081156110555781611071565b600186015473ffffffffffffffffffffffffffffffffffffffff165b905061107d8187613d74565b50505060009485525050600660205250506040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b6000868152600760209081526040918290208251608081018452815460ff81161515808352610100820463ffffffff16948301949094526501000000000090046fffffffffffffffffffffffffffffffff16938101939093526001015473ffffffffffffffffffffffffffffffffffffffff166060830152611160576fffffffffffffffffffffffffffffffff6040820152600181526000869003611160578195505b600086826020015163ffffffff166111789190615933565b90506000838211611189578161118b565b835b602084015190915063ffffffff165b818110156112d75760008682815481106111b6576111b66158d5565b6000918252602080832090910154808352600690915260409091205490915060ff1661120e576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028281548110611223576112236158d5565b600091825260209091206005909102018054909150640100000000900473ffffffffffffffffffffffffffffffffffffffff161580156112805750600481015460408701516fffffffffffffffffffffffffffffffff9182169116115b156112c257600181015473ffffffffffffffffffffffffffffffffffffffff16606087015260048101546fffffffffffffffffffffffffffffffff1660408701525b505080806112cf9061594b565b91505061119a565b5063ffffffff818116602085810191825260008c81526007909152604090819020865181549351928801517fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009094169015157fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ff161761010092909416918202939093177fffffffffffffffffffffff00000000000000000000000000000000ffffffffff16650100000000006fffffffffffffffffffffffffffffffff909316929092029190911782556060850151600190920180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9093169290921790915584900361155b57606083015160008a815260066020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558915801561145757506000547201000000000000000000000000000000000000900460ff165b156114cc5760015473ffffffffffffffffffffffffffffffffffffffff1661147f818a613d74565b885473ffffffffffffffffffffffffffffffffffffffff909116640100000000027fffffffffffffffff0000000000000000000000000000000000000000ffffffff909116178855611559565b61151373ffffffffffffffffffffffffffffffffffffffff8216156114f1578161150d565b600189015473ffffffffffffffffffffffffffffffffffffffff165b89613d74565b87547fffffffffffffffff0000000000000000000000000000000000000000ffffffff1664010000000073ffffffffffffffffffffffffffffffffffffffff8316021788555b505b505050505050505050565b600080600054700100000000000000000000000000000000900460ff1660028111156115945761159461555f565b146115cb576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000805260066020527f54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4f85460ff1661162f576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600260008154811061165b5761165b6158d5565b6000918252602090912060059091020154640100000000900473ffffffffffffffffffffffffffffffffffffffff1614611696576001611699565b60025b6000805467ffffffffffffffff421668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff82168117835592935083927fffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffff000000000000000000ffffffffffffffff9091161770010000000000000000000000000000000083600281111561174a5761174a61555f565b02179055600281111561175f5761175f61555f565b6040517f5e186f09b9c93491f14e277eea7faa5de6a2d4bda75a79af7a3684fbfb42da6090600090a27f000000000000000000000000970670459734a83899773a0fd45941b5afc1200e73ffffffffffffffffffffffffffffffffffffffff1663838c2d1e6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156117f057600080fd5b505af1158015611804573d6000803e3d6000fd5b5050505090565b6005602052816000526040600020818154811061182757600080fd5b90600052602060002001600091509150505481565b905090565b61184e8383836001611a42565b505050565b6000818152600760209081526040808320600590925282208054825461188490610100900463ffffffff1682615983565b95945050505050565b606061183c60546020613e75565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260036020526040812080549082905590819003611900576040517f17bfe5f700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517ff3fef3a300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152602482018390527f000000000000000000000000ef179756ea6525afade217ca5ab0b1b5cfe0fd92169063f3fef3a390604401600060405180830381600087803b15801561199057600080fd5b505af11580156119a4573d6000803e3d6000fd5b5050505060008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114611a02576040519150601f19603f3d011682016040523d82523d6000602084013e611a07565b606091505b505090508061184e576040517f83e6cc6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008054700100000000000000000000000000000000900460ff166002811115611a6e57611a6e61555f565b14611aa5576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028481548110611aba57611aba6158d5565b60009182526020918290206040805160e0810182526005909302909101805463ffffffff8116845273ffffffffffffffffffffffffffffffffffffffff64010000000090910481169484019490945260018101549093169082015260028201546fffffffffffffffffffffffffffffffff908116606083015260038301546080830181905260049093015480821660a084015270010000000000000000000000000000000090041660c082015291508514611ba1576040517f3014033200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60a0810151600083156fffffffffffffffffffffffffffffffff83161760011b90506000611c61826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169050861580611c9c5750611c997f00000000000000000000000000000000000000000000000000000000000000046002615933565b81145b8015611ca6575084155b15611cdd576040517fa42637bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000547201000000000000000000000000000000000000900460ff168015611d03575086155b15611d3a576040517f0ea2e75200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000008811115611d94576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611dbf7f00000000000000000000000000000000000000000000000000000000000000046001615933565b8103611dd157611dd186888588613ec7565b34611ddb83612c60565b14611e12576040517f8620aa1900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611e1d88612a81565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b0811690821603611e85576040517f3381d11400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611eb260017f0000000000000000000000000000000000000000000000000000000000000008615983565b8303611ff0577f000000000000000000000000444e09fe6d839273316a87002ab0efbea6fe780673ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f47919061599a565b73ffffffffffffffffffffffffffffffffffffffff1663f3f480d96040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f91573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fb591906159b7565b611fe9907f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff166159d0565b9050612083565b61201b60017f0000000000000000000000000000000000000000000000000000000000000004615983565b830361205657611fe97f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1660026159fc565b507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff165b6120b7817f00000000000000000000000000000000000000000000000000000000000004b067ffffffffffffffff16615a2c565b67ffffffffffffffff166120d28367ffffffffffffffff1690565b67ffffffffffffffff16111561211957612116817f00000000000000000000000000000000000000000000000000000000000004b067ffffffffffffffff16615a2c565b91505b6000604083901b421760008a8152608087901b6fffffffffffffffffffffffffffffffff8d1617602052604081209192509060008181526004602052604090205490915060ff1615612197576040517f80497e3b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60016004600083815260200190815260200160002060006101000a81548160ff02191690831515021790555060026040518060e001604052808d63ffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020013373ffffffffffffffffffffffffffffffffffffffff168152602001346fffffffffffffffffffffffffffffffff1681526020018c8152602001886fffffffffffffffffffffffffffffffff168152602001846fffffffffffffffffffffffffffffffff16815250908060018154018082558091505060019003906000526020600020906005020160009091909190915060008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060608201518160020160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055506080820151816003015560a08201518160040160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555060c08201518160040160106101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055505050600560008c8152602001908152602001600020600160028054905061242d9190615983565b81546001810183556000928352602083200155604080517fd0e30db0000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ef179756ea6525afade217ca5ab0b1b5cfe0fd92169263d0e30db09234926004808301939282900301818588803b1580156124c557600080fd5b505af11580156124d9573d6000803e3d6000fd5b50506040513393508d92508e91507f9b3245740ec3b155098a55be84957a4da13eaf7f14a8bc6f53126c0b9350f2be90600090a4505050505050505050505050565b61184e8383836000611a42565b60005471010000000000000000000000000000000000900460ff161561257a576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f7258a80700000000000000000000000000000000000000000000000000000000815263ffffffff7f0000000000000000000000000000000000000000000000000000000000000000166004820152600090819073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000970670459734a83899773a0fd45941b5afc1200e1690637258a807906024016040805180830381865afa15801561262e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126529190615a55565b90925090508161268e576040517f6a6bc3b200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080518082019091528281526020018190526008829055600981905536607a146126c157639824bdab6000526004601cfd5b80367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401351161275b576040517ff40239db000000000000000000000000000000000000000000000000000000008152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013560048201526024015b60405180910390fd5b6040805160e08101825263ffffffff8082526000602083018181527ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe369081013560f01c90038035606090811c868801908152346fffffffffffffffffffffffffffffffff81811693890193845260149094013560808901908152600160a08a0181815242871660c08c019081526002805493840181558a529a5160059092027f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace81018054995173ffffffffffffffffffffffffffffffffffffffff908116640100000000027fffffffffffffffff000000000000000000000000000000000000000000000000909b1694909c16939093179890981790915592517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5acf87018054918a167fffffffffffffffffffffffff000000000000000000000000000000000000000090921691909117905592517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad0860180549186167fffffffffffffffffffffffffffffffff0000000000000000000000000000000090921691909117905591517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad185015551955182167001000000000000000000000000000000000295909116949094177f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad29091015580547fffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffff167101000000000000000000000000000000000017815583517fd0e30db000000000000000000000000000000000000000000000000000000000815293517f000000000000000000000000ef179756ea6525afade217ca5ab0b1b5cfe0fd929092169363d0e30db093926004828101939282900301818588803b158015612a3057600080fd5b505af1158015612a44573d6000803e3d6000fd5b5050600080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000164267ffffffffffffffff161790555050505050565b600080600054700100000000000000000000000000000000900460ff166002811115612aaf57612aaf61555f565b14612ae6576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028381548110612afb57612afb6158d5565b600091825260208220600590910201805490925063ffffffff90811614612b6a57815460028054909163ffffffff16908110612b3957612b396158d5565b906000526020600020906005020160040160109054906101000a90046fffffffffffffffffffffffffffffffff1690505b6004820154600090612ba290700100000000000000000000000000000000900467ffffffffffffffff165b67ffffffffffffffff1690565b612bb69067ffffffffffffffff1642615983565b612bd5612b95846fffffffffffffffffffffffffffffffff1660401c90565b67ffffffffffffffff16612be99190615933565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b01667ffffffffffffffff168167ffffffffffffffff1611612c365780611884565b7f00000000000000000000000000000000000000000000000000000000000004b095945050505050565b600080612cff836fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1690507f0000000000000000000000000000000000000000000000000000000000000008811115612d5e576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b642e90edd00062061a806311e1a3006000612d798383615aa8565b9050670de0b6b3a76400006000612db0827f0000000000000000000000000000000000000000000000000000000000000008615abc565b90506000612dce612dc9670de0b6b3a764000086615abc565b614078565b90506000612ddc84846142d3565b90506000612dea8383614322565b90506000612df782614350565b90506000612e1682612e11670de0b6b3a76400008f615abc565b614538565b90506000612e248b83614322565b9050612e30818d615abc565b9f9e505050505050505050505050505050565b60028181548110612e5357600080fd5b60009182526020909120600590910201805460018201546002830154600384015460049094015463ffffffff8416955064010000000090930473ffffffffffffffffffffffffffffffffffffffff908116949216926fffffffffffffffffffffffffffffffff91821692918082169170010000000000000000000000000000000090041687565b60008054700100000000000000000000000000000000900460ff166002811115612f0657612f0661555f565b14612f3d576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028781548110612f5257612f526158d5565b6000918252602082206005919091020160048101549092506fffffffffffffffffffffffffffffffff16908715821760011b9050612fb17f00000000000000000000000000000000000000000000000000000000000000086001615933565b61304d826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1614613087576040517f5f53dd9800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080891561317e576130da7f00000000000000000000000000000000000000000000000000000000000000047f0000000000000000000000000000000000000000000000000000000000000008615983565b6001901b6130f9846fffffffffffffffffffffffffffffffff16614569565b6fffffffffffffffffffffffffffffffff166131159190615af9565b156131525761314961313a60016fffffffffffffffffffffffffffffffff8716615b0d565b865463ffffffff166000614608565b60030154613174565b7f00000000000000000000000000000000000000000000000000000000000000005b91508490506131a8565b600385015491506131a561313a6fffffffffffffffffffffffffffffffff86166001615b36565b90505b600882901b60088a8a6040516131bf9291906158c5565b6040518091039020901b14613200576040517f696550ff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061320b8c6146ec565b9050600061321a836003015490565b6040517fe14ced320000000000000000000000000000000000000000000000000000000081527f000000000000000000000000444e09fe6d839273316a87002ab0efbea6fe780673ffffffffffffffffffffffffffffffffffffffff169063e14ced3290613294908f908f908f908f908a90600401615baa565b6020604051808303816000875af11580156132b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132d791906159b7565b600485015491149150600090600290613382906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b61341e896fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b6134289190615be4565b6134329190615c07565b60ff161590508115158103613473576040517ffb4e40dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8754640100000000900473ffffffffffffffffffffffffffffffffffffffff16156134ca576040517f9071e6af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505085547fffffffffffffffff0000000000000000000000000000000000000000ffffffff163364010000000002179095555050505050505050505050565b60008054700100000000000000000000000000000000900460ff1660028111156135355761353561555f565b1461356c576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060008061357b8661471b565b9350935093509350600061359185858585614b24565b905060007f000000000000000000000000444e09fe6d839273316a87002ab0efbea6fe780673ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015613600573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613624919061599a565b90506001890361371c5773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a84613680367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036034013590565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815260048101939093526024830191909152604482015260206064820152608481018a905260a4015b6020604051808303816000875af11580156136f2573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061371691906159b7565b5061155b565b600289036137485773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a8489613680565b600389036137745773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a8487613680565b600489036138fb5760006137ba6fffffffffffffffffffffffffffffffff85167f0000000000000000000000000000000000000000000000000000000000000004614bde565b6009546137c79190615933565b6137d2906001615933565b9050367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900360540135811061383b57367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036054013561383d565b805b905073ffffffffffffffffffffffffffffffffffffffff82166352f0f3ad8b8560405160e084901b7fffffffff000000000000000000000000000000000000000000000000000000001681526004810192909252602482015260c084901b604482015260086064820152608481018b905260a4016020604051808303816000875af11580156138d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138f491906159b7565b505061155b565b60058903613994576040517f52f0f3ad000000000000000000000000000000000000000000000000000000008152600481018a9052602481018390527f000000000000000000000000000000000000000000000000000000000000038560c01b6044820152600860648201526084810188905273ffffffffffffffffffffffffffffffffffffffff8216906352f0f3ad9060a4016136d3565b6040517fff137e6500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000000367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003601401356060613a1f61188d565b9050909192565b600081831015613a365781613a38565b825b90505b92915050565b60008160000151826020015183604001518460600151604051602001613a80949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b60408051808201909152600080825260208201528151600003613aec576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50604080518082019091528151815260209182019181019190915290565b60606000806000613b1a85614c8c565b919450925090506001816001811115613b3557613b3561555f565b14613b6c576040517f4b9c6abe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8451613b788385615933565b14613baf576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516020808252610420820190925290816020015b6040805180820190915260008082526020820152815260200190600190039081613bc65790505093506000835b8651811015613cb457600080613c396040518060400160405280858c60000151613c1d9190615983565b8152602001858c60200151613c329190615933565b9052614c8c565b509150915060405180604001604052808383613c559190615933565b8152602001848b60200151613c6a9190615933565b815250888581518110613c7f57613c7f6158d5565b6020908102919091010152613c95600185615933565b9350613ca18183615933565b613cab9084615933565b92505050613bf3565b50845250919392505050565b60606000806000613cd085614c8c565b919450925090506000816001811115613ceb57613ceb61555f565b14613d22576040517f1ff9b2e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613d2c8284615933565b855114613d65576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6118848560200151848461512a565b600281015473ffffffffffffffffffffffffffffffffffffffff8316600090815260036020526040812080546fffffffffffffffffffffffffffffffff90931692839290613dc3908490615933565b90915550506040517f7eee288d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152602482018390527f000000000000000000000000ef179756ea6525afade217ca5ab0b1b5cfe0fd921690637eee288d90604401600060405180830381600087803b158015613e5857600080fd5b505af1158015613e6c573d6000803e3d6000fd5b50505050505050565b604051818152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90038284820160208401378260208301016000815260208101604052505092915050565b6000613ee66fffffffffffffffffffffffffffffffff84166001615b36565b90506000613ef682866001614608565b9050600086901a8380613fe25750613f2f60027f0000000000000000000000000000000000000000000000000000000000000004615af9565b6004830154600290613fd3906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b613fdd9190615c07565b60ff16145b1561403a5760ff811660011480613ffc575060ff81166002145b614035576040517ff40239db00000000000000000000000000000000000000000000000000000000815260048101889052602401612752565b613e6c565b60ff811615613e6c576040517ff40239db00000000000000000000000000000000000000000000000000000000815260048101889052602401612752565b6fffffffffffffffffffffffffffffffff811160071b81811c67ffffffffffffffff1060061b1781811c63ffffffff1060051b1781811c61ffff1060041b1781811c60ff1060031b17600082136140d757631615e6386000526004601cfd5b7ff8f9f9faf9fdfafbf9fdfcfdfafbfcfef9fafdfafcfcfbfefafafcfbffffffff6f8421084210842108cc6318c6db6d54be83831c1c601f161a1890811b609f90811c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506029190037d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b302017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d90565b60007812725dd1d243aba0e75fe645cc4873f9e65afe688c928e1f218311670de0b6b3a76400000215820261431057637c5f487d6000526004601cfd5b50670de0b6b3a7640000919091020490565b6000816000190483118202156143405763bac65e5b6000526004601cfd5b50670de0b6b3a764000091020490565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdc0d0570925a462d7821361437e57919050565b680755bf798b4a1bf1e5821261439c5763a37bfec96000526004601cfd5b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b6000613a38670de0b6b3a76400008361455086614078565b61455a9190615c29565b6145649190615ce5565b614350565b6000806145f6837e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b600160ff919091161b90920392915050565b600080826146515761464c6fffffffffffffffffffffffffffffffff86167f00000000000000000000000000000000000000000000000000000000000000046151bf565b61466c565b61466c856fffffffffffffffffffffffffffffffff1661534b565b905060028481548110614681576146816158d5565b906000526020600020906005020191505b60048201546fffffffffffffffffffffffffffffffff8281169116146146e457815460028054909163ffffffff169081106146cf576146cf6158d5565b90600052602060002090600502019150614692565b509392505050565b60008060008060006146fd8661471b565b935093509350935061471184848484614b24565b9695505050505050565b600080600080600085905060006002828154811061473b5761473b6158d5565b600091825260209091206004600590920201908101549091507f000000000000000000000000000000000000000000000000000000000000000490614812906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff161161484c576040517fb34b5c2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000815b60048301547f000000000000000000000000000000000000000000000000000000000000000490614913906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff16925082111561498857825463ffffffff166149527f00000000000000000000000000000000000000000000000000000000000000046001615933565b830361495c578391505b6002818154811061496f5761496f6158d5565b9060005260206000209060050201935080945050614850565b600481810154908401546fffffffffffffffffffffffffffffffff91821691166000816fffffffffffffffffffffffffffffffff166149f16149dc856fffffffffffffffffffffffffffffffff1660011c90565b6fffffffffffffffffffffffffffffffff1690565b6fffffffffffffffffffffffffffffffff161490508015614ac0576000614a29836fffffffffffffffffffffffffffffffff16614569565b6fffffffffffffffffffffffffffffffff161115614a94576000614a6b614a6360016fffffffffffffffffffffffffffffffff8616615b0d565b896001614608565b6003810154600490910154909c506fffffffffffffffffffffffffffffffff169a50614a9a9050565b6008549a505b600386015460048701549099506fffffffffffffffffffffffffffffffff169750614b16565b6000614ae2614a636fffffffffffffffffffffffffffffffff85166001615b36565b6003808901546004808b015492840154930154909e506fffffffffffffffffffffffffffffffff9182169d50919b50169850505b505050505050509193509193565b60006fffffffffffffffffffffffffffffffff841615614b915760408051602081018790526fffffffffffffffffffffffffffffffff8087169282019290925260608101859052908316608082015260a00160405160208183030381529060405280519060200120611884565b8282604051602001614bbf9291909182526fffffffffffffffffffffffffffffffff16602082015260400190565b6040516020818303038152906040528051906020012095945050505050565b600080614c6b847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1690508083036001841b600180831b0386831b17039250505092915050565b60008060008360000151600003614ccf576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020840151805160001a607f8111614cf4576000600160009450945094505050615123565b60b78111614e0a576000614d09608083615983565b905080876000015111614d48576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001838101517fff00000000000000000000000000000000000000000000000000000000000000169082148015614dc057507f80000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000008216105b15614df7576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5060019550935060009250615123915050565b60bf8111614f68576000614e1f60b783615983565b905080876000015111614e5e576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614ec0576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c60378111614f08576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614f128184615933565b895111614f4b576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614f56836001615933565b97509550600094506151239350505050565b60f78111614fcd576000614f7d60c083615983565b905080876000015111614fbc576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600195509350849250615123915050565b6000614fda60f783615983565b905080876000015111615019576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff0000000000000000000000000000000000000000000000000000000000000016600081900361507b576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c603781116150c3576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6150cd8184615933565b895111615106576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b615111836001615933565b97509550600194506151239350505050565b9193909250565b60608167ffffffffffffffff81111561514557615145615809565b6040519080825280601f01601f19166020018201604052801561516f576020820181803683370190505b50905081156151b85760006151848486615933565b90506020820160005b848110156151a557828101518282015260200161518d565b848111156151b4576000858301525b5050505b9392505050565b60008161525e846fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff16116152745763b34b5c226000526004601cfd5b61527d8361534b565b90508161531c826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1611613a3b57613a38615332836001615933565b6fffffffffffffffffffffffffffffffff8316906153f0565b600081196001830116816153df827e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169390931c8015179392505050565b60008061547d847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169050808303600180821b0385821b179250505092915050565b60008083601f8401126154ab57600080fd5b50813567ffffffffffffffff8111156154c357600080fd5b6020830191508360208285010111156154db57600080fd5b9250929050565b600080600083850360a08112156154f857600080fd5b608081121561550657600080fd5b50839250608084013567ffffffffffffffff81111561552457600080fd5b61553086828701615499565b9497909650939450505050565b6000806040838503121561555057600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60208101600383106155c9577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b6000806000606084860312156155e457600080fd5b505081359360208301359350604090920135919050565b6000815180845260005b8181101561562157602081850181015186830182015201615605565b81811115615633576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000613a3860208301846155fb565b60006020828403121561568b57600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff811681146156b457600080fd5b50565b6000602082840312156156c957600080fd5b81356151b881615692565b803580151581146156e457600080fd5b919050565b600080600080608085870312156156ff57600080fd5b84359350602085013592506040850135915061571d606086016156d4565b905092959194509250565b60006020828403121561573a57600080fd5b81356fffffffffffffffffffffffffffffffff811681146151b857600080fd5b6000806000806000806080878903121561577357600080fd5b86359550615783602088016156d4565b9450604087013567ffffffffffffffff808211156157a057600080fd5b6157ac8a838b01615499565b909650945060608901359150808211156157c557600080fd5b506157d289828a01615499565b979a9699509497509295939492505050565b63ffffffff8416815282602082015260606040820152600061188460608301846155fb565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006080828403121561584a57600080fd5b6040516080810181811067ffffffffffffffff82111715615894577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561594657615946615904565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361597c5761597c615904565b5060010190565b60008282101561599557615995615904565b500390565b6000602082840312156159ac57600080fd5b81516151b881615692565b6000602082840312156159c957600080fd5b5051919050565b600067ffffffffffffffff8083168185168083038211156159f3576159f3615904565b01949350505050565b600067ffffffffffffffff80831681851681830481118215151615615a2357615a23615904565b02949350505050565b600067ffffffffffffffff83811690831681811015615a4d57615a4d615904565b039392505050565b60008060408385031215615a6857600080fd5b505080516020909101519092909150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082615ab757615ab7615a79565b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615af457615af4615904565b500290565b600082615b0857615b08615a79565b500690565b60006fffffffffffffffffffffffffffffffff83811690831681811015615a4d57615a4d615904565b60006fffffffffffffffffffffffffffffffff8083168185168083038211156159f3576159f3615904565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b606081526000615bbe606083018789615b61565b8281036020840152615bd1818688615b61565b9150508260408301529695505050505050565b600060ff821660ff841680821015615bfe57615bfe615904565b90039392505050565b600060ff831680615c1a57615c1a615a79565b8060ff84160691505092915050565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600084136000841385830485118282161615615c6a57615c6a615904565b7f80000000000000000000000000000000000000000000000000000000000000006000871286820588128184161615615ca557615ca5615904565b60008712925087820587128484161615615cc157615cc1615904565b87850587128184161615615cd757615cd7615904565b505050929093029392505050565b600082615cf457615cf4615a79565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f800000000000000000000000000000000000000000000000000000000000000083141615615d4857615d48615904565b50059056fea164736f6c634300080f000a"; ++ hex"6080604052600436106102f25760003560e01c806370872aa51161018f578063c6f0308c116100e1578063ec5e63081161008a578063fa24f74311610064578063fa24f74314610b18578063fa315aa914610b3c578063fe2bbeb214610b6f57600080fd5b8063ec5e630814610a95578063eff0f59214610ac8578063f8f43ff614610af857600080fd5b8063d6ae3cd5116100bb578063d6ae3cd514610a0f578063d8cc1a3c14610a42578063dabd396d14610a6257600080fd5b8063c6f0308c14610937578063cf09e0d0146109c1578063d5d44d80146109e257600080fd5b80638d450a9511610143578063bcef3b551161011d578063bcef3b55146108b7578063bd8da956146108f7578063c395e1ca1461091757600080fd5b80638d450a9514610777578063a445ece6146107aa578063bbdc02db1461087657600080fd5b80638129fc1c116101745780638129fc1c1461071a5780638980e0cc146107225780638b85902b1461073757600080fd5b806370872aa5146106f25780637b0f0adc1461070757600080fd5b80633fc8cef3116102485780635c0cba33116101fc5780636361506d116101d65780636361506d1461066c5780636b6716c0146106ac5780636f034409146106df57600080fd5b80635c0cba3314610604578063609d33341461063757806360e274641461064c57600080fd5b806354fd4d501161022d57806354fd4d501461055e57806357da950e146105b45780635a5fa2d9146105e457600080fd5b80633fc8cef314610518578063472777c61461054b57600080fd5b80632810e1d6116102aa57806337b1b2291161028457806337b1b229146104655780633a768463146104a55780633e3ac912146104d857600080fd5b80632810e1d6146103de5780632ad69aeb146103f357806330dbe5701461041357600080fd5b806319effeb4116102db57806319effeb414610339578063200d2ed21461038457806325fc2ace146103bf57600080fd5b806301935130146102f757806303c2924d14610319575b600080fd5b34801561030357600080fd5b506103176103123660046154e2565b610b9f565b005b34801561032557600080fd5b5061031761033436600461553d565b610ec0565b34801561034557600080fd5b506000546103669068010000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020015b60405180910390f35b34801561039057600080fd5b506000546103b290700100000000000000000000000000000000900460ff1681565b60405161037b919061558e565b3480156103cb57600080fd5b506008545b60405190815260200161037b565b3480156103ea57600080fd5b506103b2611566565b3480156103ff57600080fd5b506103d061040e36600461553d565b61180b565b34801561041f57600080fd5b506001546104409073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161037b565b34801561047157600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90033560601c610440565b3480156104b157600080fd5b507f000000000000000000000000180cbe2ebb9f37d3a3c542ddc2546fd160555a73610440565b3480156104e457600080fd5b50600054610508907201000000000000000000000000000000000000900460ff1681565b604051901515815260200161037b565b34801561052457600080fd5b507f000000000000000000000000ef179756ea6525afade217ca5ab0b1b5cfe0fd92610440565b6103176105593660046155cf565b611841565b34801561056a57600080fd5b506105a76040518060400160405280600c81526020017f312e332e312d626574612e32000000000000000000000000000000000000000081525081565b60405161037b9190615666565b3480156105c057600080fd5b506008546009546105cf919082565b6040805192835260208301919091520161037b565b3480156105f057600080fd5b506103d06105ff366004615679565b611853565b34801561061057600080fd5b507f000000000000000000000000970670459734a83899773a0fd45941b5afc1200e610440565b34801561064357600080fd5b506105a761188d565b34801561065857600080fd5b506103176106673660046156b7565b61189b565b34801561067857600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003603401356103d0565b3480156106b857600080fd5b507f0000000000000000000000000000000000000000000000000000000000000000610366565b6103176106ed3660046156e9565b611a42565b3480156106fe57600080fd5b506009546103d0565b6103176107153660046155cf565b61251b565b610317612528565b34801561072e57600080fd5b506002546103d0565b34801561074357600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401356103d0565b34801561078357600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006103d0565b3480156107b657600080fd5b506108226107c5366004615679565b6007602052600090815260409020805460019091015460ff821691610100810463ffffffff1691650100000000009091046fffffffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff1684565b60408051941515855263ffffffff90931660208501526fffffffffffffffffffffffffffffffff9091169183019190915273ffffffffffffffffffffffffffffffffffffffff16606082015260800161037b565b34801561088257600080fd5b5060405163ffffffff7f000000000000000000000000000000000000000000000000000000000000000016815260200161037b565b3480156108c357600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003601401356103d0565b34801561090357600080fd5b50610366610912366004615679565b612a81565b34801561092357600080fd5b506103d0610932366004615728565b612c60565b34801561094357600080fd5b50610957610952366004615679565b612e43565b6040805163ffffffff909816885273ffffffffffffffffffffffffffffffffffffffff968716602089015295909416948601949094526fffffffffffffffffffffffffffffffff9182166060860152608085015291821660a08401521660c082015260e00161037b565b3480156109cd57600080fd5b506000546103669067ffffffffffffffff1681565b3480156109ee57600080fd5b506103d06109fd3660046156b7565b60036020526000908152604090205481565b348015610a1b57600080fd5b507f00000000000000000000000000000000000000000000000000000000000003856103d0565b348015610a4e57600080fd5b50610317610a5d36600461575a565b612eda565b348015610a6e57600080fd5b507f00000000000000000000000000000000000000000000000000000000000004b0610366565b348015610aa157600080fd5b507f00000000000000000000000000000000000000000000000000000000000000046103d0565b348015610ad457600080fd5b50610508610ae3366004615679565b60046020526000908152604090205460ff1681565b348015610b0457600080fd5b50610317610b133660046155cf565b613509565b348015610b2457600080fd5b50610b2d6139c6565b60405161037b939291906157e4565b348015610b4857600080fd5b507f00000000000000000000000000000000000000000000000000000000000000086103d0565b348015610b7b57600080fd5b50610508610b8a366004615679565b60066020526000908152604090205460ff1681565b60008054700100000000000000000000000000000000900460ff166002811115610bcb57610bcb61555f565b14610c02576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000547201000000000000000000000000000000000000900460ff1615610c55576040517f0ea2e75200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610c8c367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013590565b90565b610ca3610c9e36869003860186615838565b613a41565b14610cda576040517f9cc00b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82606001358282604051610cef9291906158c5565b604051809103902014610d2e576040517fd81d583b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610d77610d7284848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613a9d92505050565b613b0a565b90506000610d9e82600881518110610d9157610d916158d5565b6020026020010151613cc0565b9050602081511115610ddc576040517fd81d583b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602081810151825190910360031b1c367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401358103610e51576040517fb8ed883000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050600180547fffffffffffffffffffffffff000000000000000000000000000000000000000016331790555050600080547fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff1672010000000000000000000000000000000000001790555050565b60008054700100000000000000000000000000000000900460ff166002811115610eec57610eec61555f565b14610f23576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028381548110610f3857610f386158d5565b906000526020600020906005020190506000610f5384612a81565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b081169082161015610fbc576040517ff2440b5300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008481526006602052604090205460ff1615611005576040517ff1a9458100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600084815260056020526040902080548015801561102257508515155b156110bd578354640100000000900473ffffffffffffffffffffffffffffffffffffffff16600081156110555781611071565b600186015473ffffffffffffffffffffffffffffffffffffffff165b905061107d8187613d74565b50505060009485525050600660205250506040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b6000868152600760209081526040918290208251608081018452815460ff81161515808352610100820463ffffffff16948301949094526501000000000090046fffffffffffffffffffffffffffffffff16938101939093526001015473ffffffffffffffffffffffffffffffffffffffff166060830152611160576fffffffffffffffffffffffffffffffff6040820152600181526000869003611160578195505b600086826020015163ffffffff166111789190615933565b90506000838211611189578161118b565b835b602084015190915063ffffffff165b818110156112d75760008682815481106111b6576111b66158d5565b6000918252602080832090910154808352600690915260409091205490915060ff1661120e576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028281548110611223576112236158d5565b600091825260209091206005909102018054909150640100000000900473ffffffffffffffffffffffffffffffffffffffff161580156112805750600481015460408701516fffffffffffffffffffffffffffffffff9182169116115b156112c257600181015473ffffffffffffffffffffffffffffffffffffffff16606087015260048101546fffffffffffffffffffffffffffffffff1660408701525b505080806112cf9061594b565b91505061119a565b5063ffffffff818116602085810191825260008c81526007909152604090819020865181549351928801517fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009094169015157fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ff161761010092909416918202939093177fffffffffffffffffffffff00000000000000000000000000000000ffffffffff16650100000000006fffffffffffffffffffffffffffffffff909316929092029190911782556060850151600190920180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9093169290921790915584900361155b57606083015160008a815260066020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558915801561145757506000547201000000000000000000000000000000000000900460ff165b156114cc5760015473ffffffffffffffffffffffffffffffffffffffff1661147f818a613d74565b885473ffffffffffffffffffffffffffffffffffffffff909116640100000000027fffffffffffffffff0000000000000000000000000000000000000000ffffffff909116178855611559565b61151373ffffffffffffffffffffffffffffffffffffffff8216156114f1578161150d565b600189015473ffffffffffffffffffffffffffffffffffffffff165b89613d74565b87547fffffffffffffffff0000000000000000000000000000000000000000ffffffff1664010000000073ffffffffffffffffffffffffffffffffffffffff8316021788555b505b505050505050505050565b600080600054700100000000000000000000000000000000900460ff1660028111156115945761159461555f565b146115cb576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000805260066020527f54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4f85460ff1661162f576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600260008154811061165b5761165b6158d5565b6000918252602090912060059091020154640100000000900473ffffffffffffffffffffffffffffffffffffffff1614611696576001611699565b60025b6000805467ffffffffffffffff421668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff82168117835592935083927fffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffff000000000000000000ffffffffffffffff9091161770010000000000000000000000000000000083600281111561174a5761174a61555f565b02179055600281111561175f5761175f61555f565b6040517f5e186f09b9c93491f14e277eea7faa5de6a2d4bda75a79af7a3684fbfb42da6090600090a27f000000000000000000000000970670459734a83899773a0fd45941b5afc1200e73ffffffffffffffffffffffffffffffffffffffff1663838c2d1e6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156117f057600080fd5b505af1158015611804573d6000803e3d6000fd5b5050505090565b6005602052816000526040600020818154811061182757600080fd5b90600052602060002001600091509150505481565b905090565b61184e8383836001611a42565b505050565b6000818152600760209081526040808320600590925282208054825461188490610100900463ffffffff1682615983565b95945050505050565b606061183c60546020613e75565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260036020526040812080549082905590819003611900576040517f17bfe5f700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517ff3fef3a300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152602482018390527f000000000000000000000000ef179756ea6525afade217ca5ab0b1b5cfe0fd92169063f3fef3a390604401600060405180830381600087803b15801561199057600080fd5b505af11580156119a4573d6000803e3d6000fd5b5050505060008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114611a02576040519150601f19603f3d011682016040523d82523d6000602084013e611a07565b606091505b505090508061184e576040517f83e6cc6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008054700100000000000000000000000000000000900460ff166002811115611a6e57611a6e61555f565b14611aa5576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028481548110611aba57611aba6158d5565b60009182526020918290206040805160e0810182526005909302909101805463ffffffff8116845273ffffffffffffffffffffffffffffffffffffffff64010000000090910481169484019490945260018101549093169082015260028201546fffffffffffffffffffffffffffffffff908116606083015260038301546080830181905260049093015480821660a084015270010000000000000000000000000000000090041660c082015291508514611ba1576040517f3014033200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60a0810151600083156fffffffffffffffffffffffffffffffff83161760011b90506000611c61826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169050861580611c9c5750611c997f00000000000000000000000000000000000000000000000000000000000000046002615933565b81145b8015611ca6575084155b15611cdd576040517fa42637bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000547201000000000000000000000000000000000000900460ff168015611d03575086155b15611d3a576040517f0ea2e75200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000008811115611d94576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611dbf7f00000000000000000000000000000000000000000000000000000000000000046001615933565b8103611dd157611dd186888588613ec7565b34611ddb83612c60565b14611e12576040517f8620aa1900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611e1d88612a81565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b0811690821603611e85576040517f3381d11400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611eb260017f0000000000000000000000000000000000000000000000000000000000000008615983565b8303611ff0577f000000000000000000000000180cbe2ebb9f37d3a3c542ddc2546fd160555a7373ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f47919061599a565b73ffffffffffffffffffffffffffffffffffffffff1663f3f480d96040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f91573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fb591906159b7565b611fe9907f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff166159d0565b9050612083565b61201b60017f0000000000000000000000000000000000000000000000000000000000000004615983565b830361205657611fe97f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1660026159fc565b507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff165b6120b7817f00000000000000000000000000000000000000000000000000000000000004b067ffffffffffffffff16615a2c565b67ffffffffffffffff166120d28367ffffffffffffffff1690565b67ffffffffffffffff16111561211957612116817f00000000000000000000000000000000000000000000000000000000000004b067ffffffffffffffff16615a2c565b91505b6000604083901b421760008a8152608087901b6fffffffffffffffffffffffffffffffff8d1617602052604081209192509060008181526004602052604090205490915060ff1615612197576040517f80497e3b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60016004600083815260200190815260200160002060006101000a81548160ff02191690831515021790555060026040518060e001604052808d63ffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020013373ffffffffffffffffffffffffffffffffffffffff168152602001346fffffffffffffffffffffffffffffffff1681526020018c8152602001886fffffffffffffffffffffffffffffffff168152602001846fffffffffffffffffffffffffffffffff16815250908060018154018082558091505060019003906000526020600020906005020160009091909190915060008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060608201518160020160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055506080820151816003015560a08201518160040160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555060c08201518160040160106101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055505050600560008c8152602001908152602001600020600160028054905061242d9190615983565b81546001810183556000928352602083200155604080517fd0e30db0000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000ef179756ea6525afade217ca5ab0b1b5cfe0fd92169263d0e30db09234926004808301939282900301818588803b1580156124c557600080fd5b505af11580156124d9573d6000803e3d6000fd5b50506040513393508d92508e91507f9b3245740ec3b155098a55be84957a4da13eaf7f14a8bc6f53126c0b9350f2be90600090a4505050505050505050505050565b61184e8383836000611a42565b60005471010000000000000000000000000000000000900460ff161561257a576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f7258a80700000000000000000000000000000000000000000000000000000000815263ffffffff7f0000000000000000000000000000000000000000000000000000000000000000166004820152600090819073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000970670459734a83899773a0fd45941b5afc1200e1690637258a807906024016040805180830381865afa15801561262e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126529190615a55565b90925090508161268e576040517f6a6bc3b200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080518082019091528281526020018190526008829055600981905536607a146126c157639824bdab6000526004601cfd5b80367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401351161275b576040517ff40239db000000000000000000000000000000000000000000000000000000008152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013560048201526024015b60405180910390fd5b6040805160e08101825263ffffffff8082526000602083018181527ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe369081013560f01c90038035606090811c868801908152346fffffffffffffffffffffffffffffffff81811693890193845260149094013560808901908152600160a08a0181815242871660c08c019081526002805493840181558a529a5160059092027f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace81018054995173ffffffffffffffffffffffffffffffffffffffff908116640100000000027fffffffffffffffff000000000000000000000000000000000000000000000000909b1694909c16939093179890981790915592517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5acf87018054918a167fffffffffffffffffffffffff000000000000000000000000000000000000000090921691909117905592517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad0860180549186167fffffffffffffffffffffffffffffffff0000000000000000000000000000000090921691909117905591517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad185015551955182167001000000000000000000000000000000000295909116949094177f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad29091015580547fffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffff167101000000000000000000000000000000000017815583517fd0e30db000000000000000000000000000000000000000000000000000000000815293517f000000000000000000000000ef179756ea6525afade217ca5ab0b1b5cfe0fd929092169363d0e30db093926004828101939282900301818588803b158015612a3057600080fd5b505af1158015612a44573d6000803e3d6000fd5b5050600080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000164267ffffffffffffffff161790555050505050565b600080600054700100000000000000000000000000000000900460ff166002811115612aaf57612aaf61555f565b14612ae6576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028381548110612afb57612afb6158d5565b600091825260208220600590910201805490925063ffffffff90811614612b6a57815460028054909163ffffffff16908110612b3957612b396158d5565b906000526020600020906005020160040160109054906101000a90046fffffffffffffffffffffffffffffffff1690505b6004820154600090612ba290700100000000000000000000000000000000900467ffffffffffffffff165b67ffffffffffffffff1690565b612bb69067ffffffffffffffff1642615983565b612bd5612b95846fffffffffffffffffffffffffffffffff1660401c90565b67ffffffffffffffff16612be99190615933565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b01667ffffffffffffffff168167ffffffffffffffff1611612c365780611884565b7f00000000000000000000000000000000000000000000000000000000000004b095945050505050565b600080612cff836fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1690507f0000000000000000000000000000000000000000000000000000000000000008811115612d5e576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b642e90edd00062061a806311e1a3006000612d798383615aa8565b9050670de0b6b3a76400006000612db0827f0000000000000000000000000000000000000000000000000000000000000008615abc565b90506000612dce612dc9670de0b6b3a764000086615abc565b614078565b90506000612ddc84846142d3565b90506000612dea8383614322565b90506000612df782614350565b90506000612e1682612e11670de0b6b3a76400008f615abc565b614538565b90506000612e248b83614322565b9050612e30818d615abc565b9f9e505050505050505050505050505050565b60028181548110612e5357600080fd5b60009182526020909120600590910201805460018201546002830154600384015460049094015463ffffffff8416955064010000000090930473ffffffffffffffffffffffffffffffffffffffff908116949216926fffffffffffffffffffffffffffffffff91821692918082169170010000000000000000000000000000000090041687565b60008054700100000000000000000000000000000000900460ff166002811115612f0657612f0661555f565b14612f3d576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028781548110612f5257612f526158d5565b6000918252602082206005919091020160048101549092506fffffffffffffffffffffffffffffffff16908715821760011b9050612fb17f00000000000000000000000000000000000000000000000000000000000000086001615933565b61304d826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1614613087576040517f5f53dd9800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080891561317e576130da7f00000000000000000000000000000000000000000000000000000000000000047f0000000000000000000000000000000000000000000000000000000000000008615983565b6001901b6130f9846fffffffffffffffffffffffffffffffff16614569565b6fffffffffffffffffffffffffffffffff166131159190615af9565b156131525761314961313a60016fffffffffffffffffffffffffffffffff8716615b0d565b865463ffffffff166000614608565b60030154613174565b7f00000000000000000000000000000000000000000000000000000000000000005b91508490506131a8565b600385015491506131a561313a6fffffffffffffffffffffffffffffffff86166001615b36565b90505b600882901b60088a8a6040516131bf9291906158c5565b6040518091039020901b14613200576040517f696550ff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061320b8c6146ec565b9050600061321a836003015490565b6040517fe14ced320000000000000000000000000000000000000000000000000000000081527f000000000000000000000000180cbe2ebb9f37d3a3c542ddc2546fd160555a7373ffffffffffffffffffffffffffffffffffffffff169063e14ced3290613294908f908f908f908f908a90600401615baa565b6020604051808303816000875af11580156132b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132d791906159b7565b600485015491149150600090600290613382906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b61341e896fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b6134289190615be4565b6134329190615c07565b60ff161590508115158103613473576040517ffb4e40dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8754640100000000900473ffffffffffffffffffffffffffffffffffffffff16156134ca576040517f9071e6af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505085547fffffffffffffffff0000000000000000000000000000000000000000ffffffff163364010000000002179095555050505050505050505050565b60008054700100000000000000000000000000000000900460ff1660028111156135355761353561555f565b1461356c576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060008061357b8661471b565b9350935093509350600061359185858585614b24565b905060007f000000000000000000000000180cbe2ebb9f37d3a3c542ddc2546fd160555a7373ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015613600573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613624919061599a565b90506001890361371c5773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a84613680367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036034013590565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815260048101939093526024830191909152604482015260206064820152608481018a905260a4015b6020604051808303816000875af11580156136f2573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061371691906159b7565b5061155b565b600289036137485773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a8489613680565b600389036137745773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a8487613680565b600489036138fb5760006137ba6fffffffffffffffffffffffffffffffff85167f0000000000000000000000000000000000000000000000000000000000000004614bde565b6009546137c79190615933565b6137d2906001615933565b9050367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900360540135811061383b57367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036054013561383d565b805b905073ffffffffffffffffffffffffffffffffffffffff82166352f0f3ad8b8560405160e084901b7fffffffff000000000000000000000000000000000000000000000000000000001681526004810192909252602482015260c084901b604482015260086064820152608481018b905260a4016020604051808303816000875af11580156138d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138f491906159b7565b505061155b565b60058903613994576040517f52f0f3ad000000000000000000000000000000000000000000000000000000008152600481018a9052602481018390527f000000000000000000000000000000000000000000000000000000000000038560c01b6044820152600860648201526084810188905273ffffffffffffffffffffffffffffffffffffffff8216906352f0f3ad9060a4016136d3565b6040517fff137e6500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000000367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003601401356060613a1f61188d565b9050909192565b600081831015613a365781613a38565b825b90505b92915050565b60008160000151826020015183604001518460600151604051602001613a80949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b60408051808201909152600080825260208201528151600003613aec576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50604080518082019091528151815260209182019181019190915290565b60606000806000613b1a85614c8c565b919450925090506001816001811115613b3557613b3561555f565b14613b6c576040517f4b9c6abe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8451613b788385615933565b14613baf576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516020808252610420820190925290816020015b6040805180820190915260008082526020820152815260200190600190039081613bc65790505093506000835b8651811015613cb457600080613c396040518060400160405280858c60000151613c1d9190615983565b8152602001858c60200151613c329190615933565b9052614c8c565b509150915060405180604001604052808383613c559190615933565b8152602001848b60200151613c6a9190615933565b815250888581518110613c7f57613c7f6158d5565b6020908102919091010152613c95600185615933565b9350613ca18183615933565b613cab9084615933565b92505050613bf3565b50845250919392505050565b60606000806000613cd085614c8c565b919450925090506000816001811115613ceb57613ceb61555f565b14613d22576040517f1ff9b2e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613d2c8284615933565b855114613d65576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6118848560200151848461512a565b600281015473ffffffffffffffffffffffffffffffffffffffff8316600090815260036020526040812080546fffffffffffffffffffffffffffffffff90931692839290613dc3908490615933565b90915550506040517f7eee288d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152602482018390527f000000000000000000000000ef179756ea6525afade217ca5ab0b1b5cfe0fd921690637eee288d90604401600060405180830381600087803b158015613e5857600080fd5b505af1158015613e6c573d6000803e3d6000fd5b50505050505050565b604051818152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90038284820160208401378260208301016000815260208101604052505092915050565b6000613ee66fffffffffffffffffffffffffffffffff84166001615b36565b90506000613ef682866001614608565b9050600086901a8380613fe25750613f2f60027f0000000000000000000000000000000000000000000000000000000000000004615af9565b6004830154600290613fd3906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b613fdd9190615c07565b60ff16145b1561403a5760ff811660011480613ffc575060ff81166002145b614035576040517ff40239db00000000000000000000000000000000000000000000000000000000815260048101889052602401612752565b613e6c565b60ff811615613e6c576040517ff40239db00000000000000000000000000000000000000000000000000000000815260048101889052602401612752565b6fffffffffffffffffffffffffffffffff811160071b81811c67ffffffffffffffff1060061b1781811c63ffffffff1060051b1781811c61ffff1060041b1781811c60ff1060031b17600082136140d757631615e6386000526004601cfd5b7ff8f9f9faf9fdfafbf9fdfcfdfafbfcfef9fafdfafcfcfbfefafafcfbffffffff6f8421084210842108cc6318c6db6d54be83831c1c601f161a1890811b609f90811c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506029190037d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b302017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d90565b60007812725dd1d243aba0e75fe645cc4873f9e65afe688c928e1f218311670de0b6b3a76400000215820261431057637c5f487d6000526004601cfd5b50670de0b6b3a7640000919091020490565b6000816000190483118202156143405763bac65e5b6000526004601cfd5b50670de0b6b3a764000091020490565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdc0d0570925a462d7821361437e57919050565b680755bf798b4a1bf1e5821261439c5763a37bfec96000526004601cfd5b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b6000613a38670de0b6b3a76400008361455086614078565b61455a9190615c29565b6145649190615ce5565b614350565b6000806145f6837e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b600160ff919091161b90920392915050565b600080826146515761464c6fffffffffffffffffffffffffffffffff86167f00000000000000000000000000000000000000000000000000000000000000046151bf565b61466c565b61466c856fffffffffffffffffffffffffffffffff1661534b565b905060028481548110614681576146816158d5565b906000526020600020906005020191505b60048201546fffffffffffffffffffffffffffffffff8281169116146146e457815460028054909163ffffffff169081106146cf576146cf6158d5565b90600052602060002090600502019150614692565b509392505050565b60008060008060006146fd8661471b565b935093509350935061471184848484614b24565b9695505050505050565b600080600080600085905060006002828154811061473b5761473b6158d5565b600091825260209091206004600590920201908101549091507f000000000000000000000000000000000000000000000000000000000000000490614812906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff161161484c576040517fb34b5c2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000815b60048301547f000000000000000000000000000000000000000000000000000000000000000490614913906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff16925082111561498857825463ffffffff166149527f00000000000000000000000000000000000000000000000000000000000000046001615933565b830361495c578391505b6002818154811061496f5761496f6158d5565b9060005260206000209060050201935080945050614850565b600481810154908401546fffffffffffffffffffffffffffffffff91821691166000816fffffffffffffffffffffffffffffffff166149f16149dc856fffffffffffffffffffffffffffffffff1660011c90565b6fffffffffffffffffffffffffffffffff1690565b6fffffffffffffffffffffffffffffffff161490508015614ac0576000614a29836fffffffffffffffffffffffffffffffff16614569565b6fffffffffffffffffffffffffffffffff161115614a94576000614a6b614a6360016fffffffffffffffffffffffffffffffff8616615b0d565b896001614608565b6003810154600490910154909c506fffffffffffffffffffffffffffffffff169a50614a9a9050565b6008549a505b600386015460048701549099506fffffffffffffffffffffffffffffffff169750614b16565b6000614ae2614a636fffffffffffffffffffffffffffffffff85166001615b36565b6003808901546004808b015492840154930154909e506fffffffffffffffffffffffffffffffff9182169d50919b50169850505b505050505050509193509193565b60006fffffffffffffffffffffffffffffffff841615614b915760408051602081018790526fffffffffffffffffffffffffffffffff8087169282019290925260608101859052908316608082015260a00160405160208183030381529060405280519060200120611884565b8282604051602001614bbf9291909182526fffffffffffffffffffffffffffffffff16602082015260400190565b6040516020818303038152906040528051906020012095945050505050565b600080614c6b847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1690508083036001841b600180831b0386831b17039250505092915050565b60008060008360000151600003614ccf576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020840151805160001a607f8111614cf4576000600160009450945094505050615123565b60b78111614e0a576000614d09608083615983565b905080876000015111614d48576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001838101517fff00000000000000000000000000000000000000000000000000000000000000169082148015614dc057507f80000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000008216105b15614df7576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5060019550935060009250615123915050565b60bf8111614f68576000614e1f60b783615983565b905080876000015111614e5e576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614ec0576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c60378111614f08576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614f128184615933565b895111614f4b576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614f56836001615933565b97509550600094506151239350505050565b60f78111614fcd576000614f7d60c083615983565b905080876000015111614fbc576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600195509350849250615123915050565b6000614fda60f783615983565b905080876000015111615019576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff0000000000000000000000000000000000000000000000000000000000000016600081900361507b576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c603781116150c3576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6150cd8184615933565b895111615106576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b615111836001615933565b97509550600194506151239350505050565b9193909250565b60608167ffffffffffffffff81111561514557615145615809565b6040519080825280601f01601f19166020018201604052801561516f576020820181803683370190505b50905081156151b85760006151848486615933565b90506020820160005b848110156151a557828101518282015260200161518d565b848111156151b4576000858301525b5050505b9392505050565b60008161525e846fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff16116152745763b34b5c226000526004601cfd5b61527d8361534b565b90508161531c826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1611613a3b57613a38615332836001615933565b6fffffffffffffffffffffffffffffffff8316906153f0565b600081196001830116816153df827e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169390931c8015179392505050565b60008061547d847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169050808303600180821b0385821b179250505092915050565b60008083601f8401126154ab57600080fd5b50813567ffffffffffffffff8111156154c357600080fd5b6020830191508360208285010111156154db57600080fd5b9250929050565b600080600083850360a08112156154f857600080fd5b608081121561550657600080fd5b50839250608084013567ffffffffffffffff81111561552457600080fd5b61553086828701615499565b9497909650939450505050565b6000806040838503121561555057600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60208101600383106155c9577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b6000806000606084860312156155e457600080fd5b505081359360208301359350604090920135919050565b6000815180845260005b8181101561562157602081850181015186830182015201615605565b81811115615633576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000613a3860208301846155fb565b60006020828403121561568b57600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff811681146156b457600080fd5b50565b6000602082840312156156c957600080fd5b81356151b881615692565b803580151581146156e457600080fd5b919050565b600080600080608085870312156156ff57600080fd5b84359350602085013592506040850135915061571d606086016156d4565b905092959194509250565b60006020828403121561573a57600080fd5b81356fffffffffffffffffffffffffffffffff811681146151b857600080fd5b6000806000806000806080878903121561577357600080fd5b86359550615783602088016156d4565b9450604087013567ffffffffffffffff808211156157a057600080fd5b6157ac8a838b01615499565b909650945060608901359150808211156157c557600080fd5b506157d289828a01615499565b979a9699509497509295939492505050565b63ffffffff8416815282602082015260606040820152600061188460608301846155fb565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006080828403121561584a57600080fd5b6040516080810181811067ffffffffffffffff82111715615894577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561594657615946615904565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361597c5761597c615904565b5060010190565b60008282101561599557615995615904565b500390565b6000602082840312156159ac57600080fd5b81516151b881615692565b6000602082840312156159c957600080fd5b5051919050565b600067ffffffffffffffff8083168185168083038211156159f3576159f3615904565b01949350505050565b600067ffffffffffffffff80831681851681830481118215151615615a2357615a23615904565b02949350505050565b600067ffffffffffffffff83811690831681811015615a4d57615a4d615904565b039392505050565b60008060408385031215615a6857600080fd5b505080516020909101519092909150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082615ab757615ab7615a79565b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615af457615af4615904565b500290565b600082615b0857615b08615a79565b500690565b60006fffffffffffffffffffffffffffffffff83811690831681811015615a4d57615a4d615904565b60006fffffffffffffffffffffffffffffffff8083168185168083038211156159f3576159f3615904565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b606081526000615bbe606083018789615b61565b8281036020840152615bd1818688615b61565b9150508260408301529695505050505050565b600060ff821660ff841680821015615bfe57615bfe615904565b90039392505050565b600060ff831680615c1a57615c1a615a79565b8060ff84160691505092915050565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600084136000841385830485118282161615615c6a57615c6a615904565b7f80000000000000000000000000000000000000000000000000000000000000006000871286820588128184161615615ca557615ca5615904565b60008712925087820587128484161615615cc157615cc1615904565b87850587128184161615615cd757615cd7615904565b505050929093029392505050565b600082615cf457615cf4615a79565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f800000000000000000000000000000000000000000000000000000000000000083141615615d4857615d48615904565b50059056fea164736f6c634300080f000a"; + bytes internal constant acc34Code = +- hex"6080604052600436106103085760003560e01c806370872aa51161019a578063c6f0308c116100e1578063ec5e63081161008a578063fa24f74311610064578063fa24f74314610b94578063fa315aa914610bb8578063fe2bbeb214610beb57600080fd5b8063ec5e630814610b11578063eff0f59214610b44578063f8f43ff614610b7457600080fd5b8063d6ae3cd5116100bb578063d6ae3cd514610a8b578063d8cc1a3c14610abe578063dabd396d14610ade57600080fd5b8063c6f0308c146109b3578063cf09e0d014610a3d578063d5d44d8014610a5e57600080fd5b8063a445ece611610143578063bcef3b551161011d578063bcef3b5514610933578063bd8da95614610973578063c395e1ca1461099357600080fd5b8063a445ece6146107f3578063a8e4fb90146108bf578063bbdc02db146108f257600080fd5b80638980e0cc116101745780638980e0cc1461076b5780638b85902b146107805780638d450a95146107c057600080fd5b806370872aa51461073b5780637b0f0adc146107505780638129fc1c1461076357600080fd5b80633fc8cef31161025e5780635c0cba33116102075780636361506d116101e15780636361506d146106b55780636b6716c0146106f55780636f0344091461072857600080fd5b80635c0cba331461064d578063609d33341461068057806360e274641461069557600080fd5b806354fd4d501161023857806354fd4d50146105a757806357da950e146105fd5780635a5fa2d91461062d57600080fd5b80633fc8cef31461052e578063472777c614610561578063534db0e21461057457600080fd5b80632810e1d6116102c057806337b1b2291161029a57806337b1b2291461047b5780633a768463146104bb5780633e3ac912146104ee57600080fd5b80632810e1d6146103f45780632ad69aeb1461040957806330dbe5701461042957600080fd5b806319effeb4116102f157806319effeb41461034f578063200d2ed21461039a57806325fc2ace146103d557600080fd5b8063019351301461030d57806303c2924d1461032f575b600080fd5b34801561031957600080fd5b5061032d61032836600461575d565b610c1b565b005b34801561033b57600080fd5b5061032d61034a3660046157b8565b610f3c565b34801561035b57600080fd5b5060005461037c9068010000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020015b60405180910390f35b3480156103a657600080fd5b506000546103c890700100000000000000000000000000000000900460ff1681565b6040516103919190615809565b3480156103e157600080fd5b506008545b604051908152602001610391565b34801561040057600080fd5b506103c86115e2565b34801561041557600080fd5b506103e66104243660046157b8565b611887565b34801561043557600080fd5b506001546104569073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610391565b34801561048757600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90033560601c610456565b3480156104c757600080fd5b507f000000000000000000000000444e09fe6d839273316a87002ab0efbea6fe7806610456565b3480156104fa57600080fd5b5060005461051e907201000000000000000000000000000000000000900460ff1681565b6040519015158152602001610391565b34801561053a57600080fd5b507f000000000000000000000000d6eaf4c146261653ee059077b78ed088add54309610456565b61032d61056f36600461584a565b6118bd565b34801561058057600080fd5b507f0000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b63610456565b3480156105b357600080fd5b506105f06040518060400160405280600a81526020017f312e332e302d72632e310000000000000000000000000000000000000000000081525081565b60405161039191906158e1565b34801561060957600080fd5b50600854600954610618919082565b60408051928352602083019190915201610391565b34801561063957600080fd5b506103e66106483660046158f4565b6118cf565b34801561065957600080fd5b507f000000000000000000000000970670459734a83899773a0fd45941b5afc1200e610456565b34801561068c57600080fd5b506105f0611909565b3480156106a157600080fd5b5061032d6106b0366004615932565b611917565b3480156106c157600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003603401356103e6565b34801561070157600080fd5b507f000000000000000000000000000000000000000000000000000000000000000061037c565b61032d610736366004615964565b611abe565b34801561074757600080fd5b506009546103e6565b61032d61075e36600461584a565b611b7f565b61032d611b8c565b34801561077757600080fd5b506002546103e6565b34801561078c57600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401356103e6565b3480156107cc57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006103e6565b3480156107ff57600080fd5b5061086b61080e3660046158f4565b6007602052600090815260409020805460019091015460ff821691610100810463ffffffff1691650100000000009091046fffffffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff1684565b60408051941515855263ffffffff90931660208501526fffffffffffffffffffffffffffffffff9091169183019190915273ffffffffffffffffffffffffffffffffffffffff166060820152608001610391565b3480156108cb57600080fd5b507f00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8610456565b3480156108fe57600080fd5b5060405163ffffffff7f0000000000000000000000000000000000000000000000000000000000000001168152602001610391565b34801561093f57600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003601401356103e6565b34801561097f57600080fd5b5061037c61098e3660046158f4565b611c05565b34801561099f57600080fd5b506103e66109ae3660046159a3565b611de4565b3480156109bf57600080fd5b506109d36109ce3660046158f4565b611fc7565b6040805163ffffffff909816885273ffffffffffffffffffffffffffffffffffffffff968716602089015295909416948601949094526fffffffffffffffffffffffffffffffff9182166060860152608085015291821660a08401521660c082015260e001610391565b348015610a4957600080fd5b5060005461037c9067ffffffffffffffff1681565b348015610a6a57600080fd5b506103e6610a79366004615932565b60036020526000908152604090205481565b348015610a9757600080fd5b507f00000000000000000000000000000000000000000000000000000000000003856103e6565b348015610aca57600080fd5b5061032d610ad93660046159d5565b61205e565b348015610aea57600080fd5b507f00000000000000000000000000000000000000000000000000000000000004b061037c565b348015610b1d57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000046103e6565b348015610b5057600080fd5b5061051e610b5f3660046158f4565b60046020526000908152604090205460ff1681565b348015610b8057600080fd5b5061032d610b8f36600461584a565b612123565b348015610ba057600080fd5b50610ba96125e0565b60405161039193929190615a5f565b348015610bc457600080fd5b507f00000000000000000000000000000000000000000000000000000000000000086103e6565b348015610bf757600080fd5b5061051e610c063660046158f4565b60066020526000908152604090205460ff1681565b60008054700100000000000000000000000000000000900460ff166002811115610c4757610c476157da565b14610c7e576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000547201000000000000000000000000000000000000900460ff1615610cd1576040517f0ea2e75200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d08367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013590565b90565b610d1f610d1a36869003860186615ab3565b61265b565b14610d56576040517f9cc00b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82606001358282604051610d6b929190615b40565b604051809103902014610daa576040517fd81d583b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610df3610dee84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506126b792505050565b612724565b90506000610e1a82600881518110610e0d57610e0d615b50565b60200260200101516128da565b9050602081511115610e58576040517fd81d583b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602081810151825190910360031b1c367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401358103610ecd576040517fb8ed883000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050600180547fffffffffffffffffffffffff000000000000000000000000000000000000000016331790555050600080547fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff1672010000000000000000000000000000000000001790555050565b60008054700100000000000000000000000000000000900460ff166002811115610f6857610f686157da565b14610f9f576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028381548110610fb457610fb4615b50565b906000526020600020906005020190506000610fcf84611c05565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b081169082161015611038576040517ff2440b5300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008481526006602052604090205460ff1615611081576040517ff1a9458100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600084815260056020526040902080548015801561109e57508515155b15611139578354640100000000900473ffffffffffffffffffffffffffffffffffffffff16600081156110d157816110ed565b600186015473ffffffffffffffffffffffffffffffffffffffff165b90506110f9818761298e565b50505060009485525050600660205250506040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b6000868152600760209081526040918290208251608081018452815460ff81161515808352610100820463ffffffff16948301949094526501000000000090046fffffffffffffffffffffffffffffffff16938101939093526001015473ffffffffffffffffffffffffffffffffffffffff1660608301526111dc576fffffffffffffffffffffffffffffffff60408201526001815260008690036111dc578195505b600086826020015163ffffffff166111f49190615bae565b905060008382116112055781611207565b835b602084015190915063ffffffff165b8181101561135357600086828154811061123257611232615b50565b6000918252602080832090910154808352600690915260409091205490915060ff1661128a576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006002828154811061129f5761129f615b50565b600091825260209091206005909102018054909150640100000000900473ffffffffffffffffffffffffffffffffffffffff161580156112fc5750600481015460408701516fffffffffffffffffffffffffffffffff9182169116115b1561133e57600181015473ffffffffffffffffffffffffffffffffffffffff16606087015260048101546fffffffffffffffffffffffffffffffff1660408701525b5050808061134b90615bc6565b915050611216565b5063ffffffff818116602085810191825260008c81526007909152604090819020865181549351928801517fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009094169015157fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ff161761010092909416918202939093177fffffffffffffffffffffff00000000000000000000000000000000ffffffffff16650100000000006fffffffffffffffffffffffffffffffff909316929092029190911782556060850151600190920180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909316929092179091558490036115d757606083015160008a815260066020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055891580156114d357506000547201000000000000000000000000000000000000900460ff165b156115485760015473ffffffffffffffffffffffffffffffffffffffff166114fb818a61298e565b885473ffffffffffffffffffffffffffffffffffffffff909116640100000000027fffffffffffffffff0000000000000000000000000000000000000000ffffffff9091161788556115d5565b61158f73ffffffffffffffffffffffffffffffffffffffff82161561156d5781611589565b600189015473ffffffffffffffffffffffffffffffffffffffff165b8961298e565b87547fffffffffffffffff0000000000000000000000000000000000000000ffffffff1664010000000073ffffffffffffffffffffffffffffffffffffffff8316021788555b505b505050505050505050565b600080600054700100000000000000000000000000000000900460ff166002811115611610576116106157da565b14611647576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000805260066020527f54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4f85460ff166116ab576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660026000815481106116d7576116d7615b50565b6000918252602090912060059091020154640100000000900473ffffffffffffffffffffffffffffffffffffffff1614611712576001611715565b60025b6000805467ffffffffffffffff421668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff82168117835592935083927fffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffff000000000000000000ffffffffffffffff909116177001000000000000000000000000000000008360028111156117c6576117c66157da565b0217905560028111156117db576117db6157da565b6040517f5e186f09b9c93491f14e277eea7faa5de6a2d4bda75a79af7a3684fbfb42da6090600090a27f000000000000000000000000970670459734a83899773a0fd45941b5afc1200e73ffffffffffffffffffffffffffffffffffffffff1663838c2d1e6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561186c57600080fd5b505af1158015611880573d6000803e3d6000fd5b5050505090565b600560205281600052604060002081815481106118a357600080fd5b90600052602060002001600091509150505481565b905090565b6118ca8383836001611abe565b505050565b6000818152600760209081526040808320600590925282208054825461190090610100900463ffffffff1682615bfe565b95945050505050565b60606118b860546020612a8f565b73ffffffffffffffffffffffffffffffffffffffff811660009081526003602052604081208054908290559081900361197c576040517f17bfe5f700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517ff3fef3a300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152602482018390527f000000000000000000000000d6eaf4c146261653ee059077b78ed088add54309169063f3fef3a390604401600060405180830381600087803b158015611a0c57600080fd5b505af1158015611a20573d6000803e3d6000fd5b5050505060008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114611a7e576040519150601f19603f3d011682016040523d82523d6000602084013e611a83565b606091505b50509050806118ca576040517f83e6cc6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8161480611b3757503373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b6316145b611b6d576040517fd386ef3e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611b7984848484612ae1565b50505050565b6118ca8383836000611abe565b3273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c81614611bfb576040517fd386ef3e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611c036135ba565b565b600080600054700100000000000000000000000000000000900460ff166002811115611c3357611c336157da565b14611c6a576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028381548110611c7f57611c7f615b50565b600091825260208220600590910201805490925063ffffffff90811614611cee57815460028054909163ffffffff16908110611cbd57611cbd615b50565b906000526020600020906005020160040160109054906101000a90046fffffffffffffffffffffffffffffffff1690505b6004820154600090611d2690700100000000000000000000000000000000900467ffffffffffffffff165b67ffffffffffffffff1690565b611d3a9067ffffffffffffffff1642615bfe565b611d59611d19846fffffffffffffffffffffffffffffffff1660401c90565b67ffffffffffffffff16611d6d9190615bae565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b01667ffffffffffffffff168167ffffffffffffffff1611611dba5780611900565b7f00000000000000000000000000000000000000000000000000000000000004b095945050505050565b600080611e83836fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1690507f0000000000000000000000000000000000000000000000000000000000000008811115611ee2576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b642e90edd00062061a806311e1a3006000611efd8383615c44565b9050670de0b6b3a76400006000611f34827f0000000000000000000000000000000000000000000000000000000000000008615c58565b90506000611f52611f4d670de0b6b3a764000086615c58565b613b13565b90506000611f608484613d6e565b90506000611f6e8383613dbd565b90506000611f7b82613deb565b90506000611f9a82611f95670de0b6b3a76400008f615c58565b613fd3565b90506000611fa88b83613dbd565b9050611fb4818d615c58565b9f9e505050505050505050505050505050565b60028181548110611fd757600080fd5b60009182526020909120600590910201805460018201546002830154600384015460049094015463ffffffff8416955064010000000090930473ffffffffffffffffffffffffffffffffffffffff908116949216926fffffffffffffffffffffffffffffffff91821692918082169170010000000000000000000000000000000090041687565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c81614806120d757503373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b6316145b61210d576040517fd386ef3e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61211b868686868686614004565b505050505050565b60008054700100000000000000000000000000000000900460ff16600281111561214f5761214f6157da565b14612186576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060008061219586614633565b935093509350935060006121ab85858585614a3c565b905060007f000000000000000000000000444e09fe6d839273316a87002ab0efbea6fe780673ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561221a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061223e9190615c95565b9050600189036123365773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a8461229a367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036034013590565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815260048101939093526024830191909152604482015260206064820152608481018a905260a4015b6020604051808303816000875af115801561230c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123309190615cb2565b506115d7565b600289036123625773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a848961229a565b6003890361238e5773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a848761229a565b600489036125155760006123d46fffffffffffffffffffffffffffffffff85167f0000000000000000000000000000000000000000000000000000000000000004614af6565b6009546123e19190615bae565b6123ec906001615bae565b9050367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900360540135811061245557367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900360540135612457565b805b905073ffffffffffffffffffffffffffffffffffffffff82166352f0f3ad8b8560405160e084901b7fffffffff000000000000000000000000000000000000000000000000000000001681526004810192909252602482015260c084901b604482015260086064820152608481018b905260a4016020604051808303816000875af11580156124ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061250e9190615cb2565b50506115d7565b600589036125ae576040517f52f0f3ad000000000000000000000000000000000000000000000000000000008152600481018a9052602481018390527f000000000000000000000000000000000000000000000000000000000000038560c01b6044820152600860648201526084810188905273ffffffffffffffffffffffffffffffffffffffff8216906352f0f3ad9060a4016122ed565b6040517fff137e6500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000001367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003601401356060612639611909565b9050909192565b6000818310156126505781612652565b825b90505b92915050565b6000816000015182602001518360400151846060015160405160200161269a949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b60408051808201909152600080825260208201528151600003612706576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50604080518082019091528151815260209182019181019190915290565b6060600080600061273485614ba4565b91945092509050600181600181111561274f5761274f6157da565b14612786576040517f4b9c6abe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84516127928385615bae565b146127c9576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516020808252610420820190925290816020015b60408051808201909152600080825260208201528152602001906001900390816127e05790505093506000835b86518110156128ce576000806128536040518060400160405280858c600001516128379190615bfe565b8152602001858c6020015161284c9190615bae565b9052614ba4565b50915091506040518060400160405280838361286f9190615bae565b8152602001848b602001516128849190615bae565b81525088858151811061289957612899615b50565b60209081029190910101526128af600185615bae565b93506128bb8183615bae565b6128c59084615bae565b9250505061280d565b50845250919392505050565b606060008060006128ea85614ba4565b919450925090506000816001811115612905576129056157da565b1461293c576040517f1ff9b2e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6129468284615bae565b85511461297f576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61190085602001518484615042565b600281015473ffffffffffffffffffffffffffffffffffffffff8316600090815260036020526040812080546fffffffffffffffffffffffffffffffff909316928392906129dd908490615bae565b90915550506040517f7eee288d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152602482018390527f000000000000000000000000d6eaf4c146261653ee059077b78ed088add543091690637eee288d90604401600060405180830381600087803b158015612a7257600080fd5b505af1158015612a86573d6000803e3d6000fd5b50505050505050565b604051818152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90038284820160208401378260208301016000815260208101604052505092915050565b60008054700100000000000000000000000000000000900460ff166002811115612b0d57612b0d6157da565b14612b44576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028481548110612b5957612b59615b50565b60009182526020918290206040805160e0810182526005909302909101805463ffffffff8116845273ffffffffffffffffffffffffffffffffffffffff64010000000090910481169484019490945260018101549093169082015260028201546fffffffffffffffffffffffffffffffff908116606083015260038301546080830181905260049093015480821660a084015270010000000000000000000000000000000090041660c082015291508514612c40576040517f3014033200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60a0810151600083156fffffffffffffffffffffffffffffffff83161760011b90506000612d00826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169050861580612d3b5750612d387f00000000000000000000000000000000000000000000000000000000000000046002615bae565b81145b8015612d45575084155b15612d7c576040517fa42637bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000547201000000000000000000000000000000000000900460ff168015612da2575086155b15612dd9576040517f0ea2e75200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000008811115612e33576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612e5e7f00000000000000000000000000000000000000000000000000000000000000046001615bae565b8103612e7057612e70868885886150d7565b34612e7a83611de4565b14612eb1576040517f8620aa1900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000612ebc88611c05565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b0811690821603612f24576040517f3381d11400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000612f5160017f0000000000000000000000000000000000000000000000000000000000000008615bfe565b830361308f577f000000000000000000000000444e09fe6d839273316a87002ab0efbea6fe780673ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015612fc2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fe69190615c95565b73ffffffffffffffffffffffffffffffffffffffff1663f3f480d96040518163ffffffff1660e01b8152600401602060405180830381865afa158015613030573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130549190615cb2565b613088907f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff16615ccb565b9050613122565b6130ba60017f0000000000000000000000000000000000000000000000000000000000000004615bfe565b83036130f5576130887f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff166002615cf7565b507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff165b613156817f00000000000000000000000000000000000000000000000000000000000004b067ffffffffffffffff16615d27565b67ffffffffffffffff166131718367ffffffffffffffff1690565b67ffffffffffffffff1611156131b8576131b5817f00000000000000000000000000000000000000000000000000000000000004b067ffffffffffffffff16615d27565b91505b6000604083901b421760008a8152608087901b6fffffffffffffffffffffffffffffffff8d1617602052604081209192509060008181526004602052604090205490915060ff1615613236576040517f80497e3b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60016004600083815260200190815260200160002060006101000a81548160ff02191690831515021790555060026040518060e001604052808d63ffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020013373ffffffffffffffffffffffffffffffffffffffff168152602001346fffffffffffffffffffffffffffffffff1681526020018c8152602001886fffffffffffffffffffffffffffffffff168152602001846fffffffffffffffffffffffffffffffff16815250908060018154018082558091505060019003906000526020600020906005020160009091909190915060008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060608201518160020160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055506080820151816003015560a08201518160040160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555060c08201518160040160106101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055505050600560008c815260200190815260200160002060016002805490506134cc9190615bfe565b81546001810183556000928352602083200155604080517fd0e30db0000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000d6eaf4c146261653ee059077b78ed088add54309169263d0e30db09234926004808301939282900301818588803b15801561356457600080fd5b505af1158015613578573d6000803e3d6000fd5b50506040513393508d92508e91507f9b3245740ec3b155098a55be84957a4da13eaf7f14a8bc6f53126c0b9350f2be90600090a4505050505050505050505050565b60005471010000000000000000000000000000000000900460ff161561360c576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f7258a80700000000000000000000000000000000000000000000000000000000815263ffffffff7f0000000000000000000000000000000000000000000000000000000000000001166004820152600090819073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000970670459734a83899773a0fd45941b5afc1200e1690637258a807906024016040805180830381865afa1580156136c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136e49190615d50565b909250905081613720576040517f6a6bc3b200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080518082019091528281526020018190526008829055600981905536607a1461375357639824bdab6000526004601cfd5b80367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900360540135116137ed576040517ff40239db000000000000000000000000000000000000000000000000000000008152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013560048201526024015b60405180910390fd5b6040805160e08101825263ffffffff8082526000602083018181527ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe369081013560f01c90038035606090811c868801908152346fffffffffffffffffffffffffffffffff81811693890193845260149094013560808901908152600160a08a0181815242871660c08c019081526002805493840181558a529a5160059092027f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace81018054995173ffffffffffffffffffffffffffffffffffffffff908116640100000000027fffffffffffffffff000000000000000000000000000000000000000000000000909b1694909c16939093179890981790915592517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5acf87018054918a167fffffffffffffffffffffffff000000000000000000000000000000000000000090921691909117905592517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad0860180549186167fffffffffffffffffffffffffffffffff0000000000000000000000000000000090921691909117905591517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad185015551955182167001000000000000000000000000000000000295909116949094177f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad29091015580547fffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffff167101000000000000000000000000000000000017815583517fd0e30db000000000000000000000000000000000000000000000000000000000815293517f000000000000000000000000d6eaf4c146261653ee059077b78ed088add543099092169363d0e30db093926004828101939282900301818588803b158015613ac257600080fd5b505af1158015613ad6573d6000803e3d6000fd5b5050600080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000164267ffffffffffffffff161790555050505050565b6fffffffffffffffffffffffffffffffff811160071b81811c67ffffffffffffffff1060061b1781811c63ffffffff1060051b1781811c61ffff1060041b1781811c60ff1060031b1760008213613b7257631615e6386000526004601cfd5b7ff8f9f9faf9fdfafbf9fdfcfdfafbfcfef9fafdfafcfcfbfefafafcfbffffffff6f8421084210842108cc6318c6db6d54be83831c1c601f161a1890811b609f90811c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506029190037d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b302017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d90565b60007812725dd1d243aba0e75fe645cc4873f9e65afe688c928e1f218311670de0b6b3a764000002158202613dab57637c5f487d6000526004601cfd5b50670de0b6b3a7640000919091020490565b600081600019048311820215613ddb5763bac65e5b6000526004601cfd5b50670de0b6b3a764000091020490565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdc0d0570925a462d78213613e1957919050565b680755bf798b4a1bf1e58212613e375763a37bfec96000526004601cfd5b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b6000612652670de0b6b3a764000083613feb86613b13565b613ff59190615d74565b613fff9190615e30565b613deb565b60008054700100000000000000000000000000000000900460ff166002811115614030576140306157da565b14614067576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006002878154811061407c5761407c615b50565b6000918252602082206005919091020160048101549092506fffffffffffffffffffffffffffffffff16908715821760011b90506140db7f00000000000000000000000000000000000000000000000000000000000000086001615bae565b614177826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff16146141b1576040517f5f53dd9800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008089156142a8576142047f00000000000000000000000000000000000000000000000000000000000000047f0000000000000000000000000000000000000000000000000000000000000008615bfe565b6001901b614223846fffffffffffffffffffffffffffffffff16615288565b6fffffffffffffffffffffffffffffffff1661423f9190615e98565b1561427c5761427361426460016fffffffffffffffffffffffffffffffff8716615eac565b865463ffffffff166000615327565b6003015461429e565b7f00000000000000000000000000000000000000000000000000000000000000005b91508490506142d2565b600385015491506142cf6142646fffffffffffffffffffffffffffffffff86166001615ed5565b90505b600882901b60088a8a6040516142e9929190615b40565b6040518091039020901b1461432a576040517f696550ff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006143358c61540b565b90506000614344836003015490565b6040517fe14ced320000000000000000000000000000000000000000000000000000000081527f000000000000000000000000444e09fe6d839273316a87002ab0efbea6fe780673ffffffffffffffffffffffffffffffffffffffff169063e14ced32906143be908f908f908f908f908a90600401615f49565b6020604051808303816000875af11580156143dd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144019190615cb2565b6004850154911491506000906002906144ac906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b614548896fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b6145529190615f83565b61455c9190615fa6565b60ff16159050811515810361459d576040517ffb4e40dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8754640100000000900473ffffffffffffffffffffffffffffffffffffffff16156145f4576040517f9071e6af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505085547fffffffffffffffff0000000000000000000000000000000000000000ffffffff163364010000000002179095555050505050505050505050565b600080600080600085905060006002828154811061465357614653615b50565b600091825260209091206004600590920201908101549091507f00000000000000000000000000000000000000000000000000000000000000049061472a906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1611614764576040517fb34b5c2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000815b60048301547f00000000000000000000000000000000000000000000000000000000000000049061482b906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1692508211156148a057825463ffffffff1661486a7f00000000000000000000000000000000000000000000000000000000000000046001615bae565b8303614874578391505b6002818154811061488757614887615b50565b9060005260206000209060050201935080945050614768565b600481810154908401546fffffffffffffffffffffffffffffffff91821691166000816fffffffffffffffffffffffffffffffff166149096148f4856fffffffffffffffffffffffffffffffff1660011c90565b6fffffffffffffffffffffffffffffffff1690565b6fffffffffffffffffffffffffffffffff1614905080156149d8576000614941836fffffffffffffffffffffffffffffffff16615288565b6fffffffffffffffffffffffffffffffff1611156149ac57600061498361497b60016fffffffffffffffffffffffffffffffff8616615eac565b896001615327565b6003810154600490910154909c506fffffffffffffffffffffffffffffffff169a506149b29050565b6008549a505b600386015460048701549099506fffffffffffffffffffffffffffffffff169750614a2e565b60006149fa61497b6fffffffffffffffffffffffffffffffff85166001615ed5565b6003808901546004808b015492840154930154909e506fffffffffffffffffffffffffffffffff9182169d50919b50169850505b505050505050509193509193565b60006fffffffffffffffffffffffffffffffff841615614aa95760408051602081018790526fffffffffffffffffffffffffffffffff8087169282019290925260608101859052908316608082015260a00160405160208183030381529060405280519060200120611900565b8282604051602001614ad79291909182526fffffffffffffffffffffffffffffffff16602082015260400190565b6040516020818303038152906040528051906020012095945050505050565b600080614b83847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1690508083036001841b600180831b0386831b17039250505092915050565b60008060008360000151600003614be7576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020840151805160001a607f8111614c0c57600060016000945094509450505061503b565b60b78111614d22576000614c21608083615bfe565b905080876000015111614c60576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001838101517fff00000000000000000000000000000000000000000000000000000000000000169082148015614cd857507f80000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000008216105b15614d0f576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506001955093506000925061503b915050565b60bf8111614e80576000614d3760b783615bfe565b905080876000015111614d76576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614dd8576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c60378111614e20576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614e2a8184615bae565b895111614e63576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614e6e836001615bae565b975095506000945061503b9350505050565b60f78111614ee5576000614e9560c083615bfe565b905080876000015111614ed4576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60019550935084925061503b915050565b6000614ef260f783615bfe565b905080876000015111614f31576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614f93576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c60378111614fdb576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614fe58184615bae565b89511161501e576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b615029836001615bae565b975095506001945061503b9350505050565b9193909250565b60608167ffffffffffffffff81111561505d5761505d615a84565b6040519080825280601f01601f191660200182016040528015615087576020820181803683370190505b50905081156150d057600061509c8486615bae565b90506020820160005b848110156150bd5782810151828201526020016150a5565b848111156150cc576000858301525b5050505b9392505050565b60006150f66fffffffffffffffffffffffffffffffff84166001615ed5565b9050600061510682866001615327565b9050600086901a83806151f2575061513f60027f0000000000000000000000000000000000000000000000000000000000000004615e98565b60048301546002906151e3906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b6151ed9190615fa6565b60ff16145b1561524a5760ff81166001148061520c575060ff81166002145b615245576040517ff40239db000000000000000000000000000000000000000000000000000000008152600481018890526024016137e4565b612a86565b60ff811615612a86576040517ff40239db000000000000000000000000000000000000000000000000000000008152600481018890526024016137e4565b600080615315837e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b600160ff919091161b90920392915050565b600080826153705761536b6fffffffffffffffffffffffffffffffff86167f000000000000000000000000000000000000000000000000000000000000000461543a565b61538b565b61538b856fffffffffffffffffffffffffffffffff166155c6565b9050600284815481106153a0576153a0615b50565b906000526020600020906005020191505b60048201546fffffffffffffffffffffffffffffffff82811691161461540357815460028054909163ffffffff169081106153ee576153ee615b50565b906000526020600020906005020191506153b1565b509392505050565b600080600080600061541c86614633565b935093509350935061543084848484614a3c565b9695505050505050565b6000816154d9846fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff16116154ef5763b34b5c226000526004601cfd5b6154f8836155c6565b905081615597826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1611612655576126526155ad836001615bae565b6fffffffffffffffffffffffffffffffff83169061566b565b6000811960018301168161565a827e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169390931c8015179392505050565b6000806156f8847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169050808303600180821b0385821b179250505092915050565b60008083601f84011261572657600080fd5b50813567ffffffffffffffff81111561573e57600080fd5b60208301915083602082850101111561575657600080fd5b9250929050565b600080600083850360a081121561577357600080fd5b608081121561578157600080fd5b50839250608084013567ffffffffffffffff81111561579f57600080fd5b6157ab86828701615714565b9497909650939450505050565b600080604083850312156157cb57600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6020810160038310615844577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b60008060006060848603121561585f57600080fd5b505081359360208301359350604090920135919050565b6000815180845260005b8181101561589c57602081850181015186830182015201615880565b818111156158ae576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006126526020830184615876565b60006020828403121561590657600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff8116811461592f57600080fd5b50565b60006020828403121561594457600080fd5b81356150d08161590d565b8035801515811461595f57600080fd5b919050565b6000806000806080858703121561597a57600080fd5b8435935060208501359250604085013591506159986060860161594f565b905092959194509250565b6000602082840312156159b557600080fd5b81356fffffffffffffffffffffffffffffffff811681146150d057600080fd5b600080600080600080608087890312156159ee57600080fd5b863595506159fe6020880161594f565b9450604087013567ffffffffffffffff80821115615a1b57600080fd5b615a278a838b01615714565b90965094506060890135915080821115615a4057600080fd5b50615a4d89828a01615714565b979a9699509497509295939492505050565b63ffffffff841681528260208201526060604082015260006119006060830184615876565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600060808284031215615ac557600080fd5b6040516080810181811067ffffffffffffffff82111715615b0f577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115615bc157615bc1615b7f565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203615bf757615bf7615b7f565b5060010190565b600082821015615c1057615c10615b7f565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082615c5357615c53615c15565b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615c9057615c90615b7f565b500290565b600060208284031215615ca757600080fd5b81516150d08161590d565b600060208284031215615cc457600080fd5b5051919050565b600067ffffffffffffffff808316818516808303821115615cee57615cee615b7f565b01949350505050565b600067ffffffffffffffff80831681851681830481118215151615615d1e57615d1e615b7f565b02949350505050565b600067ffffffffffffffff83811690831681811015615d4857615d48615b7f565b039392505050565b60008060408385031215615d6357600080fd5b505080516020909101519092909150565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600084136000841385830485118282161615615db557615db5615b7f565b7f80000000000000000000000000000000000000000000000000000000000000006000871286820588128184161615615df057615df0615b7f565b60008712925087820587128484161615615e0c57615e0c615b7f565b87850587128184161615615e2257615e22615b7f565b505050929093029392505050565b600082615e3f57615e3f615c15565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f800000000000000000000000000000000000000000000000000000000000000083141615615e9357615e93615b7f565b500590565b600082615ea757615ea7615c15565b500690565b60006fffffffffffffffffffffffffffffffff83811690831681811015615d4857615d48615b7f565b60006fffffffffffffffffffffffffffffffff808316818516808303821115615cee57615cee615b7f565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b606081526000615f5d606083018789615f00565b8281036020840152615f70818688615f00565b9150508260408301529695505050505050565b600060ff821660ff841680821015615f9d57615f9d615b7f565b90039392505050565b600060ff831680615fb957615fb9615c15565b8060ff8416069150509291505056fea164736f6c634300080f000a"; ++ hex"6080604052600436106103085760003560e01c806370872aa51161019a578063c6f0308c116100e1578063ec5e63081161008a578063fa24f74311610064578063fa24f74314610b94578063fa315aa914610bb8578063fe2bbeb214610beb57600080fd5b8063ec5e630814610b11578063eff0f59214610b44578063f8f43ff614610b7457600080fd5b8063d6ae3cd5116100bb578063d6ae3cd514610a8b578063d8cc1a3c14610abe578063dabd396d14610ade57600080fd5b8063c6f0308c146109b3578063cf09e0d014610a3d578063d5d44d8014610a5e57600080fd5b8063a445ece611610143578063bcef3b551161011d578063bcef3b5514610933578063bd8da95614610973578063c395e1ca1461099357600080fd5b8063a445ece6146107f3578063a8e4fb90146108bf578063bbdc02db146108f257600080fd5b80638980e0cc116101745780638980e0cc1461076b5780638b85902b146107805780638d450a95146107c057600080fd5b806370872aa51461073b5780637b0f0adc146107505780638129fc1c1461076357600080fd5b80633fc8cef31161025e5780635c0cba33116102075780636361506d116101e15780636361506d146106b55780636b6716c0146106f55780636f0344091461072857600080fd5b80635c0cba331461064d578063609d33341461068057806360e274641461069557600080fd5b806354fd4d501161023857806354fd4d50146105a757806357da950e146105fd5780635a5fa2d91461062d57600080fd5b80633fc8cef31461052e578063472777c614610561578063534db0e21461057457600080fd5b80632810e1d6116102c057806337b1b2291161029a57806337b1b2291461047b5780633a768463146104bb5780633e3ac912146104ee57600080fd5b80632810e1d6146103f45780632ad69aeb1461040957806330dbe5701461042957600080fd5b806319effeb4116102f157806319effeb41461034f578063200d2ed21461039a57806325fc2ace146103d557600080fd5b8063019351301461030d57806303c2924d1461032f575b600080fd5b34801561031957600080fd5b5061032d61032836600461575d565b610c1b565b005b34801561033b57600080fd5b5061032d61034a3660046157b8565b610f3c565b34801561035b57600080fd5b5060005461037c9068010000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020015b60405180910390f35b3480156103a657600080fd5b506000546103c890700100000000000000000000000000000000900460ff1681565b6040516103919190615809565b3480156103e157600080fd5b506008545b604051908152602001610391565b34801561040057600080fd5b506103c86115e2565b34801561041557600080fd5b506103e66104243660046157b8565b611887565b34801561043557600080fd5b506001546104569073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610391565b34801561048757600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90033560601c610456565b3480156104c757600080fd5b507f000000000000000000000000180cbe2ebb9f37d3a3c542ddc2546fd160555a73610456565b3480156104fa57600080fd5b5060005461051e907201000000000000000000000000000000000000900460ff1681565b6040519015158152602001610391565b34801561053a57600080fd5b507f000000000000000000000000d6eaf4c146261653ee059077b78ed088add54309610456565b61032d61056f36600461584a565b6118bd565b34801561058057600080fd5b507f0000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b63610456565b3480156105b357600080fd5b506105f06040518060400160405280600c81526020017f312e332e312d626574612e32000000000000000000000000000000000000000081525081565b60405161039191906158e1565b34801561060957600080fd5b50600854600954610618919082565b60408051928352602083019190915201610391565b34801561063957600080fd5b506103e66106483660046158f4565b6118cf565b34801561065957600080fd5b507f000000000000000000000000970670459734a83899773a0fd45941b5afc1200e610456565b34801561068c57600080fd5b506105f0611909565b3480156106a157600080fd5b5061032d6106b0366004615932565b611917565b3480156106c157600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003603401356103e6565b34801561070157600080fd5b507f000000000000000000000000000000000000000000000000000000000000000061037c565b61032d610736366004615964565b611abe565b34801561074757600080fd5b506009546103e6565b61032d61075e36600461584a565b611b7f565b61032d611b8c565b34801561077757600080fd5b506002546103e6565b34801561078c57600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401356103e6565b3480156107cc57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006103e6565b3480156107ff57600080fd5b5061086b61080e3660046158f4565b6007602052600090815260409020805460019091015460ff821691610100810463ffffffff1691650100000000009091046fffffffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff1684565b60408051941515855263ffffffff90931660208501526fffffffffffffffffffffffffffffffff9091169183019190915273ffffffffffffffffffffffffffffffffffffffff166060820152608001610391565b3480156108cb57600080fd5b507f00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8610456565b3480156108fe57600080fd5b5060405163ffffffff7f0000000000000000000000000000000000000000000000000000000000000001168152602001610391565b34801561093f57600080fd5b50367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003601401356103e6565b34801561097f57600080fd5b5061037c61098e3660046158f4565b611c05565b34801561099f57600080fd5b506103e66109ae3660046159a3565b611de4565b3480156109bf57600080fd5b506109d36109ce3660046158f4565b611fc7565b6040805163ffffffff909816885273ffffffffffffffffffffffffffffffffffffffff968716602089015295909416948601949094526fffffffffffffffffffffffffffffffff9182166060860152608085015291821660a08401521660c082015260e001610391565b348015610a4957600080fd5b5060005461037c9067ffffffffffffffff1681565b348015610a6a57600080fd5b506103e6610a79366004615932565b60036020526000908152604090205481565b348015610a9757600080fd5b507f00000000000000000000000000000000000000000000000000000000000003856103e6565b348015610aca57600080fd5b5061032d610ad93660046159d5565b61205e565b348015610aea57600080fd5b507f00000000000000000000000000000000000000000000000000000000000004b061037c565b348015610b1d57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000046103e6565b348015610b5057600080fd5b5061051e610b5f3660046158f4565b60046020526000908152604090205460ff1681565b348015610b8057600080fd5b5061032d610b8f36600461584a565b612123565b348015610ba057600080fd5b50610ba96125e0565b60405161039193929190615a5f565b348015610bc457600080fd5b507f00000000000000000000000000000000000000000000000000000000000000086103e6565b348015610bf757600080fd5b5061051e610c063660046158f4565b60066020526000908152604090205460ff1681565b60008054700100000000000000000000000000000000900460ff166002811115610c4757610c476157da565b14610c7e576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000547201000000000000000000000000000000000000900460ff1615610cd1576040517f0ea2e75200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d08367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013590565b90565b610d1f610d1a36869003860186615ab3565b61265b565b14610d56576040517f9cc00b5b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82606001358282604051610d6b929190615b40565b604051809103902014610daa576040517fd81d583b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610df3610dee84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506126b792505050565b612724565b90506000610e1a82600881518110610e0d57610e0d615b50565b60200260200101516128da565b9050602081511115610e58576040517fd81d583b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602081810151825190910360031b1c367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605401358103610ecd576040517fb8ed883000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050600180547fffffffffffffffffffffffff000000000000000000000000000000000000000016331790555050600080547fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff1672010000000000000000000000000000000000001790555050565b60008054700100000000000000000000000000000000900460ff166002811115610f6857610f686157da565b14610f9f576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028381548110610fb457610fb4615b50565b906000526020600020906005020190506000610fcf84611c05565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b081169082161015611038576040517ff2440b5300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008481526006602052604090205460ff1615611081576040517ff1a9458100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600084815260056020526040902080548015801561109e57508515155b15611139578354640100000000900473ffffffffffffffffffffffffffffffffffffffff16600081156110d157816110ed565b600186015473ffffffffffffffffffffffffffffffffffffffff165b90506110f9818761298e565b50505060009485525050600660205250506040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b6000868152600760209081526040918290208251608081018452815460ff81161515808352610100820463ffffffff16948301949094526501000000000090046fffffffffffffffffffffffffffffffff16938101939093526001015473ffffffffffffffffffffffffffffffffffffffff1660608301526111dc576fffffffffffffffffffffffffffffffff60408201526001815260008690036111dc578195505b600086826020015163ffffffff166111f49190615bae565b905060008382116112055781611207565b835b602084015190915063ffffffff165b8181101561135357600086828154811061123257611232615b50565b6000918252602080832090910154808352600690915260409091205490915060ff1661128a576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006002828154811061129f5761129f615b50565b600091825260209091206005909102018054909150640100000000900473ffffffffffffffffffffffffffffffffffffffff161580156112fc5750600481015460408701516fffffffffffffffffffffffffffffffff9182169116115b1561133e57600181015473ffffffffffffffffffffffffffffffffffffffff16606087015260048101546fffffffffffffffffffffffffffffffff1660408701525b5050808061134b90615bc6565b915050611216565b5063ffffffff818116602085810191825260008c81526007909152604090819020865181549351928801517fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009094169015157fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ff161761010092909416918202939093177fffffffffffffffffffffff00000000000000000000000000000000ffffffffff16650100000000006fffffffffffffffffffffffffffffffff909316929092029190911782556060850151600190920180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909316929092179091558490036115d757606083015160008a815260066020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055891580156114d357506000547201000000000000000000000000000000000000900460ff165b156115485760015473ffffffffffffffffffffffffffffffffffffffff166114fb818a61298e565b885473ffffffffffffffffffffffffffffffffffffffff909116640100000000027fffffffffffffffff0000000000000000000000000000000000000000ffffffff9091161788556115d5565b61158f73ffffffffffffffffffffffffffffffffffffffff82161561156d5781611589565b600189015473ffffffffffffffffffffffffffffffffffffffff165b8961298e565b87547fffffffffffffffff0000000000000000000000000000000000000000ffffffff1664010000000073ffffffffffffffffffffffffffffffffffffffff8316021788555b505b505050505050505050565b600080600054700100000000000000000000000000000000900460ff166002811115611610576116106157da565b14611647576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000805260066020527f54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4f85460ff166116ab576040517f9a07664600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660026000815481106116d7576116d7615b50565b6000918252602090912060059091020154640100000000900473ffffffffffffffffffffffffffffffffffffffff1614611712576001611715565b60025b6000805467ffffffffffffffff421668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff82168117835592935083927fffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffff000000000000000000ffffffffffffffff909116177001000000000000000000000000000000008360028111156117c6576117c66157da565b0217905560028111156117db576117db6157da565b6040517f5e186f09b9c93491f14e277eea7faa5de6a2d4bda75a79af7a3684fbfb42da6090600090a27f000000000000000000000000970670459734a83899773a0fd45941b5afc1200e73ffffffffffffffffffffffffffffffffffffffff1663838c2d1e6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561186c57600080fd5b505af1158015611880573d6000803e3d6000fd5b5050505090565b600560205281600052604060002081815481106118a357600080fd5b90600052602060002001600091509150505481565b905090565b6118ca8383836001611abe565b505050565b6000818152600760209081526040808320600590925282208054825461190090610100900463ffffffff1682615bfe565b95945050505050565b60606118b860546020612a8f565b73ffffffffffffffffffffffffffffffffffffffff811660009081526003602052604081208054908290559081900361197c576040517f17bfe5f700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517ff3fef3a300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8381166004830152602482018390527f000000000000000000000000d6eaf4c146261653ee059077b78ed088add54309169063f3fef3a390604401600060405180830381600087803b158015611a0c57600080fd5b505af1158015611a20573d6000803e3d6000fd5b5050505060008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114611a7e576040519150601f19603f3d011682016040523d82523d6000602084013e611a83565b606091505b50509050806118ca576040517f83e6cc6b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8161480611b3757503373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b6316145b611b6d576040517fd386ef3e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611b7984848484612ae1565b50505050565b6118ca8383836000611abe565b3273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c81614611bfb576040517fd386ef3e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611c036135ba565b565b600080600054700100000000000000000000000000000000900460ff166002811115611c3357611c336157da565b14611c6a576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028381548110611c7f57611c7f615b50565b600091825260208220600590910201805490925063ffffffff90811614611cee57815460028054909163ffffffff16908110611cbd57611cbd615b50565b906000526020600020906005020160040160109054906101000a90046fffffffffffffffffffffffffffffffff1690505b6004820154600090611d2690700100000000000000000000000000000000900467ffffffffffffffff165b67ffffffffffffffff1690565b611d3a9067ffffffffffffffff1642615bfe565b611d59611d19846fffffffffffffffffffffffffffffffff1660401c90565b67ffffffffffffffff16611d6d9190615bae565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b01667ffffffffffffffff168167ffffffffffffffff1611611dba5780611900565b7f00000000000000000000000000000000000000000000000000000000000004b095945050505050565b600080611e83836fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1690507f0000000000000000000000000000000000000000000000000000000000000008811115611ee2576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b642e90edd00062061a806311e1a3006000611efd8383615c44565b9050670de0b6b3a76400006000611f34827f0000000000000000000000000000000000000000000000000000000000000008615c58565b90506000611f52611f4d670de0b6b3a764000086615c58565b613b13565b90506000611f608484613d6e565b90506000611f6e8383613dbd565b90506000611f7b82613deb565b90506000611f9a82611f95670de0b6b3a76400008f615c58565b613fd3565b90506000611fa88b83613dbd565b9050611fb4818d615c58565b9f9e505050505050505050505050505050565b60028181548110611fd757600080fd5b60009182526020909120600590910201805460018201546002830154600384015460049094015463ffffffff8416955064010000000090930473ffffffffffffffffffffffffffffffffffffffff908116949216926fffffffffffffffffffffffffffffffff91821692918082169170010000000000000000000000000000000090041687565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c81614806120d757503373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000006925b8704ff96dee942623d6fb5e946ef5884b6316145b61210d576040517fd386ef3e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61211b868686868686614004565b505050505050565b60008054700100000000000000000000000000000000900460ff16600281111561214f5761214f6157da565b14612186576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060008061219586614633565b935093509350935060006121ab85858585614a3c565b905060007f000000000000000000000000180cbe2ebb9f37d3a3c542ddc2546fd160555a7373ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561221a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061223e9190615c95565b9050600189036123365773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a8461229a367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036034013590565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815260048101939093526024830191909152604482015260206064820152608481018a905260a4015b6020604051808303816000875af115801561230c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123309190615cb2565b506115d7565b600289036123625773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a848961229a565b6003890361238e5773ffffffffffffffffffffffffffffffffffffffff81166352f0f3ad8a848761229a565b600489036125155760006123d46fffffffffffffffffffffffffffffffff85167f0000000000000000000000000000000000000000000000000000000000000004614af6565b6009546123e19190615bae565b6123ec906001615bae565b9050367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900360540135811061245557367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900360540135612457565b805b905073ffffffffffffffffffffffffffffffffffffffff82166352f0f3ad8b8560405160e084901b7fffffffff000000000000000000000000000000000000000000000000000000001681526004810192909252602482015260c084901b604482015260086064820152608481018b905260a4016020604051808303816000875af11580156124ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061250e9190615cb2565b50506115d7565b600589036125ae576040517f52f0f3ad000000000000000000000000000000000000000000000000000000008152600481018a9052602481018390527f000000000000000000000000000000000000000000000000000000000000038560c01b6044820152600860648201526084810188905273ffffffffffffffffffffffffffffffffffffffff8216906352f0f3ad9060a4016122ed565b6040517fff137e6500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000001367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003601401356060612639611909565b9050909192565b6000818310156126505781612652565b825b90505b92915050565b6000816000015182602001518360400151846060015160405160200161269a949392919093845260208401929092526040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b60408051808201909152600080825260208201528151600003612706576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50604080518082019091528151815260209182019181019190915290565b6060600080600061273485614ba4565b91945092509050600181600181111561274f5761274f6157da565b14612786576040517f4b9c6abe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84516127928385615bae565b146127c9576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516020808252610420820190925290816020015b60408051808201909152600080825260208201528152602001906001900390816127e05790505093506000835b86518110156128ce576000806128536040518060400160405280858c600001516128379190615bfe565b8152602001858c6020015161284c9190615bae565b9052614ba4565b50915091506040518060400160405280838361286f9190615bae565b8152602001848b602001516128849190615bae565b81525088858151811061289957612899615b50565b60209081029190910101526128af600185615bae565b93506128bb8183615bae565b6128c59084615bae565b9250505061280d565b50845250919392505050565b606060008060006128ea85614ba4565b919450925090506000816001811115612905576129056157da565b1461293c576040517f1ff9b2e400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6129468284615bae565b85511461297f576040517f5c5537b800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61190085602001518484615042565b600281015473ffffffffffffffffffffffffffffffffffffffff8316600090815260036020526040812080546fffffffffffffffffffffffffffffffff909316928392906129dd908490615bae565b90915550506040517f7eee288d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152602482018390527f000000000000000000000000d6eaf4c146261653ee059077b78ed088add543091690637eee288d90604401600060405180830381600087803b158015612a7257600080fd5b505af1158015612a86573d6000803e3d6000fd5b50505050505050565b604051818152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90038284820160208401378260208301016000815260208101604052505092915050565b60008054700100000000000000000000000000000000900460ff166002811115612b0d57612b0d6157da565b14612b44576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060028481548110612b5957612b59615b50565b60009182526020918290206040805160e0810182526005909302909101805463ffffffff8116845273ffffffffffffffffffffffffffffffffffffffff64010000000090910481169484019490945260018101549093169082015260028201546fffffffffffffffffffffffffffffffff908116606083015260038301546080830181905260049093015480821660a084015270010000000000000000000000000000000090041660c082015291508514612c40576040517f3014033200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60a0810151600083156fffffffffffffffffffffffffffffffff83161760011b90506000612d00826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169050861580612d3b5750612d387f00000000000000000000000000000000000000000000000000000000000000046002615bae565b81145b8015612d45575084155b15612d7c576040517fa42637bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000547201000000000000000000000000000000000000900460ff168015612da2575086155b15612dd9576040517f0ea2e75200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000008811115612e33576040517f56f57b2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612e5e7f00000000000000000000000000000000000000000000000000000000000000046001615bae565b8103612e7057612e70868885886150d7565b34612e7a83611de4565b14612eb1576040517f8620aa1900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000612ebc88611c05565b905067ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000004b0811690821603612f24576040517f3381d11400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000612f5160017f0000000000000000000000000000000000000000000000000000000000000008615bfe565b830361308f577f000000000000000000000000180cbe2ebb9f37d3a3c542ddc2546fd160555a7373ffffffffffffffffffffffffffffffffffffffff16637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015612fc2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fe69190615c95565b73ffffffffffffffffffffffffffffffffffffffff1663f3f480d96040518163ffffffff1660e01b8152600401602060405180830381865afa158015613030573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130549190615cb2565b613088907f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff16615ccb565b9050613122565b6130ba60017f0000000000000000000000000000000000000000000000000000000000000004615bfe565b83036130f5576130887f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff166002615cf7565b507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff165b613156817f00000000000000000000000000000000000000000000000000000000000004b067ffffffffffffffff16615d27565b67ffffffffffffffff166131718367ffffffffffffffff1690565b67ffffffffffffffff1611156131b8576131b5817f00000000000000000000000000000000000000000000000000000000000004b067ffffffffffffffff16615d27565b91505b6000604083901b421760008a8152608087901b6fffffffffffffffffffffffffffffffff8d1617602052604081209192509060008181526004602052604090205490915060ff1615613236576040517f80497e3b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60016004600083815260200190815260200160002060006101000a81548160ff02191690831515021790555060026040518060e001604052808d63ffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020013373ffffffffffffffffffffffffffffffffffffffff168152602001346fffffffffffffffffffffffffffffffff1681526020018c8152602001886fffffffffffffffffffffffffffffffff168152602001846fffffffffffffffffffffffffffffffff16815250908060018154018082558091505060019003906000526020600020906005020160009091909190915060008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060608201518160020160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055506080820151816003015560a08201518160040160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555060c08201518160040160106101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055505050600560008c815260200190815260200160002060016002805490506134cc9190615bfe565b81546001810183556000928352602083200155604080517fd0e30db0000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000d6eaf4c146261653ee059077b78ed088add54309169263d0e30db09234926004808301939282900301818588803b15801561356457600080fd5b505af1158015613578573d6000803e3d6000fd5b50506040513393508d92508e91507f9b3245740ec3b155098a55be84957a4da13eaf7f14a8bc6f53126c0b9350f2be90600090a4505050505050505050505050565b60005471010000000000000000000000000000000000900460ff161561360c576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f7258a80700000000000000000000000000000000000000000000000000000000815263ffffffff7f0000000000000000000000000000000000000000000000000000000000000001166004820152600090819073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000970670459734a83899773a0fd45941b5afc1200e1690637258a807906024016040805180830381865afa1580156136c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136e49190615d50565b909250905081613720576040517f6a6bc3b200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080518082019091528281526020018190526008829055600981905536607a1461375357639824bdab6000526004601cfd5b80367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900360540135116137ed576040517ff40239db000000000000000000000000000000000000000000000000000000008152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013560048201526024015b60405180910390fd5b6040805160e08101825263ffffffff8082526000602083018181527ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe369081013560f01c90038035606090811c868801908152346fffffffffffffffffffffffffffffffff81811693890193845260149094013560808901908152600160a08a0181815242871660c08c019081526002805493840181558a529a5160059092027f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace81018054995173ffffffffffffffffffffffffffffffffffffffff908116640100000000027fffffffffffffffff000000000000000000000000000000000000000000000000909b1694909c16939093179890981790915592517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5acf87018054918a167fffffffffffffffffffffffff000000000000000000000000000000000000000090921691909117905592517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad0860180549186167fffffffffffffffffffffffffffffffff0000000000000000000000000000000090921691909117905591517f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad185015551955182167001000000000000000000000000000000000295909116949094177f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ad29091015580547fffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffff167101000000000000000000000000000000000017815583517fd0e30db000000000000000000000000000000000000000000000000000000000815293517f000000000000000000000000d6eaf4c146261653ee059077b78ed088add543099092169363d0e30db093926004828101939282900301818588803b158015613ac257600080fd5b505af1158015613ad6573d6000803e3d6000fd5b5050600080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000164267ffffffffffffffff161790555050505050565b6fffffffffffffffffffffffffffffffff811160071b81811c67ffffffffffffffff1060061b1781811c63ffffffff1060051b1781811c61ffff1060041b1781811c60ff1060031b1760008213613b7257631615e6386000526004601cfd5b7ff8f9f9faf9fdfafbf9fdfcfdfafbfcfef9fafdfafcfcfbfefafafcfbffffffff6f8421084210842108cc6318c6db6d54be83831c1c601f161a1890811b609f90811c6c465772b2bbbb5f824b15207a3081018102606090811d6d0388eaa27412d5aca026815d636e018202811d6d0df99ac502031bf953eff472fdcc018202811d6d13cdffb29d51d99322bdff5f2211018202811d6d0a0f742023def783a307a986912e018202811d6d01920d8043ca89b5239253284e42018202811d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7883018302821d6d0139601a2efabe717e604cbb4894018302821d6d02247f7a7b6594320649aa03aba1018302821d7fffffffffffffffffffffffffffffffffffffff73c0c716a594e00d54e3c4cbc9018302821d7ffffffffffffffffffffffffffffffffffffffdc7b88c420e53a9890533129f6f01830290911d7fffffffffffffffffffffffffffffffffffffff465fda27eb4d63ded474e5f832019091027ffffffffffffffff5f6af8f7b3396644f18e157960000000000000000000000000105711340daa0d5f769dba1915cef59f0815a5506029190037d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b302017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d90565b60007812725dd1d243aba0e75fe645cc4873f9e65afe688c928e1f218311670de0b6b3a764000002158202613dab57637c5f487d6000526004601cfd5b50670de0b6b3a7640000919091020490565b600081600019048311820215613ddb5763bac65e5b6000526004601cfd5b50670de0b6b3a764000091020490565b60007ffffffffffffffffffffffffffffffffffffffffffffffffdc0d0570925a462d78213613e1957919050565b680755bf798b4a1bf1e58212613e375763a37bfec96000526004601cfd5b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056b80000000000000000000000001901d6bb17217f7d1cf79abc9e3b39881029093037fffffffffffffffffffffffffffffffffffffffdbf3ccf1604d263450f02a550481018102606090811d6d0277594991cfc85f6e2461837cd9018202811d7fffffffffffffffffffffffffffffffffffffe5adedaa1cb095af9e4da10e363c018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d7ffffffffffffffffffffffffffffffffffffd38dc772608b0ae56cce01296c0eb018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084017ffffffffffffffffffffffffffffffffffffffe2c69812cf03b0763fd454a8f7e010290911d6e0587f503bb6ea29d25fcb7401964500190910279d835ebba824c98fb31b83b2ca45c000000000000000000000000010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b6000612652670de0b6b3a764000083613feb86613b13565b613ff59190615d74565b613fff9190615e30565b613deb565b60008054700100000000000000000000000000000000900460ff166002811115614030576140306157da565b14614067576040517f67fe195000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006002878154811061407c5761407c615b50565b6000918252602082206005919091020160048101549092506fffffffffffffffffffffffffffffffff16908715821760011b90506140db7f00000000000000000000000000000000000000000000000000000000000000086001615bae565b614177826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff16146141b1576040517f5f53dd9800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008089156142a8576142047f00000000000000000000000000000000000000000000000000000000000000047f0000000000000000000000000000000000000000000000000000000000000008615bfe565b6001901b614223846fffffffffffffffffffffffffffffffff16615288565b6fffffffffffffffffffffffffffffffff1661423f9190615e98565b1561427c5761427361426460016fffffffffffffffffffffffffffffffff8716615eac565b865463ffffffff166000615327565b6003015461429e565b7f00000000000000000000000000000000000000000000000000000000000000005b91508490506142d2565b600385015491506142cf6142646fffffffffffffffffffffffffffffffff86166001615ed5565b90505b600882901b60088a8a6040516142e9929190615b40565b6040518091039020901b1461432a576040517f696550ff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006143358c61540b565b90506000614344836003015490565b6040517fe14ced320000000000000000000000000000000000000000000000000000000081527f000000000000000000000000180cbe2ebb9f37d3a3c542ddc2546fd160555a7373ffffffffffffffffffffffffffffffffffffffff169063e14ced32906143be908f908f908f908f908a90600401615f49565b6020604051808303816000875af11580156143dd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144019190615cb2565b6004850154911491506000906002906144ac906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b614548896fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b6145529190615f83565b61455c9190615fa6565b60ff16159050811515810361459d576040517ffb4e40dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8754640100000000900473ffffffffffffffffffffffffffffffffffffffff16156145f4576040517f9071e6af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505085547fffffffffffffffff0000000000000000000000000000000000000000ffffffff163364010000000002179095555050505050505050505050565b600080600080600085905060006002828154811061465357614653615b50565b600091825260209091206004600590920201908101549091507f00000000000000000000000000000000000000000000000000000000000000049061472a906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1611614764576040517fb34b5c2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000815b60048301547f00000000000000000000000000000000000000000000000000000000000000049061482b906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1692508211156148a057825463ffffffff1661486a7f00000000000000000000000000000000000000000000000000000000000000046001615bae565b8303614874578391505b6002818154811061488757614887615b50565b9060005260206000209060050201935080945050614768565b600481810154908401546fffffffffffffffffffffffffffffffff91821691166000816fffffffffffffffffffffffffffffffff166149096148f4856fffffffffffffffffffffffffffffffff1660011c90565b6fffffffffffffffffffffffffffffffff1690565b6fffffffffffffffffffffffffffffffff1614905080156149d8576000614941836fffffffffffffffffffffffffffffffff16615288565b6fffffffffffffffffffffffffffffffff1611156149ac57600061498361497b60016fffffffffffffffffffffffffffffffff8616615eac565b896001615327565b6003810154600490910154909c506fffffffffffffffffffffffffffffffff169a506149b29050565b6008549a505b600386015460048701549099506fffffffffffffffffffffffffffffffff169750614a2e565b60006149fa61497b6fffffffffffffffffffffffffffffffff85166001615ed5565b6003808901546004808b015492840154930154909e506fffffffffffffffffffffffffffffffff9182169d50919b50169850505b505050505050509193509193565b60006fffffffffffffffffffffffffffffffff841615614aa95760408051602081018790526fffffffffffffffffffffffffffffffff8087169282019290925260608101859052908316608082015260a00160405160208183030381529060405280519060200120611900565b8282604051602001614ad79291909182526fffffffffffffffffffffffffffffffff16602082015260400190565b6040516020818303038152906040528051906020012095945050505050565b600080614b83847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1690508083036001841b600180831b0386831b17039250505092915050565b60008060008360000151600003614be7576040517f5ab458fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020840151805160001a607f8111614c0c57600060016000945094509450505061503b565b60b78111614d22576000614c21608083615bfe565b905080876000015111614c60576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001838101517fff00000000000000000000000000000000000000000000000000000000000000169082148015614cd857507f80000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000008216105b15614d0f576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506001955093506000925061503b915050565b60bf8111614e80576000614d3760b783615bfe565b905080876000015111614d76576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614dd8576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c60378111614e20576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614e2a8184615bae565b895111614e63576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614e6e836001615bae565b975095506000945061503b9350505050565b60f78111614ee5576000614e9560c083615bfe565b905080876000015111614ed4576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60019550935084925061503b915050565b6000614ef260f783615bfe565b905080876000015111614f31576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018301517fff00000000000000000000000000000000000000000000000000000000000000166000819003614f93576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600184015160088302610100031c60378111614fdb576040517fbabb01dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614fe58184615bae565b89511161501e576040517f66c9448500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b615029836001615bae565b975095506001945061503b9350505050565b9193909250565b60608167ffffffffffffffff81111561505d5761505d615a84565b6040519080825280601f01601f191660200182016040528015615087576020820181803683370190505b50905081156150d057600061509c8486615bae565b90506020820160005b848110156150bd5782810151828201526020016150a5565b848111156150cc576000858301525b5050505b9392505050565b60006150f66fffffffffffffffffffffffffffffffff84166001615ed5565b9050600061510682866001615327565b9050600086901a83806151f2575061513f60027f0000000000000000000000000000000000000000000000000000000000000004615e98565b60048301546002906151e3906fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b6151ed9190615fa6565b60ff16145b1561524a5760ff81166001148061520c575060ff81166002145b615245576040517ff40239db000000000000000000000000000000000000000000000000000000008152600481018890526024016137e4565b612a86565b60ff811615612a86576040517ff40239db000000000000000000000000000000000000000000000000000000008152600481018890526024016137e4565b600080615315837e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b600160ff919091161b90920392915050565b600080826153705761536b6fffffffffffffffffffffffffffffffff86167f000000000000000000000000000000000000000000000000000000000000000461543a565b61538b565b61538b856fffffffffffffffffffffffffffffffff166155c6565b9050600284815481106153a0576153a0615b50565b906000526020600020906005020191505b60048201546fffffffffffffffffffffffffffffffff82811691161461540357815460028054909163ffffffff169081106153ee576153ee615b50565b906000526020600020906005020191506153b1565b509392505050565b600080600080600061541c86614633565b935093509350935061543084848484614a3c565b9695505050505050565b6000816154d9846fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff16116154ef5763b34b5c226000526004601cfd5b6154f8836155c6565b905081615597826fffffffffffffffffffffffffffffffff167e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff1611612655576126526155ad836001615bae565b6fffffffffffffffffffffffffffffffff83169061566b565b6000811960018301168161565a827e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169390931c8015179392505050565b6000806156f8847e09010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f7f07c4acdd0000000000000000000000000000000000000000000000000000000067ffffffffffffffff831160061b83811c63ffffffff1060051b1792831c600181901c17600281901c17600481901c17600881901c17601081901c170260fb1c1a1790565b60ff169050808303600180821b0385821b179250505092915050565b60008083601f84011261572657600080fd5b50813567ffffffffffffffff81111561573e57600080fd5b60208301915083602082850101111561575657600080fd5b9250929050565b600080600083850360a081121561577357600080fd5b608081121561578157600080fd5b50839250608084013567ffffffffffffffff81111561579f57600080fd5b6157ab86828701615714565b9497909650939450505050565b600080604083850312156157cb57600080fd5b50508035926020909101359150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6020810160038310615844577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b60008060006060848603121561585f57600080fd5b505081359360208301359350604090920135919050565b6000815180845260005b8181101561589c57602081850181015186830182015201615880565b818111156158ae576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006126526020830184615876565b60006020828403121561590657600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff8116811461592f57600080fd5b50565b60006020828403121561594457600080fd5b81356150d08161590d565b8035801515811461595f57600080fd5b919050565b6000806000806080858703121561597a57600080fd5b8435935060208501359250604085013591506159986060860161594f565b905092959194509250565b6000602082840312156159b557600080fd5b81356fffffffffffffffffffffffffffffffff811681146150d057600080fd5b600080600080600080608087890312156159ee57600080fd5b863595506159fe6020880161594f565b9450604087013567ffffffffffffffff80821115615a1b57600080fd5b615a278a838b01615714565b90965094506060890135915080821115615a4057600080fd5b50615a4d89828a01615714565b979a9699509497509295939492505050565b63ffffffff841681528260208201526060604082015260006119006060830184615876565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600060808284031215615ac557600080fd5b6040516080810181811067ffffffffffffffff82111715615b0f577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115615bc157615bc1615b7f565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203615bf757615bf7615b7f565b5060010190565b600082821015615c1057615c10615b7f565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082615c5357615c53615c15565b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615c9057615c90615b7f565b500290565b600060208284031215615ca757600080fd5b81516150d08161590d565b600060208284031215615cc457600080fd5b5051919050565b600067ffffffffffffffff808316818516808303821115615cee57615cee615b7f565b01949350505050565b600067ffffffffffffffff80831681851681830481118215151615615d1e57615d1e615b7f565b02949350505050565b600067ffffffffffffffff83811690831681811015615d4857615d48615b7f565b039392505050565b60008060408385031215615d6357600080fd5b505080516020909101519092909150565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600084136000841385830485118282161615615db557615db5615b7f565b7f80000000000000000000000000000000000000000000000000000000000000006000871286820588128184161615615df057615df0615b7f565b60008712925087820587128484161615615e0c57615e0c615b7f565b87850587128184161615615e2257615e22615b7f565b505050929093029392505050565b600082615e3f57615e3f615c15565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f800000000000000000000000000000000000000000000000000000000000000083141615615e9357615e93615b7f565b500590565b600082615ea757615ea7615c15565b500690565b60006fffffffffffffffffffffffffffffffff83811690831681811015615d4857615d48615b7f565b60006fffffffffffffffffffffffffffffffff808316818516808303821115615cee57615cee615b7f565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b606081526000615f5d606083018789615f00565b8281036020840152615f70818688615f00565b9150508260408301529695505050505050565b600060ff821660ff841680821015615f9d57615f9d615b7f565b90039392505050565b600060ff831680615fb957615fb9615c15565b8060ff8416069150509291505056fea164736f6c634300080f000a"; + }
@@ -34991,7 +137854,7 @@ -